diff options
Diffstat (limited to 'doc/docs/.vuepress/theme/util/index.js')
-rw-r--r-- | doc/docs/.vuepress/theme/util/index.js | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/doc/docs/.vuepress/theme/util/index.js b/doc/docs/.vuepress/theme/util/index.js new file mode 100644 index 0000000..92fcd3b --- /dev/null +++ b/doc/docs/.vuepress/theme/util/index.js | |||
@@ -0,0 +1,244 @@ | |||
1 | export const hashRE = /#.*$/ | ||
2 | export const extRE = /\.(md|html)$/ | ||
3 | export const endingSlashRE = /\/$/ | ||
4 | export const outboundRE = /^[a-z]+:/i | ||
5 | |||
6 | export function normalize (path) { | ||
7 | return decodeURI(path) | ||
8 | .replace(hashRE, '') | ||
9 | .replace(extRE, '') | ||
10 | } | ||
11 | |||
12 | export function getHash (path) { | ||
13 | const match = path.match(hashRE) | ||
14 | if (match) { | ||
15 | return match[0] | ||
16 | } | ||
17 | } | ||
18 | |||
19 | export function isExternal (path) { | ||
20 | return outboundRE.test(path) | ||
21 | } | ||
22 | |||
23 | export function isMailto (path) { | ||
24 | return /^mailto:/.test(path) | ||
25 | } | ||
26 | |||
27 | export function isTel (path) { | ||
28 | return /^tel:/.test(path) | ||
29 | } | ||
30 | |||
31 | export function ensureExt (path) { | ||
32 | if (isExternal(path)) { | ||
33 | return path | ||
34 | } | ||
35 | const hashMatch = path.match(hashRE) | ||
36 | const hash = hashMatch ? hashMatch[0] : '' | ||
37 | const normalized = normalize(path) | ||
38 | |||
39 | if (endingSlashRE.test(normalized)) { | ||
40 | return path | ||
41 | } | ||
42 | return normalized + '.html' + hash | ||
43 | } | ||
44 | |||
45 | export function isActive (route, path) { | ||
46 | const routeHash = decodeURIComponent(route.hash) | ||
47 | const linkHash = getHash(path) | ||
48 | if (linkHash && routeHash !== linkHash) { | ||
49 | return false | ||
50 | } | ||
51 | const routePath = normalize(route.path) | ||
52 | const pagePath = normalize(path) | ||
53 | return routePath === pagePath | ||
54 | } | ||
55 | |||
56 | export function resolvePage (pages, rawPath, base) { | ||
57 | if (isExternal(rawPath)) { | ||
58 | return { | ||
59 | type: 'external', | ||
60 | path: rawPath | ||
61 | } | ||
62 | } | ||
63 | if (base) { | ||
64 | rawPath = resolvePath(rawPath, base) | ||
65 | } | ||
66 | const path = normalize(rawPath) | ||
67 | for (let i = 0; i < pages.length; i++) { | ||
68 | if (normalize(pages[i].regularPath) === path) { | ||
69 | return Object.assign({}, pages[i], { | ||
70 | type: 'page', | ||
71 | path: ensureExt(pages[i].path) | ||
72 | }) | ||
73 | } | ||
74 | } | ||
75 | console.error(`[vuepress] No matching page found for sidebar item "${rawPath}"`) | ||
76 | return {} | ||
77 | } | ||
78 | |||
79 | function resolvePath (relative, base, append) { | ||
80 | const firstChar = relative.charAt(0) | ||
81 | if (firstChar === '/') { | ||
82 | return relative | ||
83 | } | ||
84 | |||
85 | if (firstChar === '?' || firstChar === '#') { | ||
86 | return base + relative | ||
87 | } | ||
88 | |||
89 | const stack = base.split('/') | ||
90 | |||
91 | // remove trailing segment if: | ||
92 | // - not appending | ||
93 | // - appending to trailing slash (last segment is empty) | ||
94 | if (!append || !stack[stack.length - 1]) { | ||
95 | stack.pop() | ||
96 | } | ||
97 | |||
98 | // resolve relative path | ||
99 | const segments = relative.replace(/^\//, '').split('/') | ||
100 | for (let i = 0; i < segments.length; i++) { | ||
101 | const segment = segments[i] | ||
102 | if (segment === '..') { | ||
103 | stack.pop() | ||
104 | } else if (segment !== '.') { | ||
105 | stack.push(segment) | ||
106 | } | ||
107 | } | ||
108 | |||
109 | // ensure leading slash | ||
110 | if (stack[0] !== '') { | ||
111 | stack.unshift('') | ||
112 | } | ||
113 | |||
114 | return stack.join('/') | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * @param { Page } page | ||
119 | * @param { string } regularPath | ||
120 | * @param { SiteData } site | ||
121 | * @param { string } localePath | ||
122 | * @returns { SidebarGroup } | ||
123 | */ | ||
124 | export function resolveSidebarItems (page, regularPath, site, localePath) { | ||
125 | const { pages, themeConfig } = site | ||
126 | |||
127 | const localeConfig = localePath && themeConfig.locales | ||
128 | ? themeConfig.locales[localePath] || themeConfig | ||
129 | : themeConfig | ||
130 | |||
131 | const pageSidebarConfig = page.frontmatter.sidebar || localeConfig.sidebar || themeConfig.sidebar | ||
132 | if (pageSidebarConfig === 'auto') { | ||
133 | return resolveHeaders(page) | ||
134 | } | ||
135 | |||
136 | const sidebarConfig = localeConfig.sidebar || themeConfig.sidebar | ||
137 | if (!sidebarConfig) { | ||
138 | return [] | ||
139 | } else { | ||
140 | const { base, config } = resolveMatchingConfig(regularPath, sidebarConfig) | ||
141 | if (config === 'auto') { | ||
142 | return resolveHeaders(page) | ||
143 | } | ||
144 | return config | ||
145 | ? config.map(item => resolveItem(item, pages, base)) | ||
146 | : [] | ||
147 | } | ||
148 | } | ||
149 | |||
150 | /** | ||
151 | * @param { Page } page | ||
152 | * @returns { SidebarGroup } | ||
153 | */ | ||
154 | function resolveHeaders (page) { | ||
155 | const headers = groupHeaders(page.headers || []) | ||
156 | return [{ | ||
157 | type: 'group', | ||
158 | collapsable: false, | ||
159 | title: page.title, | ||
160 | path: null, | ||
161 | children: headers.map(h => ({ | ||
162 | type: 'auto', | ||
163 | title: h.title, | ||
164 | basePath: page.path, | ||
165 | path: page.path + '#' + h.slug, | ||
166 | children: h.children || [] | ||
167 | })) | ||
168 | }] | ||
169 | } | ||
170 | |||
171 | export function groupHeaders (headers) { | ||
172 | // group h3s under h2 | ||
173 | headers = headers.map(h => Object.assign({}, h)) | ||
174 | let lastH2 | ||
175 | headers.forEach(h => { | ||
176 | if (h.level === 2) { | ||
177 | lastH2 = h | ||
178 | } else if (lastH2) { | ||
179 | (lastH2.children || (lastH2.children = [])).push(h) | ||
180 | } | ||
181 | }) | ||
182 | return headers.filter(h => h.level === 2) | ||
183 | } | ||
184 | |||
185 | export function resolveNavLinkItem (linkItem) { | ||
186 | return Object.assign(linkItem, { | ||
187 | type: linkItem.items && linkItem.items.length ? 'links' : 'link' | ||
188 | }) | ||
189 | } | ||
190 | |||
191 | /** | ||
192 | * @param { Route } route | ||
193 | * @param { Array<string|string[]> | Array<SidebarGroup> | [link: string]: SidebarConfig } config | ||
194 | * @returns { base: string, config: SidebarConfig } | ||
195 | */ | ||
196 | export function resolveMatchingConfig (regularPath, config) { | ||
197 | if (Array.isArray(config)) { | ||
198 | return { | ||
199 | base: '/', | ||
200 | config: config | ||
201 | } | ||
202 | } | ||
203 | for (const base in config) { | ||
204 | if (ensureEndingSlash(regularPath).indexOf(encodeURI(base)) === 0) { | ||
205 | return { | ||
206 | base, | ||
207 | config: config[base] | ||
208 | } | ||
209 | } | ||
210 | } | ||
211 | return {} | ||
212 | } | ||
213 | |||
214 | function ensureEndingSlash (path) { | ||
215 | return /(\.html|\/)$/.test(path) | ||
216 | ? path | ||
217 | : path + '/' | ||
218 | } | ||
219 | |||
220 | function resolveItem (item, pages, base, groupDepth = 1) { | ||
221 | if (typeof item === 'string') { | ||
222 | return resolvePage(pages, item, base) | ||
223 | } else if (Array.isArray(item)) { | ||
224 | return Object.assign(resolvePage(pages, item[0], base), { | ||
225 | title: item[1] | ||
226 | }) | ||
227 | } else { | ||
228 | const children = item.children || [] | ||
229 | if (children.length === 0 && item.path) { | ||
230 | return Object.assign(resolvePage(pages, item.path, base), { | ||
231 | title: item.title | ||
232 | }) | ||
233 | } | ||
234 | return { | ||
235 | type: 'group', | ||
236 | path: item.path, | ||
237 | title: item.title, | ||
238 | sidebarDepth: item.sidebarDepth, | ||
239 | initialOpenGroupIndex: item.initialOpenGroupIndex, | ||
240 | children: children.map(child => resolveItem(child, pages, base, groupDepth + 1)), | ||
241 | collapsable: item.collapsable !== false | ||
242 | } | ||
243 | } | ||
244 | } | ||