/
githubmirror
/
angular
Обзор
Документация
Войти
/
githubmirror
/
angular
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
adev/src/context/llms.mts
142 строки
5 KB
Matthieu Riegler
docs(docs-infra): generate llms-full.txt at build time (#61864)
08 июл 2025, 21:27
08 июл 2025, 21:27
a1f8cc4
Код
Авторство
О чём код?
/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.dev/license */ // The purpose of this script is to generate a llms-full.txt // Run with `node adev/scripts/shared/llms.mjs` to generate llms-full.txt from the list in llms-list.md //tslint:disable:no-console import {readFile, writeFile} from 'fs/promises'; import {resolve, dirname} from 'path'; const INPUT_MD_FILENAME = 'adev/src/context/llms-list.md'; const OUTPUT_FILENAME = 'adev/src/context/llms-full.txt'; function postProcessOutputContent(content: string) { // Helper to map custom languages to standard Markdown languages const mapLanguage = (lang: string) => { if (!lang) return ''; // For code blocks without a specified language const lowerLang = lang.trim().toLowerCase(); if (lowerLang === 'angular-ts') return 'typescript'; if (lowerLang === 'angular-html') return 'html'; return lowerLang; // Use as is for other languages like shell, etc. }; // Process docs-code-multifile and their inner docs-code elements content = content.replace( /<docs-code-multifile>([\s\S]*?)<\/docs-code-multifile>/gs, (match, innerHTML) => { let multifileResult = ''; // Regex for <docs-code> within <docs-code-multifile>, expecting 'header' and optional 'language' const codeRegex = /<docs-code\s+header="([^"]+)"(?:\s+language="([^"]*)")?[^>]*>([\s\S]*?)<\/docs-code>/gs; let codeMatch; while ((codeMatch = codeRegex.exec(innerHTML)) !== null) { const header = codeMatch[1].trim(); const langAttr = codeMatch[2]; // Language attribute might be undefined const language = mapLanguage(langAttr); let code = codeMatch[3].trim(); // Note: If code content includes HTML entities like <, they would need unescaping here. // e.g., code = code.replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&'); multifileResult += `\`\`\`${language}\n// ${header}\n${code}\n\`\`\`\n`; } return multifileResult; }, ); // Process standalone docs-code elements content = content.replace( /<docs-code(?:\s+language="([^"]*)")?[^>]*>([\s\S]*?)<\/docs-code>/gs, (match, langAttr, codeContent) => { const language = mapLanguage(langAttr); let code = codeContent.trim(); // Note: HTML entity unescaping might be needed here as well. return `\`\`\`${language}\n${code}\n\`\`\`\n`; }, ); // Process code block languages content = content.replace(/```([\w-]+)\s*/gs, (match, lang, code) => { const mappedLang = mapLanguage(lang); // lang can be undefined if no language was specified return `\`\`\`${mappedLang}\n`; }); // Remove docs-decorative-header elements content = content.replace( /<docs-decorative-header[^>]*>[\s\S]*?<\/docs-decorative-header>/gs, '', ); // Remove docs-card elements content = content.replace(/<docs-card\b[^>]*>[\s\S]*?<\/docs-card>/gi, ''); // remove docs-pill-row elements content = content.replace(/<docs-pill-row\b[^>]*>[\s\S]*?<\/docs-pill-row>/gi, ''); // Remove docs-callout tags, keeping the content within them content = content.replace(/<docs-callout[^>]*>([\s\S]*?)<\/docs-callout>/gis, '$1'); // Remove docs-card-container tags, keeping the content within them content = content.replace(/<docs-card-container>/g, ''); content = content.replace(/<\/docs-card-container>/g, ''); return content; } async function main() { const inputFilePath = resolve(process.cwd(), INPUT_MD_FILENAME); const baseDirForIncludes = dirname(inputFilePath); console.log(`Starting processing of: ${inputFilePath}`); let mainFileContent: string; try { mainFileContent = await readFile(inputFilePath, 'utf-8'); } catch (error: unknown) { console.error(`Error: Failed to read input file "${inputFilePath}".`); console.error((error as Error).message); process.exit(1); // Exit with error code } let processedContent: string = mainFileContent; const matches = [...mainFileContent.matchAll(/(.*\.md)/g)]; console.log(`Found ${matches.length} files`); let resultString = ''; for (const match of matches) { const filePath = match[0]; const absolutePathToIncludeFile = resolve(filePath); try { console.log(` Including content from: ${absolutePathToIncludeFile}`); const includedFileContent = await readFile(absolutePathToIncludeFile, 'utf-8'); const processedFile = postProcessOutputContent(includedFileContent); resultString += processedFile; // Append the content of the included file } catch (fileReadError: any) { console.warn( ` Warning: Could not read file "${absolutePathToIncludeFile}" - ${fileReadError.message}`, ); } } // Basic cleanup of blank lines processedContent = resultString.replace(/(?:\s*\n){3,}/g, '\n'); const outputFilePath = resolve(process.cwd(), OUTPUT_FILENAME); try { await writeFile(outputFilePath, processedContent, 'utf-8'); console.log(`Successfully generated combined file: ${outputFilePath}`); } catch (error: unknown) { console.error(`Error: Failed to write output file "${outputFilePath}".`); console.error((error as Error).message); process.exit(1); // Exit with error code } } main();