UNPKG

ajv

Version:
240 lines (213 loc) 5.83 kB
export const hashRE = /#.*$/ export const extRE = /\.(md|html)$/ export const endingSlashRE = /\/$/ export const outboundRE = /^[a-z]+:/i export function normalize(path) { return decodeURI(path).replace(hashRE, "").replace(extRE, "") } export function getHash(path) { const match = path.match(hashRE) if (match) { return match[0] } } export function isExternal(path) { return outboundRE.test(path) } export function isMailto(path) { return /^mailto:/.test(path) } export function isTel(path) { return /^tel:/.test(path) } export function ensureExt(path) { if (isExternal(path)) { return path } const hashMatch = path.match(hashRE) const hash = hashMatch ? hashMatch[0] : "" const normalized = normalize(path) if (endingSlashRE.test(normalized)) { return path } return normalized + ".html" + hash } export function isActive(route, path) { const routeHash = decodeURIComponent(route.hash) const linkHash = getHash(path) if (linkHash && routeHash !== linkHash) { return false } const routePath = normalize(route.path) const pagePath = normalize(path) return routePath === pagePath } export function resolvePage(pages, rawPath, base) { if (isExternal(rawPath)) { return { type: "external", path: rawPath, } } if (base) { rawPath = resolvePath(rawPath, base) } const path = normalize(rawPath) for (let i = 0; i < pages.length; i++) { if (normalize(pages[i].regularPath) === path) { return Object.assign({}, pages[i], { type: "page", path: ensureExt(pages[i].path), }) } } console.error(`[vuepress] No matching page found for sidebar item "${rawPath}"`) return {} } function resolvePath(relative, base, append) { const firstChar = relative.charAt(0) if (firstChar === "/") { return relative } if (firstChar === "?" || firstChar === "#") { return base + relative } const stack = base.split("/") // remove trailing segment if: // - not appending // - appending to trailing slash (last segment is empty) if (!append || !stack[stack.length - 1]) { stack.pop() } // resolve relative path const segments = relative.replace(/^\//, "").split("/") for (let i = 0; i < segments.length; i++) { const segment = segments[i] if (segment === "..") { stack.pop() } else if (segment !== ".") { stack.push(segment) } } // ensure leading slash if (stack[0] !== "") { stack.unshift("") } return stack.join("/") } /** * @param { Page } page * @param { string } regularPath * @param { SiteData } site * @param { string } localePath * @returns { SidebarGroup } */ export function resolveSidebarItems(page, regularPath, site, localePath) { const {pages, themeConfig} = site const localeConfig = localePath && themeConfig.locales ? themeConfig.locales[localePath] || themeConfig : themeConfig const pageSidebarConfig = page.frontmatter.sidebar || localeConfig.sidebar || themeConfig.sidebar if (pageSidebarConfig === "auto") { return resolveHeaders(page) } const sidebarConfig = localeConfig.sidebar || themeConfig.sidebar if (!sidebarConfig) { return [] } else { const {base, config} = resolveMatchingConfig(regularPath, sidebarConfig) if (config === "auto") { return resolveHeaders(page) } return config ? config.map((item) => resolveItem(item, pages, base)) : [] } } /** * @param { Page } page * @returns { SidebarGroup } */ function resolveHeaders(page) { const headers = groupHeaders(page.headers || []) return [ { type: "group", collapsable: false, title: page.title, path: null, children: headers.map((h) => ({ type: "auto", title: h.title, basePath: page.path, path: page.path + "#" + h.slug, children: h.children || [], })), }, ] } export function groupHeaders(headers) { // group h3s under h2 headers = headers.map((h) => Object.assign({}, h)) let lastH2 headers.forEach((h) => { if (h.level === 2) { lastH2 = h } else if (lastH2) { ;(lastH2.children || (lastH2.children = [])).push(h) } }) return headers.filter((h) => h.level === 2) } export function resolveNavLinkItem(linkItem) { return Object.assign(linkItem, { type: linkItem.items && linkItem.items.length ? "links" : "link", }) } /** * @param { Route } route * @param { Array<string|string[]> | Array<SidebarGroup> | [link: string]: SidebarConfig } config * @returns { base: string, config: SidebarConfig } */ export function resolveMatchingConfig(regularPath, config) { if (Array.isArray(config)) { return { base: "/", config: config, } } for (const base in config) { if (ensureEndingSlash(regularPath).indexOf(encodeURI(base)) === 0) { return { base, config: config[base], } } } return {} } function ensureEndingSlash(path) { return /(\.html|\/)$/.test(path) ? path : path + "/" } function resolveItem(item, pages, base, groupDepth = 1) { if (typeof item === "string") { return resolvePage(pages, item, base) } else if (Array.isArray(item)) { return Object.assign(resolvePage(pages, item[0], base), { title: item[1], }) } else { const children = item.children || [] if (children.length === 0 && item.path) { return Object.assign(resolvePage(pages, item.path, base), { title: item.title, }) } return { type: "group", path: item.path, title: item.title, sidebarDepth: item.sidebarDepth, initialOpenGroupIndex: item.initialOpenGroupIndex, children: children.map((child) => resolveItem(child, pages, base, groupDepth + 1)), collapsable: item.collapsable !== false, } } }