mirror of
https://github.com/directus/directus.git
synced 2026-02-08 11:54:58 -05:00
* Allow formatted value display for numbers * Move the docs website into monorepo * Fix build * Tweak docs build setup * Fix tips, pull in images * Add syntax highlighting to docs * Restructure nav, add divider * Fix tips formatting * Add prettier config * Add editorconfig
244 lines
5.5 KiB
JavaScript
244 lines
5.5 KiB
JavaScript
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 (item.type === 'divider') {
|
|
return { type: 'divider', path: '' };
|
|
}
|
|
|
|
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,
|
|
};
|
|
}
|
|
}
|