mirror of
https://gitee.com/docsifyjs/docsify.git
synced 2024-12-02 12:10:04 +08:00
fix: Unable to navigate on server without default index support (#1372)
* Fix: Cannot serve off `/.../index.html` Docsify must be hosted on a server that supports a default directory index (i.e. maps `/.../` -> `/.../index.html`). Some platforms do not support this, however. For example, HTML apps hosted on the popular game/software platform, Itch.io. This change supports hosting Docsify off an explicit path file, such as `/index.html`. It does this by: 1. Adding handling for paths like `index.html#/blah`, and 2. Normalising paths with fragments back to markdown paths For example, `http://example.org/index.html#/blah` would be mapped to `http://example.org/blah.md`. This fixes: https://github.com/docsifyjs/docsify/issues/427 * Add end-to-end test for index file hosting * Add code comments for explicit file changes * Add additional tests for index file hosting * Add additional tests for index file hosting * [wip] Attempt to switch tests to Jest * Add e2e test for new Jest test framework * Verify sidebar links use file hosting * Fix: endsWith() not supported for IE11 * Refactor: utility method moved to utility file * Fix IE11 error from use of String.includes() Co-authored-by: John Hildenbiddle <jhildenbiddle@users.noreply.github.com>
This commit is contained in:
parent
14ce7f3d86
commit
759ffac992
@ -1,13 +1,12 @@
|
||||
import { noop } from '../../util/core';
|
||||
import { on } from '../../util/dom';
|
||||
import { parseQuery, cleanPath, replaceSlug } from '../util';
|
||||
import { parseQuery, cleanPath, replaceSlug, endsWith } from '../util';
|
||||
import { History } from './base';
|
||||
|
||||
function replaceHash(path) {
|
||||
const i = location.href.indexOf('#');
|
||||
location.replace(location.href.slice(0, i >= 0 ? i : 0) + '#' + path);
|
||||
}
|
||||
|
||||
export class HashHistory extends History {
|
||||
constructor(config) {
|
||||
super(config);
|
||||
@ -18,7 +17,15 @@ export class HashHistory extends History {
|
||||
const path = window.location.pathname || '';
|
||||
const base = this.config.basePath;
|
||||
|
||||
return /^(\/|https?:)/g.test(base) ? base : cleanPath(path + '/' + base);
|
||||
// This handles the case where Docsify is served off an
|
||||
// explicit file path, i.e.`/base/index.html#/blah`. This
|
||||
// prevents the `/index.html` part of the URI from being
|
||||
// remove during routing.
|
||||
// See here: https://github.com/docsifyjs/docsify/pull/1372
|
||||
const basePath = endsWith(path, '.html')
|
||||
? path + '#/' + base
|
||||
: path + '/' + base;
|
||||
return /^(\/|https?:)/g.test(base) ? base : cleanPath(basePath);
|
||||
}
|
||||
|
||||
getCurrentPath() {
|
||||
|
@ -76,10 +76,44 @@ export const resolvePath = cached(path => {
|
||||
return '/' + resolved.join('/');
|
||||
});
|
||||
|
||||
/**
|
||||
* Normalises the URI path to handle the case where Docsify is
|
||||
* hosted off explicit files, i.e. /index.html. This function
|
||||
* eliminates any path segments that contain `#` fragments.
|
||||
*
|
||||
* This is used to map browser URIs to markdown file sources.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* http://example.org/base/index.html#/blah
|
||||
*
|
||||
* would be mapped to:
|
||||
*
|
||||
* http://example.org/base/blah.md.
|
||||
*
|
||||
* See here for more information:
|
||||
*
|
||||
* https://github.com/docsifyjs/docsify/pull/1372
|
||||
*
|
||||
* @param {string} path The URI path to normalise
|
||||
* @return {string} { path, query }
|
||||
*/
|
||||
|
||||
function normaliseFragment(path) {
|
||||
return path
|
||||
.split('/')
|
||||
.filter(p => p.indexOf('#') === -1)
|
||||
.join('/');
|
||||
}
|
||||
|
||||
export function getPath(...args) {
|
||||
return cleanPath(args.join('/'));
|
||||
return cleanPath(args.map(normaliseFragment).join('/'));
|
||||
}
|
||||
|
||||
export const replaceSlug = cached(path => {
|
||||
return path.replace('#', '?id=');
|
||||
});
|
||||
|
||||
export function endsWith(str, suffix) {
|
||||
return str.indexOf(suffix, str.length - suffix.length) !== -1;
|
||||
}
|
||||
|
28
test/e2e/index-file.test.js
Normal file
28
test/e2e/index-file.test.js
Normal file
@ -0,0 +1,28 @@
|
||||
const docsifyInit = require('../helpers/docsify-init');
|
||||
|
||||
describe(`Index file hosting`, function() {
|
||||
const sharedOptions = {
|
||||
config: {
|
||||
basePath: `${TEST_HOST}/docs/index.html#/`,
|
||||
},
|
||||
testURL: `${TEST_HOST}/docs/index.html#/`,
|
||||
};
|
||||
|
||||
test('should serve from index file', async () => {
|
||||
await docsifyInit(sharedOptions);
|
||||
|
||||
await expect(page).toHaveText(
|
||||
'#main',
|
||||
'A magical documentation site generator'
|
||||
);
|
||||
expect(page.url()).toMatch(/index\.html#\/$/);
|
||||
});
|
||||
|
||||
test('should use index file links in sidebar from index file hosting', async () => {
|
||||
await docsifyInit(sharedOptions);
|
||||
|
||||
await page.click('a[href="#/quickstart"]');
|
||||
await expect(page).toHaveText('#main', 'Quick start');
|
||||
expect(page.url()).toMatch(/index\.html#\/quickstart$/);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user