Repository navigation
Expand file tree
/
Copy pathhash.js
More file actions
131 lines (109 loc) · 3.6 KB
/
Copy pathhash.js
File metadata and controls
131 lines (109 loc) · 3.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import { isExternal, noop } from '../../util/core.js';
import { on } from '../../util/dom.js';
import {
cleanPath,
getClickedLink,
getSidebarNavigationTarget,
isCurrentContextNavigation,
parseQuery,
replaceSlug,
} from '../util.js';
import { History } from './base.js';
function replaceHash(path) {
const i = location.href.indexOf('#');
location.replace(location.href.slice(0, i >= 0 ? i : 0) + '#' + path);
}
export class HashHistory extends History {
mode = 'hash';
getBasePath() {
const path = window.location.pathname || '';
const base = this.config.basePath;
// 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 = path.endsWith('.html')
? path + '#/' + base
: path + '/' + base;
return /^(\/|https?:)/g.test(base) ? base : cleanPath(basePath);
}
getCurrentPath() {
// We can't use location.hash here because it's not
// consistent across browsers - Firefox will pre-decode it!
const href = location.href;
const index = href.indexOf('#');
return index === -1 ? '' : href.slice(index + 1);
}
/** @param {(params: {source: any, focusTarget?: import('../util.js').SidebarNavigationTarget}) => void} [cb] */
onchange(cb = noop) {
// The hashchange event does not tell us if it originated from
// a clicked link or by moving back/forward in the history;
// therefore we set a `navigating` flag when a link is clicked
// to be able to tell these two scenarios apart
let navigating = false;
let navigatingFocusTarget;
on('click', e => {
const el = getClickedLink(e);
if (el && isCurrentContextNavigation(e, el) && !isExternal(el.href)) {
navigating = true;
navigatingFocusTarget = getSidebarNavigationTarget(el);
// Do not compare hash containing these classes.
if (el.matches('.app-name-link, .page-link')) {
if (el.hash === location.hash) {
navigating = false;
navigatingFocusTarget = undefined;
}
return;
}
if (el.hash === location.hash) {
cb({ focusTarget: navigatingFocusTarget, source: 'navigate' });
navigating = false;
navigatingFocusTarget = undefined;
}
}
});
on('hashchange', () => {
const source = navigating ? 'navigate' : 'history';
const focusTarget = navigating ? navigatingFocusTarget : undefined;
navigating = false;
navigatingFocusTarget = undefined;
cb({ focusTarget, source });
});
}
normalize() {
let path = this.getCurrentPath();
path = replaceSlug(path);
if (path.charAt(0) === '/') {
return replaceHash(path);
}
replaceHash('/' + path);
}
/**
* Parse the url
* @param {string} path URL to be parsed
* @return {import('../index.js').Route} { path, query, file, response }
*/
parse(path = location.href) {
let query = '';
const hashIndex = path.indexOf('#');
if (hashIndex >= 0) {
path = path.slice(hashIndex + 1);
}
const queryIndex = path.indexOf('?');
if (queryIndex >= 0) {
query = path.slice(queryIndex + 1);
path = path.slice(0, queryIndex);
}
return {
path,
file: this.getFile(path, true),
query: parseQuery(query),
response: {},
};
}
toURL(path, params, currentRoute) {
return '#' + super.toURL(path, params, currentRoute);
}
}
/** @typedef {any} TODO */