vuepress-plugin-llms
Version:
📜 VuePress plugin for generating documentation friendly to Large Language Models (LLMs) | 📜 VuePress 插件,用于生成对大语言模型(LLMs)友好的文档。
142 lines (141 loc) • 5.89 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateLLMsTxt = generateLLMsTxt;
exports.generateLLMsFullTxt = generateLLMsFullTxt;
exports.generateTOC = generateTOC;
const promises_1 = __importDefault(require("node:fs/promises"));
const node_path_1 = __importDefault(require("node:path"));
const gray_matter_1 = __importDefault(require("gray-matter"));
const picocolors_1 = __importDefault(require("picocolors"));
const remark_1 = require("remark");
const remark_frontmatter_1 = __importDefault(require("remark-frontmatter"));
const utils_js_1 = require("./utils.js");
const logger_js_1 = __importDefault(require("./logger.js"));
/**
* Generate the contents of the `llms.txt` file, which contains a table of contents
* with links to all sections of the documentation.
*/
/**
* 生成 `llms.txt` 文件的内容,其中包含指向文档所有部分的链接的目录。
*/
async function generateLLMsTxt(preparedFiles, options) {
logger_js_1.default.info('Generating toc...');
const { indexMd, LLMsTxtTemplate, templateVariables, siteConfig, domain, linksExtension, cleanUrls, srcDir, } = options;
let variables = {
title: siteConfig.title,
description: siteConfig.description,
toc: '',
...templateVariables,
};
// Try to read index.md if it exists
// 如果 index.md 存在,尝试读取它
try {
if (indexMd) {
logger_js_1.default.info(`Reading index.md from: ${picocolors_1.default.cyan(indexMd)}`);
const indexContent = await promises_1.default.readFile(indexMd, 'utf-8');
const indexMdData = (0, gray_matter_1.default)(indexContent);
if (indexMdData.data.title && !templateVariables.title) {
variables.title = indexMdData.data.title;
}
if (indexMdData.data.description && !templateVariables.description) {
variables.description = indexMdData.data.description;
}
}
}
catch (error) {
logger_js_1.default.warn(`Failed to read index.md: ${error.message}`);
}
// Generate TOC if requested
// 如果请求,生成目录
if (!(typeof variables.toc === 'boolean' && variables.toc === false)) {
logger_js_1.default.info('Generating TOC from prepared files');
variables.toc = await generateTOC(preparedFiles, {
srcDir,
domain,
linksExtension,
cleanUrls,
});
}
// Expand template with variables
// 使用变量展开模板
return (0, utils_js_1.expandTemplate)(LLMsTxtTemplate, variables);
}
/**
* Generate the contents of the `llms-full.txt` file, which contains the entire
* content of all documentation embedded directly.
*/
/**
* 生成 `llms-full.txt` 文件的内容,其中直接嵌入了所有文档的全部内容。
*/
async function generateLLMsFullTxt(preparedFiles, options) {
const { srcDir, domain, linksExtension, cleanUrls } = options;
logger_js_1.default.info('Generating full content file');
// Process each file by adding a divider and metadata
// 通过添加分隔符和元数据处理每个文件
const sections = await Promise.all(preparedFiles.map(async (file) => {
// For each file, we'll create a section with metadata and content
// 对于每个文件,我们将创建一个包含元数据和内容的部分
const relativePath = node_path_1.default.relative(srcDir, file.path);
const metadata = (0, utils_js_1.generateMetadata)({
title: file.title,
relativePath,
domain,
linksExtension,
cleanUrls,
});
let contentToProcess = file.file.content;
// Convert markdown to plain text and strip HTML tags
// 将 markdown 转换为纯文本并去除 HTML 标签
try {
const processedContent = await (0, remark_1.remark)()
.use(remark_frontmatter_1.default)
.process(contentToProcess);
// Strip HTML tags from the processed content
// 从处理后的内容中去除 HTML 标签
let htmlContent = String(processedContent);
contentToProcess = htmlContent.replace(/<[^>]*>/g, '');
}
catch (error) {
logger_js_1.default.warn(`Failed to process HTML in ${file.path}: ${error.message}`);
}
return `${metadata}\n\n${contentToProcess}`;
}));
// Combine all sections with dividers
// 用分隔符组合所有部分
return sections.join('\n\n---\n\n');
}
/**
* Generate a table of contents from the prepared files.
*/
/**
* 从准备好的文件生成目录。
*/
async function generateTOC(preparedFiles, options) {
const { srcDir, domain, linksExtension, cleanUrls } = options;
return preparedFiles
.map((file) => {
const relativePath = node_path_1.default.relative(srcDir, file.path);
const normalizedPath = (0, utils_js_1.normalizePath)(relativePath, {
domain,
linksExtension,
cleanUrls,
});
// Get first sentence from content if available
// 如果可用,从内容中获取第一句话
let description = '';
const firstPara = file.file.content.split('\n\n')[0];
if (firstPara) {
// Extract text of the first sentence
// 提取第一句话的文本
const match = firstPara.match(/^[^.!?]+[.!?]/);
if (match) {
description = match[0].trim();
}
}
return `- [${file.title}](${normalizedPath})${description ? `: ${description}` : ''}`;
})
.join('\n');
}