fix: исправить доступность артефактов документации
All checks were successful
CI/CD Pipeline / build (push) Successful in 16s
CI/CD Pipeline / version (push) Successful in 4s
CI/CD Pipeline / docker (push) Successful in 43s
CI/CD Pipeline / deploy (push) Successful in 7s

- добавлены HTML-подсказки для обнаружения llms.txt агентами
- обновлена карточка скачивания спецификации и архива
- добавлен раздел с порядком чтения спецификации
- исправлена генерация ссылок для single-file, Markdown и ZIP
- обновлены сгенерированные README.md и ARCHITECTURE.md
This commit is contained in:
2026-05-02 18:51:44 +03:00
parent 07542330b5
commit 1a1de7cad4
8 changed files with 143 additions and 10 deletions

View File

@@ -65,6 +65,35 @@ function fileRelToMdUrl(file: string): string {
return `${DOC_ROUTE_PREFIX}/${file}`;
}
const ARCHITECTURE_LINK_RE = /\]\((\/architecture(?:\/[^)\s#]*)?)(#[^)\s]*)?\)/g;
function architectureRouteToFileRel(route: string): string {
if (route.replace(/\/$/, "") === "/architecture") return "architecture/index.md";
return linkToFileRel(route);
}
function transformArchitectureLinks(
content: string,
toHref: (route: string, hash: string) => string,
): string {
return content.replace(ARCHITECTURE_LINK_RE, (_match, route: string, hash = "") => {
return `](${toHref(route, hash)})`;
});
}
function transformArchiveLinks(content: string): string {
return transformArchitectureLinks(content, (route, hash) => {
const fileName = path.basename(architectureRouteToFileRel(route));
return `./${fileName}${hash}`;
});
}
function transformSiteMarkdownLinks(content: string): string {
return transformArchitectureLinks(content, (route, hash) => {
return `${fileRelToMdUrl(architectureRouteToFileRel(route))}${hash}`;
});
}
function getAllFiles(): string[] {
return SIDEBAR.flatMap((g) => g.items.map((item) => linkToFileRel(item.link)));
}
@@ -75,6 +104,38 @@ const stripFrontmatter = (content: string) =>
const stripRulesLink = (content: string) =>
content.replace(/<!-- rules-link -->[\s\S]*?<!-- \/rules-link -->\n*/g, "");
function slugifyHeading(heading: string): string {
return heading
.trim()
.replace(/[`*_~[\]()]/g, "")
.toLowerCase()
.replace(/[^\p{L}\p{N}\s-]/gu, "")
.trim()
.replace(/\s+/g, "-");
}
function fileRelToSingleFileAnchor(file: string): string {
const filePath = path.join(SRC_DIR, file);
if (!fs.existsSync(filePath)) return slugifyHeading(path.basename(file, ".md"));
const raw = stripFrontmatter(fs.readFileSync(filePath, "utf8"));
const title = raw.match(/^#\s+(.+)$/m)?.[1];
return slugifyHeading(title ?? path.basename(file, ".md"));
}
function transformSingleFileLinks(content: string): string {
return transformArchitectureLinks(content, (route, hash) => {
if (hash) return hash;
return `#${fileRelToSingleFileAnchor(architectureRouteToFileRel(route))}`;
});
}
function transformReadmeLinks(content: string): string {
return transformArchitectureLinks(content, (route, hash) => {
return `docs/${architectureRouteToFileRel(route)}${hash}`;
});
}
const shiftHeadings = (content: string) => {
const lines = content.split("\n");
let inCodeBlock = false;
@@ -100,7 +161,8 @@ const buildArchitectureMarkdown = (routePrefix: string) => {
if (!content) continue;
const route = routePrefix + fileRelToRoute(file).replace(DOC_ROUTE_PREFIX, "");
const processed = file.endsWith("index.md") ? content : shiftHeadings(content);
const shifted = file.endsWith("index.md") ? content : shiftHeadings(content);
const processed = transformSingleFileLinks(shifted);
parts.push(`<!-- ${route} -->\n${processed}`);
}
@@ -151,9 +213,10 @@ function copyMarkdownFiles() {
const src = path.join(SRC_DIR, file);
if (!fs.existsSync(src)) continue;
const content = transformSiteMarkdownLinks(fs.readFileSync(src, "utf8"));
const dest = path.join(DOCS_PUBLIC_DIR, file);
fs.mkdirSync(path.dirname(dest), { recursive: true });
fs.copyFileSync(src, dest);
fs.writeFileSync(dest, content, "utf8");
copied++;
}
@@ -179,6 +242,7 @@ function buildZip() {
if (!fs.existsSync(src)) continue;
let content = fs.readFileSync(src, "utf8");
content = stripRulesLink(stripFrontmatter(content)).trim();
content = transformArchiveLinks(content);
const destName = path.basename(file);
fs.writeFileSync(path.join(tmpDir, destName), content, "utf8");
}
@@ -205,6 +269,7 @@ function buildReadme() {
let content = stripFrontmatter(fs.readFileSync(indexPath, "utf8"));
content = content.replace(/<!-- rules-link -->[\s\S]*?<!-- \/rules-link -->\n*/g, "");
content = transformReadmeLinks(content);
fs.writeFileSync("./README.md", content, "utf8");
console.log("README.md создан");
}