aboutsummaryrefslogtreecommitdiff
path: root/doc/docs/.vuepress/theme/util/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'doc/docs/.vuepress/theme/util/index.js')
-rw-r--r--doc/docs/.vuepress/theme/util/index.js244
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 @@
1export const hashRE = /#.*$/
2export const extRE = /\.(md|html)$/
3export const endingSlashRE = /\/$/
4export const outboundRE = /^[a-z]+:/i
5
6export function normalize (path) {
7 return decodeURI(path)
8 .replace(hashRE, '')
9 .replace(extRE, '')
10}
11
12export function getHash (path) {
13 const match = path.match(hashRE)
14 if (match) {
15 return match[0]
16 }
17}
18
19export function isExternal (path) {
20 return outboundRE.test(path)
21}
22
23export function isMailto (path) {
24 return /^mailto:/.test(path)
25}
26
27export function isTel (path) {
28 return /^tel:/.test(path)
29}
30
31export 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
45export 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
56export 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
79function 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 */
124export 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 */
154function 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
171export 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
185export 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 */
196export 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
214function ensureEndingSlash (path) {
215 return /(\.html|\/)$/.test(path)
216 ? path
217 : path + '/'
218}
219
220function 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}