docs-ready 0.4.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-4NYEWEU2.js +73 -0
- package/dist/chunk-4NYEWEU2.js.map +1 -0
- package/dist/chunk-5XFC7QYB.js +33 -0
- package/dist/chunk-5XFC7QYB.js.map +1 -0
- package/dist/chunk-PXQN4E6K.js +42 -0
- package/dist/chunk-PXQN4E6K.js.map +1 -0
- package/dist/{generate-N54SEQ7E.js → generate-2KF6X5GF.js} +53 -99
- package/dist/generate-2KF6X5GF.js.map +1 -0
- package/dist/{guard-EKGLQRED.js → guard-24Z36RVB.js} +40 -33
- package/dist/guard-24Z36RVB.js.map +1 -0
- package/dist/index.js +20 -10
- package/dist/index.js.map +1 -1
- package/dist/validate-GKDIBEZX.js +219 -0
- package/dist/validate-GKDIBEZX.js.map +1 -0
- package/dist/watcher-TAYSGKGV.js +35 -0
- package/dist/watcher-TAYSGKGV.js.map +1 -0
- package/dist/workflow-PTPU42JU.js +75 -0
- package/dist/workflow-PTPU42JU.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-7YN54Y4Y.js +0 -21
- package/dist/chunk-7YN54Y4Y.js.map +0 -1
- package/dist/generate-N54SEQ7E.js.map +0 -1
- package/dist/guard-EKGLQRED.js.map +0 -1
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/core/scanner.ts
|
|
4
|
+
import fs from "fs/promises";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import matter from "gray-matter";
|
|
7
|
+
import { glob } from "glob";
|
|
8
|
+
async function scanDocs(docsDir, options) {
|
|
9
|
+
const resolvedDir = path.resolve(docsDir);
|
|
10
|
+
const allFiles = [];
|
|
11
|
+
for (const pattern of options.include) {
|
|
12
|
+
const matches = await glob(pattern, {
|
|
13
|
+
cwd: resolvedDir,
|
|
14
|
+
ignore: options.exclude,
|
|
15
|
+
nodir: true,
|
|
16
|
+
absolute: false
|
|
17
|
+
});
|
|
18
|
+
allFiles.push(...matches);
|
|
19
|
+
}
|
|
20
|
+
const uniqueFiles = [...new Set(allFiles)];
|
|
21
|
+
const pages = [];
|
|
22
|
+
for (const relativePath of uniqueFiles) {
|
|
23
|
+
const filePath = path.join(resolvedDir, relativePath);
|
|
24
|
+
const raw = await fs.readFile(filePath, "utf-8");
|
|
25
|
+
const { data: frontmatter, content } = matter(raw);
|
|
26
|
+
const title = resolveTitle(frontmatter, content, relativePath);
|
|
27
|
+
const description = frontmatter.description ?? null;
|
|
28
|
+
pages.push({
|
|
29
|
+
filePath,
|
|
30
|
+
relativePath: relativePath.replace(/\\/g, "/"),
|
|
31
|
+
title,
|
|
32
|
+
description,
|
|
33
|
+
frontmatter,
|
|
34
|
+
content
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
pages.sort((a, b) => {
|
|
38
|
+
const posA = a.frontmatter.sidebar_position ?? Infinity;
|
|
39
|
+
const posB = b.frontmatter.sidebar_position ?? Infinity;
|
|
40
|
+
if (posA !== posB) return posA - posB;
|
|
41
|
+
return a.relativePath.localeCompare(b.relativePath);
|
|
42
|
+
});
|
|
43
|
+
return pages;
|
|
44
|
+
}
|
|
45
|
+
function resolveTitle(frontmatter, content, relativePath) {
|
|
46
|
+
if (typeof frontmatter.title === "string" && frontmatter.title.trim()) {
|
|
47
|
+
return frontmatter.title.trim();
|
|
48
|
+
}
|
|
49
|
+
const h1Match = content.match(/^#\s+(.+)$/m);
|
|
50
|
+
if (h1Match) {
|
|
51
|
+
return h1Match[1].trim();
|
|
52
|
+
}
|
|
53
|
+
const basename = path.basename(relativePath, path.extname(relativePath));
|
|
54
|
+
return basename.charAt(0).toUpperCase() + basename.slice(1).replace(/[-_]/g, " ");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/utils/tokens.ts
|
|
58
|
+
function estimateTokens(content) {
|
|
59
|
+
return Math.ceil(content.length / 4);
|
|
60
|
+
}
|
|
61
|
+
function formatTokens(count) {
|
|
62
|
+
if (count >= 1e3) {
|
|
63
|
+
return `~${(count / 1e3).toFixed(1)}K tokens`;
|
|
64
|
+
}
|
|
65
|
+
return `~${count} tokens`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export {
|
|
69
|
+
scanDocs,
|
|
70
|
+
estimateTokens,
|
|
71
|
+
formatTokens
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=chunk-4NYEWEU2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/scanner.ts","../src/utils/tokens.ts"],"sourcesContent":["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport matter from \"gray-matter\";\nimport { glob } from \"glob\";\n\nexport interface ScannedPage {\n filePath: string;\n relativePath: string;\n title: string;\n description: string | null;\n frontmatter: Record<string, unknown>;\n content: string;\n}\n\nexport interface ScanOptions {\n include: string[];\n exclude: string[];\n}\n\nexport async function scanDocs(docsDir: string, options: ScanOptions): Promise<ScannedPage[]> {\n const resolvedDir = path.resolve(docsDir);\n const allFiles: string[] = [];\n\n for (const pattern of options.include) {\n const matches = await glob(pattern, {\n cwd: resolvedDir,\n ignore: options.exclude,\n nodir: true,\n absolute: false,\n });\n allFiles.push(...matches);\n }\n\n const uniqueFiles = [...new Set(allFiles)];\n const pages: ScannedPage[] = [];\n\n for (const relativePath of uniqueFiles) {\n const filePath = path.join(resolvedDir, relativePath);\n const raw = await fs.readFile(filePath, \"utf-8\");\n const { data: frontmatter, content } = matter(raw);\n\n const title = resolveTitle(frontmatter, content, relativePath);\n const description = (frontmatter.description as string) ?? null;\n\n pages.push({\n filePath,\n relativePath: relativePath.replace(/\\\\/g, \"/\"),\n title,\n description,\n frontmatter,\n content,\n });\n }\n\n pages.sort((a, b) => {\n const posA = (a.frontmatter.sidebar_position as number) ?? Infinity;\n const posB = (b.frontmatter.sidebar_position as number) ?? Infinity;\n if (posA !== posB) return posA - posB;\n return a.relativePath.localeCompare(b.relativePath);\n });\n\n return pages;\n}\n\nfunction resolveTitle(\n frontmatter: Record<string, unknown>,\n content: string,\n relativePath: string\n): string {\n if (typeof frontmatter.title === \"string\" && frontmatter.title.trim()) {\n return frontmatter.title.trim();\n }\n\n const h1Match = content.match(/^#\\s+(.+)$/m);\n if (h1Match) {\n return h1Match[1].trim();\n }\n\n const basename = path.basename(relativePath, path.extname(relativePath));\n return basename.charAt(0).toUpperCase() + basename.slice(1).replace(/[-_]/g, \" \");\n}\n","/**\n * Estimate token count using chars/4 heuristic.\n * Accurate within ~15% for English technical documentation.\n */\nexport function estimateTokens(content: string): number {\n return Math.ceil(content.length / 4);\n}\n\n/**\n * Format token count for display (e.g. \"~12.5K tokens\")\n */\nexport function formatTokens(count: number): string {\n if (count >= 1000) {\n return `~${(count / 1000).toFixed(1)}K tokens`;\n }\n return `~${count} tokens`;\n}\n"],"mappings":";;;AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,YAAY;AACnB,SAAS,YAAY;AAgBrB,eAAsB,SAAS,SAAiB,SAA8C;AAC5F,QAAM,cAAc,KAAK,QAAQ,OAAO;AACxC,QAAM,WAAqB,CAAC;AAE5B,aAAW,WAAW,QAAQ,SAAS;AACrC,UAAM,UAAU,MAAM,KAAK,SAAS;AAAA,MAClC,KAAK;AAAA,MACL,QAAQ,QAAQ;AAAA,MAChB,OAAO;AAAA,MACP,UAAU;AAAA,IACZ,CAAC;AACD,aAAS,KAAK,GAAG,OAAO;AAAA,EAC1B;AAEA,QAAM,cAAc,CAAC,GAAG,IAAI,IAAI,QAAQ,CAAC;AACzC,QAAM,QAAuB,CAAC;AAE9B,aAAW,gBAAgB,aAAa;AACtC,UAAM,WAAW,KAAK,KAAK,aAAa,YAAY;AACpD,UAAM,MAAM,MAAM,GAAG,SAAS,UAAU,OAAO;AAC/C,UAAM,EAAE,MAAM,aAAa,QAAQ,IAAI,OAAO,GAAG;AAEjD,UAAM,QAAQ,aAAa,aAAa,SAAS,YAAY;AAC7D,UAAM,cAAe,YAAY,eAA0B;AAE3D,UAAM,KAAK;AAAA,MACT;AAAA,MACA,cAAc,aAAa,QAAQ,OAAO,GAAG;AAAA,MAC7C;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,KAAK,CAAC,GAAG,MAAM;AACnB,UAAM,OAAQ,EAAE,YAAY,oBAA+B;AAC3D,UAAM,OAAQ,EAAE,YAAY,oBAA+B;AAC3D,QAAI,SAAS,KAAM,QAAO,OAAO;AACjC,WAAO,EAAE,aAAa,cAAc,EAAE,YAAY;AAAA,EACpD,CAAC;AAED,SAAO;AACT;AAEA,SAAS,aACP,aACA,SACA,cACQ;AACR,MAAI,OAAO,YAAY,UAAU,YAAY,YAAY,MAAM,KAAK,GAAG;AACrE,WAAO,YAAY,MAAM,KAAK;AAAA,EAChC;AAEA,QAAM,UAAU,QAAQ,MAAM,aAAa;AAC3C,MAAI,SAAS;AACX,WAAO,QAAQ,CAAC,EAAE,KAAK;AAAA,EACzB;AAEA,QAAM,WAAW,KAAK,SAAS,cAAc,KAAK,QAAQ,YAAY,CAAC;AACvE,SAAO,SAAS,OAAO,CAAC,EAAE,YAAY,IAAI,SAAS,MAAM,CAAC,EAAE,QAAQ,SAAS,GAAG;AAClF;;;AC5EO,SAAS,eAAe,SAAyB;AACtD,SAAO,KAAK,KAAK,QAAQ,SAAS,CAAC;AACrC;AAKO,SAAS,aAAa,OAAuB;AAClD,MAAI,SAAS,KAAM;AACjB,WAAO,KAAK,QAAQ,KAAM,QAAQ,CAAC,CAAC;AAAA,EACtC;AACA,SAAO,IAAI,KAAK;AAClB;","names":[]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/utils/http.ts
|
|
4
|
+
async function fetchWithTimeout(url, options = {}) {
|
|
5
|
+
const { timeout = 1e4, headers = {} } = options;
|
|
6
|
+
const controller = new AbortController();
|
|
7
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
8
|
+
try {
|
|
9
|
+
const response = await fetch(url, {
|
|
10
|
+
signal: controller.signal,
|
|
11
|
+
headers
|
|
12
|
+
});
|
|
13
|
+
return response;
|
|
14
|
+
} finally {
|
|
15
|
+
clearTimeout(timeoutId);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function githubHeaders() {
|
|
19
|
+
const headers = {
|
|
20
|
+
Accept: "application/vnd.github.v3+json"
|
|
21
|
+
};
|
|
22
|
+
const token = process.env.GITHUB_TOKEN;
|
|
23
|
+
if (token) {
|
|
24
|
+
headers.Authorization = `Bearer ${token}`;
|
|
25
|
+
}
|
|
26
|
+
return headers;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export {
|
|
30
|
+
fetchWithTimeout,
|
|
31
|
+
githubHeaders
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=chunk-5XFC7QYB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/http.ts"],"sourcesContent":["export interface FetchOptions {\n timeout?: number;\n headers?: Record<string, string>;\n}\n\nexport async function fetchWithTimeout(\n url: string,\n options: FetchOptions = {}\n): Promise<Response> {\n const { timeout = 10000, headers = {} } = options;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(url, {\n signal: controller.signal,\n headers,\n });\n return response;\n } finally {\n clearTimeout(timeoutId);\n }\n}\n\nexport function githubHeaders(): Record<string, string> {\n const headers: Record<string, string> = {\n Accept: \"application/vnd.github.v3+json\",\n };\n const token = process.env.GITHUB_TOKEN;\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n return headers;\n}\n"],"mappings":";;;AAKA,eAAsB,iBACpB,KACA,UAAwB,CAAC,GACN;AACnB,QAAM,EAAE,UAAU,KAAO,UAAU,CAAC,EAAE,IAAI;AAC1C,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,OAAO;AAE9D,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ,WAAW;AAAA,MACnB;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT,UAAE;AACA,iBAAa,SAAS;AAAA,EACxB;AACF;AAEO,SAAS,gBAAwC;AACtD,QAAM,UAAkC;AAAA,IACtC,QAAQ;AAAA,EACV;AACA,QAAM,QAAQ,QAAQ,IAAI;AAC1B,MAAI,OAAO;AACT,YAAQ,gBAAgB,UAAU,KAAK;AAAA,EACzC;AACA,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/utils/logger.ts
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import ora from "ora";
|
|
6
|
+
var currentLevel = "normal";
|
|
7
|
+
function setLogLevel(level) {
|
|
8
|
+
currentLevel = level;
|
|
9
|
+
}
|
|
10
|
+
var log = {
|
|
11
|
+
info: (msg) => {
|
|
12
|
+
if (currentLevel !== "quiet") console.log(chalk.blue("\u2139"), msg);
|
|
13
|
+
},
|
|
14
|
+
success: (msg) => {
|
|
15
|
+
if (currentLevel !== "quiet") console.log(chalk.green("\u2714"), msg);
|
|
16
|
+
},
|
|
17
|
+
warn: (msg) => {
|
|
18
|
+
console.log(chalk.yellow("\u26A0"), msg);
|
|
19
|
+
},
|
|
20
|
+
error: (msg) => {
|
|
21
|
+
console.error(chalk.red("\u2716"), msg);
|
|
22
|
+
},
|
|
23
|
+
dim: (msg) => {
|
|
24
|
+
if (currentLevel !== "quiet") console.log(chalk.dim(msg));
|
|
25
|
+
},
|
|
26
|
+
debug: (msg) => {
|
|
27
|
+
if (currentLevel === "verbose") console.log(chalk.gray("[debug]"), msg);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
function spinner(text) {
|
|
31
|
+
if (currentLevel === "quiet") {
|
|
32
|
+
return { start: () => ({}), stop: () => ({}), succeed: () => ({}), fail: () => ({}) };
|
|
33
|
+
}
|
|
34
|
+
return ora({ text, color: "cyan" });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export {
|
|
38
|
+
setLogLevel,
|
|
39
|
+
log,
|
|
40
|
+
spinner
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=chunk-PXQN4E6K.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/logger.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport ora, { type Ora } from \"ora\";\n\nexport type LogLevel = \"quiet\" | \"normal\" | \"verbose\";\n\nlet currentLevel: LogLevel = \"normal\";\n\nexport function setLogLevel(level: LogLevel): void {\n currentLevel = level;\n}\n\nexport const log = {\n info: (msg: string) => {\n if (currentLevel !== \"quiet\") console.log(chalk.blue(\"ℹ\"), msg);\n },\n success: (msg: string) => {\n if (currentLevel !== \"quiet\") console.log(chalk.green(\"✔\"), msg);\n },\n warn: (msg: string) => {\n console.log(chalk.yellow(\"⚠\"), msg);\n },\n error: (msg: string) => {\n console.error(chalk.red(\"✖\"), msg);\n },\n dim: (msg: string) => {\n if (currentLevel !== \"quiet\") console.log(chalk.dim(msg));\n },\n debug: (msg: string) => {\n if (currentLevel === \"verbose\") console.log(chalk.gray(\"[debug]\"), msg);\n },\n};\n\nexport function spinner(text: string): Ora {\n if (currentLevel === \"quiet\") {\n // Return a no-op spinner\n return { start: () => ({} as Ora), stop: () => ({} as Ora), succeed: () => ({} as Ora), fail: () => ({} as Ora) } as unknown as Ora;\n }\n return ora({ text, color: \"cyan\" });\n}\n"],"mappings":";;;AAAA,OAAO,WAAW;AAClB,OAAO,SAAuB;AAI9B,IAAI,eAAyB;AAEtB,SAAS,YAAY,OAAuB;AACjD,iBAAe;AACjB;AAEO,IAAM,MAAM;AAAA,EACjB,MAAM,CAAC,QAAgB;AACrB,QAAI,iBAAiB,QAAS,SAAQ,IAAI,MAAM,KAAK,QAAG,GAAG,GAAG;AAAA,EAChE;AAAA,EACA,SAAS,CAAC,QAAgB;AACxB,QAAI,iBAAiB,QAAS,SAAQ,IAAI,MAAM,MAAM,QAAG,GAAG,GAAG;AAAA,EACjE;AAAA,EACA,MAAM,CAAC,QAAgB;AACrB,YAAQ,IAAI,MAAM,OAAO,QAAG,GAAG,GAAG;AAAA,EACpC;AAAA,EACA,OAAO,CAAC,QAAgB;AACtB,YAAQ,MAAM,MAAM,IAAI,QAAG,GAAG,GAAG;AAAA,EACnC;AAAA,EACA,KAAK,CAAC,QAAgB;AACpB,QAAI,iBAAiB,QAAS,SAAQ,IAAI,MAAM,IAAI,GAAG,CAAC;AAAA,EAC1D;AAAA,EACA,OAAO,CAAC,QAAgB;AACtB,QAAI,iBAAiB,UAAW,SAAQ,IAAI,MAAM,KAAK,SAAS,GAAG,GAAG;AAAA,EACxE;AACF;AAEO,SAAS,QAAQ,MAAmB;AACzC,MAAI,iBAAiB,SAAS;AAE5B,WAAO,EAAE,OAAO,OAAO,CAAC,IAAW,MAAM,OAAO,CAAC,IAAW,SAAS,OAAO,CAAC,IAAW,MAAM,OAAO,CAAC,GAAU;AAAA,EAClH;AACA,SAAO,IAAI,EAAE,MAAM,OAAO,OAAO,CAAC;AACpC;","names":[]}
|
|
@@ -1,72 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
estimateTokens,
|
|
4
|
+
formatTokens,
|
|
5
|
+
scanDocs
|
|
6
|
+
} from "./chunk-4NYEWEU2.js";
|
|
2
7
|
import {
|
|
3
8
|
loadConfig
|
|
4
9
|
} from "./chunk-QI2AROM3.js";
|
|
5
10
|
import {
|
|
6
11
|
log,
|
|
7
12
|
spinner
|
|
8
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-PXQN4E6K.js";
|
|
9
14
|
|
|
10
15
|
// src/cli/commands/generate.ts
|
|
11
|
-
import fs2 from "fs/promises";
|
|
12
|
-
import path4 from "path";
|
|
13
|
-
|
|
14
|
-
// src/core/scanner.ts
|
|
15
16
|
import fs from "fs/promises";
|
|
16
|
-
import
|
|
17
|
-
import matter from "gray-matter";
|
|
18
|
-
import { glob } from "glob";
|
|
19
|
-
async function scanDocs(docsDir, options) {
|
|
20
|
-
const resolvedDir = path.resolve(docsDir);
|
|
21
|
-
const allFiles = [];
|
|
22
|
-
for (const pattern of options.include) {
|
|
23
|
-
const matches = await glob(pattern, {
|
|
24
|
-
cwd: resolvedDir,
|
|
25
|
-
ignore: options.exclude,
|
|
26
|
-
nodir: true,
|
|
27
|
-
absolute: false
|
|
28
|
-
});
|
|
29
|
-
allFiles.push(...matches);
|
|
30
|
-
}
|
|
31
|
-
const uniqueFiles = [...new Set(allFiles)];
|
|
32
|
-
const pages = [];
|
|
33
|
-
for (const relativePath of uniqueFiles) {
|
|
34
|
-
const filePath = path.join(resolvedDir, relativePath);
|
|
35
|
-
const raw = await fs.readFile(filePath, "utf-8");
|
|
36
|
-
const { data: frontmatter, content } = matter(raw);
|
|
37
|
-
const title = resolveTitle(frontmatter, content, relativePath);
|
|
38
|
-
const description = frontmatter.description ?? null;
|
|
39
|
-
pages.push({
|
|
40
|
-
filePath,
|
|
41
|
-
relativePath: relativePath.replace(/\\/g, "/"),
|
|
42
|
-
title,
|
|
43
|
-
description,
|
|
44
|
-
frontmatter,
|
|
45
|
-
content
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
pages.sort((a, b) => {
|
|
49
|
-
const posA = a.frontmatter.sidebar_position ?? Infinity;
|
|
50
|
-
const posB = b.frontmatter.sidebar_position ?? Infinity;
|
|
51
|
-
if (posA !== posB) return posA - posB;
|
|
52
|
-
return a.relativePath.localeCompare(b.relativePath);
|
|
53
|
-
});
|
|
54
|
-
return pages;
|
|
55
|
-
}
|
|
56
|
-
function resolveTitle(frontmatter, content, relativePath) {
|
|
57
|
-
if (typeof frontmatter.title === "string" && frontmatter.title.trim()) {
|
|
58
|
-
return frontmatter.title.trim();
|
|
59
|
-
}
|
|
60
|
-
const h1Match = content.match(/^#\s+(.+)$/m);
|
|
61
|
-
if (h1Match) {
|
|
62
|
-
return h1Match[1].trim();
|
|
63
|
-
}
|
|
64
|
-
const basename = path.basename(relativePath, path.extname(relativePath));
|
|
65
|
-
return basename.charAt(0).toUpperCase() + basename.slice(1).replace(/[-_]/g, " ");
|
|
66
|
-
}
|
|
17
|
+
import path3 from "path";
|
|
67
18
|
|
|
68
19
|
// src/generate/llms-txt.ts
|
|
69
|
-
import
|
|
20
|
+
import path2 from "path";
|
|
70
21
|
|
|
71
22
|
// node_modules/balanced-match/dist/esm/index.js
|
|
72
23
|
var balanced = (a, b, str) => {
|
|
@@ -312,9 +263,9 @@ var posixClasses = {
|
|
|
312
263
|
var braceEscape = (s) => s.replace(/[[\]\\-]/g, "\\$&");
|
|
313
264
|
var regexpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
|
314
265
|
var rangesToString = (ranges) => ranges.join("");
|
|
315
|
-
var parseClass = (
|
|
266
|
+
var parseClass = (glob, position) => {
|
|
316
267
|
const pos = position;
|
|
317
|
-
if (
|
|
268
|
+
if (glob.charAt(pos) !== "[") {
|
|
318
269
|
throw new Error("not in a brace expression");
|
|
319
270
|
}
|
|
320
271
|
const ranges = [];
|
|
@@ -326,8 +277,8 @@ var parseClass = (glob2, position) => {
|
|
|
326
277
|
let negate = false;
|
|
327
278
|
let endPos = pos;
|
|
328
279
|
let rangeStart = "";
|
|
329
|
-
WHILE: while (i <
|
|
330
|
-
const c =
|
|
280
|
+
WHILE: while (i < glob.length) {
|
|
281
|
+
const c = glob.charAt(i);
|
|
331
282
|
if ((c === "!" || c === "^") && i === pos + 1) {
|
|
332
283
|
negate = true;
|
|
333
284
|
i++;
|
|
@@ -347,9 +298,9 @@ var parseClass = (glob2, position) => {
|
|
|
347
298
|
}
|
|
348
299
|
if (c === "[" && !escaping) {
|
|
349
300
|
for (const [cls, [unip, u, neg]] of Object.entries(posixClasses)) {
|
|
350
|
-
if (
|
|
301
|
+
if (glob.startsWith(cls, i)) {
|
|
351
302
|
if (rangeStart) {
|
|
352
|
-
return ["$.", false,
|
|
303
|
+
return ["$.", false, glob.length - pos, true];
|
|
353
304
|
}
|
|
354
305
|
i += cls.length;
|
|
355
306
|
if (neg)
|
|
@@ -372,12 +323,12 @@ var parseClass = (glob2, position) => {
|
|
|
372
323
|
i++;
|
|
373
324
|
continue;
|
|
374
325
|
}
|
|
375
|
-
if (
|
|
326
|
+
if (glob.startsWith("-]", i + 1)) {
|
|
376
327
|
ranges.push(braceEscape(c + "-"));
|
|
377
328
|
i += 2;
|
|
378
329
|
continue;
|
|
379
330
|
}
|
|
380
|
-
if (
|
|
331
|
+
if (glob.startsWith("-", i + 1)) {
|
|
381
332
|
rangeStart = c;
|
|
382
333
|
i += 2;
|
|
383
334
|
continue;
|
|
@@ -389,7 +340,7 @@ var parseClass = (glob2, position) => {
|
|
|
389
340
|
return ["", false, 0, false];
|
|
390
341
|
}
|
|
391
342
|
if (!ranges.length && !negs.length) {
|
|
392
|
-
return ["$.", false,
|
|
343
|
+
return ["$.", false, glob.length - pos, true];
|
|
393
344
|
}
|
|
394
345
|
if (negs.length === 0 && ranges.length === 1 && /^\\?.$/.test(ranges[0]) && !negate) {
|
|
395
346
|
const r = ranges[0].length === 2 ? ranges[0].slice(-1) : ranges[0];
|
|
@@ -797,16 +748,16 @@ var AST = class {
|
|
|
797
748
|
toMMPattern() {
|
|
798
749
|
if (this !== this.#root)
|
|
799
750
|
return this.#root.toMMPattern();
|
|
800
|
-
const
|
|
751
|
+
const glob = this.toString();
|
|
801
752
|
const [re, body, hasMagic, uflag] = this.toRegExpSource();
|
|
802
|
-
const anyMagic = hasMagic || this.#hasMagic || this.#options.nocase && !this.#options.nocaseMagicOnly &&
|
|
753
|
+
const anyMagic = hasMagic || this.#hasMagic || this.#options.nocase && !this.#options.nocaseMagicOnly && glob.toUpperCase() !== glob.toLowerCase();
|
|
803
754
|
if (!anyMagic) {
|
|
804
755
|
return body;
|
|
805
756
|
}
|
|
806
757
|
const flags = (this.#options.nocase ? "i" : "") + (uflag ? "u" : "");
|
|
807
758
|
return Object.assign(new RegExp(`^${re}$`, flags), {
|
|
808
759
|
_src: re,
|
|
809
|
-
_glob:
|
|
760
|
+
_glob: glob
|
|
810
761
|
});
|
|
811
762
|
}
|
|
812
763
|
get options() {
|
|
@@ -1001,13 +952,13 @@ var AST = class {
|
|
|
1001
952
|
return re;
|
|
1002
953
|
}).filter((p) => !(this.isStart() && this.isEnd()) || !!p).join("|");
|
|
1003
954
|
}
|
|
1004
|
-
static #parseGlob(
|
|
955
|
+
static #parseGlob(glob, hasMagic, noEmpty = false) {
|
|
1005
956
|
let escaping = false;
|
|
1006
957
|
let re = "";
|
|
1007
958
|
let uflag = false;
|
|
1008
959
|
let inStar = false;
|
|
1009
|
-
for (let i = 0; i <
|
|
1010
|
-
const c =
|
|
960
|
+
for (let i = 0; i < glob.length; i++) {
|
|
961
|
+
const c = glob.charAt(i);
|
|
1011
962
|
if (escaping) {
|
|
1012
963
|
escaping = false;
|
|
1013
964
|
re += (reSpecials.has(c) ? "\\" : "") + c;
|
|
@@ -1017,14 +968,14 @@ var AST = class {
|
|
|
1017
968
|
if (inStar)
|
|
1018
969
|
continue;
|
|
1019
970
|
inStar = true;
|
|
1020
|
-
re += noEmpty && /^[*]+$/.test(
|
|
971
|
+
re += noEmpty && /^[*]+$/.test(glob) ? starNoEmpty : star;
|
|
1021
972
|
hasMagic = true;
|
|
1022
973
|
continue;
|
|
1023
974
|
} else {
|
|
1024
975
|
inStar = false;
|
|
1025
976
|
}
|
|
1026
977
|
if (c === "\\") {
|
|
1027
|
-
if (i ===
|
|
978
|
+
if (i === glob.length - 1) {
|
|
1028
979
|
re += "\\\\";
|
|
1029
980
|
} else {
|
|
1030
981
|
escaping = true;
|
|
@@ -1032,7 +983,7 @@ var AST = class {
|
|
|
1032
983
|
continue;
|
|
1033
984
|
}
|
|
1034
985
|
if (c === "[") {
|
|
1035
|
-
const [src, needUflag, consumed, magic] = parseClass(
|
|
986
|
+
const [src, needUflag, consumed, magic] = parseClass(glob, i);
|
|
1036
987
|
if (consumed) {
|
|
1037
988
|
re += src;
|
|
1038
989
|
uflag = uflag || needUflag;
|
|
@@ -1048,7 +999,7 @@ var AST = class {
|
|
|
1048
999
|
}
|
|
1049
1000
|
re += regExpEscape(c);
|
|
1050
1001
|
}
|
|
1051
|
-
return [re, unescape(
|
|
1002
|
+
return [re, unescape(glob), !!hasMagic, uflag];
|
|
1052
1003
|
}
|
|
1053
1004
|
};
|
|
1054
1005
|
_a = AST;
|
|
@@ -1120,11 +1071,11 @@ var qmarksTestNoExtDot = ([$0]) => {
|
|
|
1120
1071
|
return (f) => f.length === len && f !== "." && f !== "..";
|
|
1121
1072
|
};
|
|
1122
1073
|
var defaultPlatform = typeof process === "object" && process ? typeof process.env === "object" && process.env && process.env.__MINIMATCH_TESTING_PLATFORM__ || process.platform : "posix";
|
|
1123
|
-
var
|
|
1074
|
+
var path = {
|
|
1124
1075
|
win32: { sep: "\\" },
|
|
1125
1076
|
posix: { sep: "/" }
|
|
1126
1077
|
};
|
|
1127
|
-
var sep = defaultPlatform === "win32" ?
|
|
1078
|
+
var sep = defaultPlatform === "win32" ? path.win32.sep : path.posix.sep;
|
|
1128
1079
|
minimatch.sep = sep;
|
|
1129
1080
|
var GLOBSTAR = /* @__PURE__ */ Symbol("globstar **");
|
|
1130
1081
|
minimatch.GLOBSTAR = GLOBSTAR;
|
|
@@ -1945,7 +1896,7 @@ function extractFirstParagraph(content) {
|
|
|
1945
1896
|
function groupByDirectory(pages) {
|
|
1946
1897
|
const groups = /* @__PURE__ */ new Map();
|
|
1947
1898
|
for (const page of pages) {
|
|
1948
|
-
const dir =
|
|
1899
|
+
const dir = path2.dirname(page.relativePath);
|
|
1949
1900
|
const topDir = dir === "." ? "." : dir.split("/")[0];
|
|
1950
1901
|
if (!groups.has(topDir)) {
|
|
1951
1902
|
groups.set(topDir, []);
|
|
@@ -1986,24 +1937,13 @@ ${cleaned}`);
|
|
|
1986
1937
|
return sections.join("\n\n").trimEnd() + "\n";
|
|
1987
1938
|
}
|
|
1988
1939
|
|
|
1989
|
-
// src/utils/tokens.ts
|
|
1990
|
-
function estimateTokens(content) {
|
|
1991
|
-
return Math.ceil(content.length / 4);
|
|
1992
|
-
}
|
|
1993
|
-
function formatTokens(count) {
|
|
1994
|
-
if (count >= 1e3) {
|
|
1995
|
-
return `~${(count / 1e3).toFixed(1)}K tokens`;
|
|
1996
|
-
}
|
|
1997
|
-
return `~${count} tokens`;
|
|
1998
|
-
}
|
|
1999
|
-
|
|
2000
1940
|
// src/cli/commands/generate.ts
|
|
2001
1941
|
async function generateCommand(options = {}) {
|
|
2002
1942
|
const cwd = process.cwd();
|
|
2003
1943
|
const config = await loadConfig(cwd);
|
|
2004
1944
|
const spin = spinner("Scanning documentation...");
|
|
2005
1945
|
spin.start();
|
|
2006
|
-
const docsDir =
|
|
1946
|
+
const docsDir = path3.resolve(cwd, config.docs.dir);
|
|
2007
1947
|
const pages = await scanDocs(docsDir, {
|
|
2008
1948
|
include: config.docs.include,
|
|
2009
1949
|
exclude: config.docs.exclude
|
|
@@ -2014,7 +1954,7 @@ async function generateCommand(options = {}) {
|
|
|
2014
1954
|
return;
|
|
2015
1955
|
}
|
|
2016
1956
|
log.info(`Found ${pages.length} documentation pages`);
|
|
2017
|
-
const outputDir =
|
|
1957
|
+
const outputDir = path3.resolve(cwd, config.generate.output_dir);
|
|
2018
1958
|
if (config.generate.llms_txt && options.only !== "llms-full") {
|
|
2019
1959
|
const llmsTxt = generateLlmsTxt(pages, {
|
|
2020
1960
|
title: config.title,
|
|
@@ -2026,8 +1966,8 @@ async function generateCommand(options = {}) {
|
|
|
2026
1966
|
log.info("[dry-run] Would write llms.txt");
|
|
2027
1967
|
log.dim(` ${llmsTxt.length} chars, ${formatTokens(estimateTokens(llmsTxt))}`);
|
|
2028
1968
|
} else {
|
|
2029
|
-
await
|
|
2030
|
-
await
|
|
1969
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
1970
|
+
await fs.writeFile(path3.join(outputDir, "llms.txt"), llmsTxt, "utf-8");
|
|
2031
1971
|
log.success(`Generated llms.txt (${formatTokens(estimateTokens(llmsTxt))})`);
|
|
2032
1972
|
}
|
|
2033
1973
|
}
|
|
@@ -2037,8 +1977,8 @@ async function generateCommand(options = {}) {
|
|
|
2037
1977
|
log.info("[dry-run] Would write llms-full.txt");
|
|
2038
1978
|
log.dim(` ${llmsFullTxt.length} chars, ${formatTokens(estimateTokens(llmsFullTxt))}`);
|
|
2039
1979
|
} else {
|
|
2040
|
-
await
|
|
2041
|
-
await
|
|
1980
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
1981
|
+
await fs.writeFile(path3.join(outputDir, "llms-full.txt"), llmsFullTxt, "utf-8");
|
|
2042
1982
|
log.success(`Generated llms-full.txt (${formatTokens(estimateTokens(llmsFullTxt))})`);
|
|
2043
1983
|
}
|
|
2044
1984
|
}
|
|
@@ -2059,13 +1999,27 @@ async function generateCommand(options = {}) {
|
|
|
2059
1999
|
log.info("[dry-run] Would write ai-context.md");
|
|
2060
2000
|
log.dim(` ${aiContext.length} chars, ${formatTokens(estimateTokens(aiContext))}`);
|
|
2061
2001
|
} else {
|
|
2062
|
-
await
|
|
2063
|
-
await
|
|
2002
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
2003
|
+
await fs.writeFile(path3.join(outputDir, "ai-context.md"), aiContext, "utf-8");
|
|
2064
2004
|
log.success(`Generated ai-context.md (${formatTokens(estimateTokens(aiContext))})`);
|
|
2065
2005
|
}
|
|
2066
2006
|
}
|
|
2007
|
+
if (options.watch) {
|
|
2008
|
+
log.info("Watching for changes... (press Ctrl+C to stop)");
|
|
2009
|
+
const { watchDocs } = await import("./watcher-TAYSGKGV.js");
|
|
2010
|
+
watchDocs({
|
|
2011
|
+
dir: docsDir,
|
|
2012
|
+
patterns: config.docs.include,
|
|
2013
|
+
onChange: async () => {
|
|
2014
|
+
log.info("Changes detected, regenerating...");
|
|
2015
|
+
await generateCommand({ ...options, watch: false });
|
|
2016
|
+
}
|
|
2017
|
+
});
|
|
2018
|
+
await new Promise(() => {
|
|
2019
|
+
});
|
|
2020
|
+
}
|
|
2067
2021
|
}
|
|
2068
2022
|
export {
|
|
2069
2023
|
generateCommand
|
|
2070
2024
|
};
|
|
2071
|
-
//# sourceMappingURL=generate-
|
|
2025
|
+
//# sourceMappingURL=generate-2KF6X5GF.js.map
|