|
1 | 1 | const path = require('path');
|
2 | 2 | const fs = require('fs');
|
| 3 | +const matter = require('gray-matter'); |
| 4 | + |
| 5 | +const DOCS_URL = 'https://commandkit.dev/docs/next/guide'; |
3 | 6 |
|
4 | 7 | module.exports = function (context) {
|
5 | 8 | return {
|
6 | 9 | name: 'llms-txt-plugin',
|
7 | 10 | loadContent: async () => {
|
8 | 11 | const { siteDir } = context;
|
9 | 12 | const docsDir = path.join(siteDir, 'docs');
|
| 13 | + const guideDir = path.join(docsDir, 'guide'); |
10 | 14 | const versionedDocsDir = path.join(siteDir, 'versioned_docs');
|
11 |
| - const allMdx = []; |
| 15 | + const allDocs = []; |
12 | 16 |
|
13 |
| - // Recursive function to get all mdx and md files (excluding API reference) |
14 | 17 | const getMdxFiles = async (dir, versionPrefix = '') => {
|
15 | 18 | if (!fs.existsSync(dir)) return;
|
16 | 19 |
|
| 20 | + // skip versioned docs |
| 21 | + if (dir.includes(versionedDocsDir)) return; |
| 22 | + |
17 | 23 | const entries = await fs.promises.readdir(dir, { withFileTypes: true });
|
18 | 24 |
|
19 | 25 | for (const entry of entries) {
|
20 | 26 | const fullPath = path.join(dir, entry.name);
|
21 | 27 | if (entry.isDirectory()) {
|
22 |
| - // Skip api-reference directories |
23 |
| - if (entry.name === 'api-reference') { |
24 |
| - continue; |
25 |
| - } |
26 | 28 | await getMdxFiles(fullPath, versionPrefix);
|
27 |
| - } else if ( |
28 |
| - entry.name.endsWith('.mdx') || |
29 |
| - entry.name.endsWith('.md') |
30 |
| - ) { |
31 |
| - // Skip files in api-reference paths |
32 |
| - if (fullPath.includes('api-reference')) { |
33 |
| - continue; |
34 |
| - } |
| 29 | + } else if (entry.name.endsWith('.mdx') || entry.name.endsWith('.md')) { |
35 | 30 | const content = await fs.promises.readFile(fullPath, 'utf8');
|
36 |
| - allMdx.push({ |
37 |
| - content, |
38 |
| - path: fullPath, |
| 31 | + const { data: frontmatter } = matter(content); |
| 32 | + |
| 33 | + // Get relative path from guide directory |
| 34 | + const relativePath = path.relative(guideDir, fullPath) |
| 35 | + .replace(/\.mdx?$/, '') |
| 36 | + .replace(/\\/g, '/'); |
| 37 | + |
| 38 | + allDocs.push({ |
| 39 | + title: frontmatter.title, |
| 40 | + description: frontmatter.description, |
| 41 | + path: relativePath, |
39 | 42 | version: versionPrefix,
|
40 | 43 | });
|
41 | 44 | }
|
42 | 45 | }
|
43 | 46 | };
|
44 | 47 |
|
45 |
| - // Get current/latest docs |
46 |
| - await getMdxFiles(docsDir, 'latest'); |
47 |
| - |
48 |
| - // Get versioned docs |
49 |
| - if (fs.existsSync(versionedDocsDir)) { |
50 |
| - const versionDirs = await fs.promises.readdir(versionedDocsDir, { |
51 |
| - withFileTypes: true, |
52 |
| - }); |
53 |
| - for (const versionDir of versionDirs) { |
54 |
| - if (versionDir.isDirectory()) { |
55 |
| - const versionName = versionDir.name.replace('version-', ''); |
56 |
| - await getMdxFiles( |
57 |
| - path.join(versionedDocsDir, versionDir.name), |
58 |
| - versionName, |
59 |
| - ); |
60 |
| - } |
61 |
| - } |
| 48 | + // Only process guide directory |
| 49 | + if (fs.existsSync(guideDir)) { |
| 50 | + await getMdxFiles(guideDir, 'latest'); |
62 | 51 | }
|
63 | 52 |
|
64 |
| - return { allMdx }; |
| 53 | + return { allDocs }; |
65 | 54 | },
|
66 | 55 | postBuild: async ({ content, outDir }) => {
|
67 |
| - const { allMdx } = content; |
| 56 | + const { allDocs } = content; |
68 | 57 |
|
69 |
| - // Filter out any remaining API reference content and concatenate |
70 |
| - const filteredContent = allMdx |
71 |
| - .filter((item) => !item.path.includes('api-reference')) |
72 |
| - .map((item) => item.content) |
73 |
| - .join('\n\n---\n\n'); |
| 58 | + // Generate markdown content |
| 59 | + const markdownContent = [ |
| 60 | + '# CommandKit Docs\n', |
| 61 | + ...allDocs |
| 62 | + .filter(doc => doc.title && doc.description) |
| 63 | + .map(doc => { |
| 64 | + const url = `${DOCS_URL}/${doc.path}`; |
| 65 | + return `- [${doc.title}](${url}): ${doc.description || doc.title}`; |
| 66 | + }) |
| 67 | + ].join('\n'); |
74 | 68 |
|
75 |
| - // Write concatenated content as llms.txt |
| 69 | + // Write markdown content |
76 | 70 | const llmsTxtPath = path.join(outDir, 'llms.txt');
|
77 | 71 | try {
|
78 |
| - await fs.promises.writeFile(llmsTxtPath, filteredContent); |
| 72 | + await fs.promises.writeFile(llmsTxtPath, markdownContent); |
79 | 73 | console.log('✅ llms.txt generated successfully');
|
80 | 74 | } catch (err) {
|
81 | 75 | console.error('❌ Error generating llms.txt:', err);
|
|
0 commit comments