feat: добавить документацию NextJS Style Guide
- добавлен отдельный VitePress-сайт для NextJS Style Guide - удалены дубли SLM-канонов из style-guide - обновлены ссылки, сборочные скрипты, CI, Docker и README - разблокирована карточка NextJS Style Guide на главной
This commit is contained in:
@@ -7,11 +7,17 @@ type Page = {
|
||||
target: string;
|
||||
};
|
||||
|
||||
type DocsConfig = {
|
||||
mounts: Page[];
|
||||
type RouteRewrite = {
|
||||
from: string;
|
||||
to: string;
|
||||
};
|
||||
|
||||
const MD_LINK_RE = /\]\((?!#|[a-z][a-z0-9+.-]*:)([^)\s]+\.md)(#[^)]*)?\)/gi;
|
||||
type DocsConfig = {
|
||||
mounts: Page[];
|
||||
routeRewrites?: RouteRewrite[];
|
||||
};
|
||||
|
||||
const MD_LINK_RE = /\]\((?!#|[a-z][a-z0-9+.-]*:|\/\/)([^)\s]+)(#[^)]*)?\)/gi;
|
||||
|
||||
const siteName = process.argv[2];
|
||||
|
||||
@@ -33,6 +39,7 @@ const config = (await import(pathToFileURL(configPath).href)) as DocsConfig;
|
||||
const targetBySource = new Map(
|
||||
config.mounts.map((page) => [normalizePath(page.source), normalizePath(page.target)]),
|
||||
);
|
||||
const routeRewrites = [...(config.routeRewrites ?? [])].sort((a, b) => b.from.length - a.from.length);
|
||||
|
||||
function normalizePath(value: string) {
|
||||
return value.split(path.sep).join('/').replace(/^\.\//, '');
|
||||
@@ -47,17 +54,71 @@ function formatRelativeMarkdownPath(fromTarget: string, toTarget: string) {
|
||||
return relative.startsWith('.') ? relative : `./${relative}`;
|
||||
}
|
||||
|
||||
function applyRouteRewrites(route: string) {
|
||||
for (const rewrite of routeRewrites) {
|
||||
if (route === rewrite.from || route.startsWith(`${rewrite.from}/`) || route.startsWith(`${rewrite.from}#`)) {
|
||||
return `${rewrite.to}${route.slice(rewrite.from.length)}`;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function formatDocsRoute(route: string) {
|
||||
const rewritten = applyRouteRewrites(route);
|
||||
if (rewritten) return rewritten;
|
||||
|
||||
if (route === '/docs') return '/';
|
||||
if (route.startsWith('/docs/')) return route.slice('/docs'.length);
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function formatRelativeRoute(hrefPath: string, sourceDir: string) {
|
||||
const sourcePath = normalizePath(path.posix.normalize(path.posix.join(sourceDir, hrefPath)));
|
||||
|
||||
if (sourcePath.startsWith('style-guide/')) {
|
||||
const route = `/docs/${sourcePath.slice('style-guide/'.length)}`;
|
||||
|
||||
return applyRouteRewrites(route);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function transformMarkdownLinks(content: string, page: Page) {
|
||||
const sourceDir = path.posix.dirname(normalizePath(page.source));
|
||||
|
||||
return content.replace(MD_LINK_RE, (match, href: string, hash = '') => {
|
||||
const [hrefPath, query = ''] = href.split('?');
|
||||
const queryPart = query ? `?${query}` : '';
|
||||
|
||||
if (hrefPath.startsWith('/')) {
|
||||
const route = formatDocsRoute(hrefPath);
|
||||
|
||||
if (route) return `](${route}${queryPart}${hash})`;
|
||||
|
||||
const rewritten = applyRouteRewrites(hrefPath);
|
||||
|
||||
if (rewritten) return `](${rewritten}${queryPart}${hash})`;
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
if (!hrefPath.endsWith('.md')) {
|
||||
const route = formatRelativeRoute(hrefPath, sourceDir);
|
||||
|
||||
if (route) return `](${route}${queryPart}${hash})`;
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
const sourcePath = normalizePath(path.posix.normalize(path.posix.join(sourceDir, hrefPath)));
|
||||
const target = targetBySource.get(sourcePath);
|
||||
|
||||
if (!target) return match;
|
||||
|
||||
const nextHref = formatRelativeMarkdownPath(page.target, `${target}${query ? `?${query}` : ''}`);
|
||||
const nextHref = formatRelativeMarkdownPath(page.target, `${target}${queryPart}`);
|
||||
|
||||
return `](${nextHref}${hash})`;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user