|
|
@@ -1,7 +1,10 @@
|
|
|
const fs = require('fs');
|
|
|
const path = require('path');
|
|
|
+const { globSync } = require('glob');
|
|
|
|
|
|
const distDir = path.join(__dirname, '../docs/.vitepress/dist');
|
|
|
+const docsDir = path.join(__dirname, '../docs');
|
|
|
+const codesSrcDir = path.join(__dirname, '../docs/codes');
|
|
|
const files = ['llms.txt', 'llms-full.txt'];
|
|
|
|
|
|
function cleanTitle(title) {
|
|
|
@@ -19,6 +22,52 @@ function cleanTitle(title) {
|
|
|
return cleaned.trim();
|
|
|
}
|
|
|
|
|
|
+function getProjectCodes(rootFilesDir) {
|
|
|
+ const fullProjectDir = path.join(codesSrcDir, rootFilesDir);
|
|
|
+ if (!fs.existsSync(fullProjectDir)) return '';
|
|
|
+
|
|
|
+ const projectFiles = globSync('**/*.*', {
|
|
|
+ cwd: fullProjectDir,
|
|
|
+ ignore: [
|
|
|
+ '**/build/**',
|
|
|
+ '**/.*',
|
|
|
+ '**/*.o',
|
|
|
+ '**/*.obj',
|
|
|
+ '**/*.exe',
|
|
|
+ '**/*.bin',
|
|
|
+ '**/test.lua',
|
|
|
+ '**/*.cache/**',
|
|
|
+ '**/*.gcm',
|
|
|
+ '**/compile_commands.json',
|
|
|
+ '**/compile_command.json'
|
|
|
+ ],
|
|
|
+ nodir: true
|
|
|
+ });
|
|
|
+
|
|
|
+ if (projectFiles.length === 0) return '';
|
|
|
+
|
|
|
+ let output = `\n\n### Code Examples (${rootFilesDir})\n`;
|
|
|
+
|
|
|
+ // Sort files
|
|
|
+ projectFiles.sort((a, b) => {
|
|
|
+ if (a === 'xmake.lua') return -1;
|
|
|
+ if (b === 'xmake.lua') return 1;
|
|
|
+ return a.localeCompare(b);
|
|
|
+ });
|
|
|
+
|
|
|
+ for (const file of projectFiles) {
|
|
|
+ const fullPath = path.join(fullProjectDir, file);
|
|
|
+ const content = fs.readFileSync(fullPath, 'utf-8');
|
|
|
+ const ext = path.extname(file).toLowerCase().substring(1);
|
|
|
+ const lang = (file.endsWith('xmake.lua') || ext === 'lua') ? 'lua' :
|
|
|
+ (['c', 'cpp', 'h', 'hpp', 'm', 'mm'].includes(ext) ? 'cpp' :
|
|
|
+ (ext || 'text'));
|
|
|
+
|
|
|
+ output += `\n#### ${file}\n\n\`\`\`${lang}\n${content}\n\`\`\`\n`;
|
|
|
+ }
|
|
|
+ return output;
|
|
|
+}
|
|
|
+
|
|
|
function processFile(filename) {
|
|
|
const filePath = path.join(distDir, filename);
|
|
|
if (!fs.existsSync(filePath)) {
|
|
|
@@ -28,6 +77,53 @@ function processFile(filename) {
|
|
|
|
|
|
let content = fs.readFileSync(filePath, 'utf8');
|
|
|
|
|
|
+ // Inject FileExplorer codes
|
|
|
+ const parts = content.split(/^---\r?\nurl: (.*?)\r?\n---/gm);
|
|
|
+ if (parts.length > 1) {
|
|
|
+ let newContent = parts[0];
|
|
|
+ for (let i = 1; i < parts.length; i += 2) {
|
|
|
+ const url = parts[i];
|
|
|
+ let sectionContent = parts[i+1];
|
|
|
+
|
|
|
+ const relPath = url.startsWith('/') ? url.substring(1) : url;
|
|
|
+ // Remove .html if present and add .md, but usually url in llms.txt keeps .md or original
|
|
|
+ // The Read result showed /zh/guide/.../install-and-uninstall.md
|
|
|
+ // So we assume it maps to docs/...
|
|
|
+
|
|
|
+ // If url ends with .html, replace with .md
|
|
|
+ let mdRelPath = relPath;
|
|
|
+ if (mdRelPath.endsWith('.html')) {
|
|
|
+ mdRelPath = mdRelPath.replace(/\.html$/, '.md');
|
|
|
+ }
|
|
|
+
|
|
|
+ const mdPath = path.join(docsDir, mdRelPath);
|
|
|
+
|
|
|
+ if (fs.existsSync(mdPath)) {
|
|
|
+ const mdContent = fs.readFileSync(mdPath, 'utf8');
|
|
|
+ // Find FileExplorer tags
|
|
|
+ const regex = /<FileExplorer\s+rootFilesDir="([^"]+)"\s*\/>/g;
|
|
|
+ let match;
|
|
|
+ const codesToAdd = [];
|
|
|
+ while ((match = regex.exec(mdContent)) !== null) {
|
|
|
+ const rootFilesDir = match[1];
|
|
|
+ const codes = getProjectCodes(rootFilesDir);
|
|
|
+ if (codes) {
|
|
|
+ codesToAdd.push(codes);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (codesToAdd.length > 0) {
|
|
|
+ sectionContent += codesToAdd.join('\n');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ newContent += `---
|
|
|
+url: ${url}
|
|
|
+---${sectionContent}`;
|
|
|
+ }
|
|
|
+ content = newContent;
|
|
|
+ }
|
|
|
+
|
|
|
// Fix TOC titles in format: - [Title](link)
|
|
|
// We match the line starting with - [
|
|
|
content = content.replace(/^-\s+\[(.*?)\]\((.*?)\)/gm, (match, title, link) => {
|
|
|
@@ -36,23 +132,8 @@ function processFile(filename) {
|
|
|
});
|
|
|
|
|
|
// Also fix titles in the content (for llms-full.txt)
|
|
|
- // Titles usually start with #
|
|
|
- // e.g. # 安装卸载 {#install-and-uninstall}
|
|
|
content = content.replace(/^(#+)\s+(.*?)(\s+\{#[^}]+\})?\s*$/gm, (match, hashes, title, anchor) => {
|
|
|
- // If it's a header, we also want to clean the title part
|
|
|
- // But wait, the anchor in header is actually useful for linking?
|
|
|
- // In llms-full.txt, we might want to keep the header as is, or maybe clean it too?
|
|
|
- // The user complaint was "garbled", which likely refers to the messy text.
|
|
|
- // For headers in full text, keeping anchor is fine as it defines the ID.
|
|
|
- // But looking at llms-full.txt content:
|
|
|
- // # 安装卸载 {#install-and-uninstall}
|
|
|
- // This is standard markdown header with ID. It is NOT garbled.
|
|
|
-
|
|
|
- // However, the TOC in llms.txt has:
|
|
|
- // - [安装卸载 {#install-and-uninstall}](/zh/guide/basic-commands/install-and-uninstall.md)
|
|
|
- // This looks messy in a list of links.
|
|
|
-
|
|
|
- return match; // Don't change headers in content for now, unless requested.
|
|
|
+ return match; // Don't change headers in content for now
|
|
|
});
|
|
|
|
|
|
// Add BOM if not present
|