@marlinjai/clearify 2.0.0 → 2.2.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/node/{chunk-CTL4YL7C.js → chunk-77IOLCAM.js} +13 -1
- package/dist/node/{chunk-RW4IKHY4.js → chunk-LVPVSOXK.js} +2 -2
- package/dist/node/chunk-TVDWHKQF.js +134 -0
- package/dist/node/{chunk-CK2SLBAG.js → chunk-V5J36LF5.js} +24 -16
- package/dist/node/{chunk-BCEGDIR6.js → chunk-XAX53RY5.js} +43 -3
- package/dist/node/{chunk-PGTNVDNF.js → chunk-ZWF6VCSQ.js} +7 -1
- package/dist/node/core/config.js +1 -1
- package/dist/node/core/llms-txt.d.ts +54 -0
- package/dist/node/core/llms-txt.js +10 -0
- package/dist/node/core/navigation.d.ts +1 -1
- package/dist/node/core/navigation.js +3 -1
- package/dist/node/core/search.d.ts +9 -2
- package/dist/node/node/build.js +5 -4
- package/dist/node/node/check.d.ts +5 -1
- package/dist/node/node/check.js +7 -3
- package/dist/node/node/index.d.ts +1 -0
- package/dist/node/node/index.js +6 -5
- package/dist/node/types/index.d.ts +28 -4
- package/dist/node/vite-plugin/index.js +3 -3
- package/package.json +4 -1
|
@@ -10,6 +10,16 @@ import { globbySync } from "globby";
|
|
|
10
10
|
function toTitleCase(str) {
|
|
11
11
|
return str.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
12
12
|
}
|
|
13
|
+
function inferDocType(filePath) {
|
|
14
|
+
const normalized = filePath.replace(/\\/g, "/").toLowerCase();
|
|
15
|
+
const file = basename(normalized, extname(normalized));
|
|
16
|
+
if (file === "readme") return "readme";
|
|
17
|
+
if (file === "changelog" || file === "changes") return "changelog";
|
|
18
|
+
if (file === "roadmap") return "roadmap";
|
|
19
|
+
if (file.includes("handover") || /\/handovers(\/|$)/.test(normalized)) return "handover";
|
|
20
|
+
if (/\/(plans|specs|superpowers|research|decisions)(\/|$)/.test(normalized)) return "plan";
|
|
21
|
+
return "documentation";
|
|
22
|
+
}
|
|
13
23
|
function fileToRoutePath(filePath, docsDir, basePath = "/") {
|
|
14
24
|
const rel = relative(docsDir, filePath);
|
|
15
25
|
const ext = extname(rel);
|
|
@@ -42,7 +52,8 @@ function scanDocs(docsDir, exclude = [], basePath = "/") {
|
|
|
42
52
|
icon: data.icon,
|
|
43
53
|
order: data.order,
|
|
44
54
|
summary: data.summary,
|
|
45
|
-
|
|
55
|
+
// `type` per the shared contract; inferred from path when omitted.
|
|
56
|
+
type: data.type ?? inferDocType(filePath),
|
|
46
57
|
tags: data.tags,
|
|
47
58
|
projects: data.projects,
|
|
48
59
|
status: data.status,
|
|
@@ -197,6 +208,7 @@ function buildSectionData(section, rootFiles, customNavigation) {
|
|
|
197
208
|
}
|
|
198
209
|
|
|
199
210
|
export {
|
|
211
|
+
inferDocType,
|
|
200
212
|
scanDocs,
|
|
201
213
|
buildNavigation,
|
|
202
214
|
buildRoutes,
|
|
@@ -10,10 +10,10 @@ import {
|
|
|
10
10
|
resolveSections,
|
|
11
11
|
scanHubProjects,
|
|
12
12
|
writeDataConfig
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-ZWF6VCSQ.js";
|
|
14
14
|
import {
|
|
15
15
|
buildSectionData
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-77IOLCAM.js";
|
|
17
17
|
|
|
18
18
|
// src/vite-plugin/index.ts
|
|
19
19
|
import { resolve, dirname } from "path";
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// src/core/llms-txt.ts
|
|
2
|
+
import { readFileSync } from "fs";
|
|
3
|
+
import matter from "gray-matter";
|
|
4
|
+
function normalizeBase(siteUrl) {
|
|
5
|
+
if (!siteUrl) return "";
|
|
6
|
+
return siteUrl.replace(/\/$/, "");
|
|
7
|
+
}
|
|
8
|
+
function toAbsoluteUrl(base, routePath) {
|
|
9
|
+
if (!base) return routePath;
|
|
10
|
+
if (!routePath.startsWith("/")) return `${base}/${routePath}`;
|
|
11
|
+
return `${base}${routePath}`;
|
|
12
|
+
}
|
|
13
|
+
function stripFrontmatterAndH1(markdown) {
|
|
14
|
+
const { content } = matter(markdown);
|
|
15
|
+
return content.replace(/^\s*#\s+[^\n]*\n+/, "").trimStart();
|
|
16
|
+
}
|
|
17
|
+
function firstParagraphSummary(markdown) {
|
|
18
|
+
const parsed = matter(markdown);
|
|
19
|
+
const fromFrontmatter = typeof parsed.data.summary === "string" && parsed.data.summary.trim() || typeof parsed.data.description === "string" && parsed.data.description.trim() || "";
|
|
20
|
+
const body = parsed.content;
|
|
21
|
+
const lines = body.split(/\r?\n/);
|
|
22
|
+
let inFence = false;
|
|
23
|
+
const paragraph = [];
|
|
24
|
+
for (const rawLine of lines) {
|
|
25
|
+
const line = rawLine.trimEnd();
|
|
26
|
+
if (/^```/.test(line)) {
|
|
27
|
+
inFence = !inFence;
|
|
28
|
+
if (paragraph.length > 0) break;
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (inFence) continue;
|
|
32
|
+
if (!line.trim()) {
|
|
33
|
+
if (paragraph.length > 0) break;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (/^(#{1,6}\s|>\s|[-*+]\s|\d+\.\s|\|.*\|\s*$|<)/.test(line)) {
|
|
37
|
+
if (paragraph.length > 0) break;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
paragraph.push(line.trim());
|
|
41
|
+
}
|
|
42
|
+
const text = paragraph.join(" ").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/([*_]{1,3})([^*_]+)\1/g, "$2").replace(/\s+/g, " ").trim();
|
|
43
|
+
return text || fromFrontmatter;
|
|
44
|
+
}
|
|
45
|
+
function uniqueOrdered(items) {
|
|
46
|
+
const seen = /* @__PURE__ */ new Set();
|
|
47
|
+
const out = [];
|
|
48
|
+
for (const item of items) {
|
|
49
|
+
if (seen.has(item)) continue;
|
|
50
|
+
seen.add(item);
|
|
51
|
+
out.push(item);
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
function buildHeader(config) {
|
|
56
|
+
const name = config.name.trim();
|
|
57
|
+
const tagline = config.hubProject?.description && config.hubProject.description.trim() || `Documentation for ${name}.`;
|
|
58
|
+
return `# ${name}
|
|
59
|
+
|
|
60
|
+
> ${tagline}
|
|
61
|
+
|
|
62
|
+
`;
|
|
63
|
+
}
|
|
64
|
+
function generateLlmsTxt(config, docs) {
|
|
65
|
+
const base = normalizeBase(config.siteUrl);
|
|
66
|
+
let out = buildHeader(config);
|
|
67
|
+
const mainDocs = docs.filter((d) => !d.optional);
|
|
68
|
+
const optionalDocs = docs.filter((d) => d.optional);
|
|
69
|
+
const sectionLabels = uniqueOrdered(mainDocs.map((d) => d.sectionLabel));
|
|
70
|
+
for (const label of sectionLabels) {
|
|
71
|
+
const sectionDocs = mainDocs.filter((d) => d.sectionLabel === label);
|
|
72
|
+
if (sectionDocs.length === 0) continue;
|
|
73
|
+
out += `## ${label}
|
|
74
|
+
|
|
75
|
+
`;
|
|
76
|
+
for (const doc of sectionDocs) {
|
|
77
|
+
const url = toAbsoluteUrl(base, doc.routePath);
|
|
78
|
+
const summary = firstParagraphSummary(doc.markdown);
|
|
79
|
+
if (summary) {
|
|
80
|
+
out += `- [${doc.title}](${url}): ${summary}
|
|
81
|
+
`;
|
|
82
|
+
} else {
|
|
83
|
+
out += `- [${doc.title}](${url})
|
|
84
|
+
`;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
out += "\n";
|
|
88
|
+
}
|
|
89
|
+
if (optionalDocs.length > 0) {
|
|
90
|
+
out += `## Optional
|
|
91
|
+
|
|
92
|
+
`;
|
|
93
|
+
for (const doc of optionalDocs) {
|
|
94
|
+
const url = toAbsoluteUrl(base, doc.routePath);
|
|
95
|
+
const summary = firstParagraphSummary(doc.markdown);
|
|
96
|
+
if (summary) {
|
|
97
|
+
out += `- [${doc.title}](${url}): ${summary}
|
|
98
|
+
`;
|
|
99
|
+
} else {
|
|
100
|
+
out += `- [${doc.title}](${url})
|
|
101
|
+
`;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
out += "\n";
|
|
105
|
+
}
|
|
106
|
+
return out.trimEnd() + "\n";
|
|
107
|
+
}
|
|
108
|
+
function generateLlmsFullTxt(config, docs) {
|
|
109
|
+
const base = normalizeBase(config.siteUrl);
|
|
110
|
+
let out = buildHeader(config);
|
|
111
|
+
for (const doc of docs) {
|
|
112
|
+
const url = toAbsoluteUrl(base, doc.routePath);
|
|
113
|
+
const body = stripFrontmatterAndH1(doc.markdown);
|
|
114
|
+
out += `## ${doc.title}
|
|
115
|
+
|
|
116
|
+
`;
|
|
117
|
+
out += `Source: ${url}
|
|
118
|
+
|
|
119
|
+
`;
|
|
120
|
+
if (body) {
|
|
121
|
+
out += body.trimEnd() + "\n\n";
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return out.trimEnd() + "\n";
|
|
125
|
+
}
|
|
126
|
+
function readMarkdownFile(filePath) {
|
|
127
|
+
return readFileSync(filePath, "utf-8");
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export {
|
|
131
|
+
generateLlmsTxt,
|
|
132
|
+
generateLlmsFullTxt,
|
|
133
|
+
readMarkdownFile
|
|
134
|
+
};
|
|
@@ -2,25 +2,31 @@ import {
|
|
|
2
2
|
loadUserConfig,
|
|
3
3
|
resolveConfig,
|
|
4
4
|
resolveSections
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-ZWF6VCSQ.js";
|
|
6
6
|
import {
|
|
7
7
|
scanDocs
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-77IOLCAM.js";
|
|
9
9
|
|
|
10
10
|
// src/node/check.ts
|
|
11
11
|
import { resolve, relative } from "path";
|
|
12
12
|
import { readFileSync, existsSync } from "fs";
|
|
13
13
|
import matter from "gray-matter";
|
|
14
|
-
var
|
|
14
|
+
var VALID_TYPES = [
|
|
15
|
+
"readme",
|
|
15
16
|
"documentation",
|
|
16
|
-
"internal",
|
|
17
17
|
"plan",
|
|
18
|
-
"research",
|
|
19
|
-
"decision",
|
|
20
18
|
"roadmap",
|
|
21
|
-
"changelog"
|
|
19
|
+
"changelog",
|
|
20
|
+
"handover"
|
|
21
|
+
];
|
|
22
|
+
var VALID_STATUSES = [
|
|
23
|
+
"draft",
|
|
24
|
+
"decided",
|
|
25
|
+
"in-progress",
|
|
26
|
+
"completed",
|
|
27
|
+
"archived",
|
|
28
|
+
"rejected"
|
|
22
29
|
];
|
|
23
|
-
var VALID_STATUSES = ["active", "superseded", "archived"];
|
|
24
30
|
function isStrictPath(filePath) {
|
|
25
31
|
const normalized = filePath.replace(/\\/g, "/");
|
|
26
32
|
return /\/docs\/plans(\/|$)/.test(normalized) || /\/docs\/internal(\/|$)/.test(normalized);
|
|
@@ -43,8 +49,8 @@ function validateFrontmatter(doc, userRoot) {
|
|
|
43
49
|
if (!rawFm.summary) {
|
|
44
50
|
issues.push({ file: rel, field: "summary", message: "missing required field", severity: "error" });
|
|
45
51
|
}
|
|
46
|
-
if (!rawFm.
|
|
47
|
-
issues.push({ file: rel, field: "
|
|
52
|
+
if (!rawFm.type) {
|
|
53
|
+
issues.push({ file: rel, field: "type", message: "recommended field missing (inferred from path)", severity: "warning" });
|
|
48
54
|
}
|
|
49
55
|
} else {
|
|
50
56
|
if (!rawFm.title) {
|
|
@@ -53,16 +59,16 @@ function validateFrontmatter(doc, userRoot) {
|
|
|
53
59
|
if (!rawFm.summary) {
|
|
54
60
|
issues.push({ file: rel, field: "summary", message: "recommended field missing", severity: "warning" });
|
|
55
61
|
}
|
|
56
|
-
if (!rawFm.
|
|
57
|
-
issues.push({ file: rel, field: "
|
|
62
|
+
if (!rawFm.type) {
|
|
63
|
+
issues.push({ file: rel, field: "type", message: "recommended field missing (inferred from path)", severity: "warning" });
|
|
58
64
|
}
|
|
59
65
|
}
|
|
60
|
-
if (rawFm.
|
|
61
|
-
if (!
|
|
66
|
+
if (rawFm.type !== void 0) {
|
|
67
|
+
if (!VALID_TYPES.includes(rawFm.type)) {
|
|
62
68
|
issues.push({
|
|
63
69
|
file: rel,
|
|
64
|
-
field: "
|
|
65
|
-
message: `invalid value "${rawFm.
|
|
70
|
+
field: "type",
|
|
71
|
+
message: `invalid value "${rawFm.type}" (allowed: ${VALID_TYPES.join(", ")})`,
|
|
66
72
|
severity: "error"
|
|
67
73
|
});
|
|
68
74
|
}
|
|
@@ -259,6 +265,8 @@ function levenshtein(a, b) {
|
|
|
259
265
|
}
|
|
260
266
|
|
|
261
267
|
export {
|
|
268
|
+
VALID_TYPES,
|
|
269
|
+
VALID_STATUSES,
|
|
262
270
|
checkFrontmatter,
|
|
263
271
|
checkLinks
|
|
264
272
|
};
|
|
@@ -6,17 +6,21 @@ import {
|
|
|
6
6
|
import {
|
|
7
7
|
mermaidContentHash
|
|
8
8
|
} from "./chunk-SCZZB7OE.js";
|
|
9
|
+
import {
|
|
10
|
+
generateLlmsFullTxt,
|
|
11
|
+
generateLlmsTxt
|
|
12
|
+
} from "./chunk-TVDWHKQF.js";
|
|
9
13
|
import {
|
|
10
14
|
clearifyPlugin
|
|
11
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-LVPVSOXK.js";
|
|
12
16
|
import {
|
|
13
17
|
loadUserConfig,
|
|
14
18
|
resolveConfig,
|
|
15
19
|
resolveSections
|
|
16
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-ZWF6VCSQ.js";
|
|
17
21
|
import {
|
|
18
22
|
buildSectionData
|
|
19
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-77IOLCAM.js";
|
|
20
24
|
|
|
21
25
|
// src/node/build.ts
|
|
22
26
|
import { build as viteBuild } from "vite";
|
|
@@ -72,6 +76,29 @@ function generateSitemap(routes, siteUrl) {
|
|
|
72
76
|
${urls.join("\n")}
|
|
73
77
|
</urlset>`;
|
|
74
78
|
}
|
|
79
|
+
function formatBytes(bytes) {
|
|
80
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
81
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
82
|
+
return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
|
|
83
|
+
}
|
|
84
|
+
function collectLlmsDocs(sections) {
|
|
85
|
+
const out = [];
|
|
86
|
+
for (const sd of sections) {
|
|
87
|
+
for (const doc of sd.docs) {
|
|
88
|
+
const title = doc.frontmatter.title ?? "Untitled";
|
|
89
|
+
const optional = (doc.frontmatter.order ?? 0) >= 9e3;
|
|
90
|
+
const markdown = existsSync(doc.filePath) ? readFileSync(doc.filePath, "utf-8") : "";
|
|
91
|
+
out.push({
|
|
92
|
+
title,
|
|
93
|
+
routePath: doc.routePath,
|
|
94
|
+
sectionLabel: sd.section.label,
|
|
95
|
+
markdown,
|
|
96
|
+
optional
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return out;
|
|
101
|
+
}
|
|
75
102
|
function generateRobotsTxt(siteUrl) {
|
|
76
103
|
const lines = ["User-agent: *", "Allow: /"];
|
|
77
104
|
if (siteUrl) {
|
|
@@ -312,6 +339,19 @@ async function buildSite() {
|
|
|
312
339
|
const sitemap = generateSitemap(sitemapRoutes, config.siteUrl);
|
|
313
340
|
writeFileSync(resolve(outDir, "sitemap.xml"), sitemap);
|
|
314
341
|
console.log(" Generated sitemap.xml");
|
|
342
|
+
if (config.generateLlmsTxt !== false) {
|
|
343
|
+
const llmsDocs = collectLlmsDocs(sectionDataList);
|
|
344
|
+
const llmsTxt = generateLlmsTxt(config, llmsDocs);
|
|
345
|
+
const llmsFullTxt = generateLlmsFullTxt(config, llmsDocs);
|
|
346
|
+
const llmsTxtPath = resolve(outDir, "llms.txt");
|
|
347
|
+
const llmsFullTxtPath = resolve(outDir, "llms-full.txt");
|
|
348
|
+
writeFileSync(llmsTxtPath, llmsTxt);
|
|
349
|
+
writeFileSync(llmsFullTxtPath, llmsFullTxt);
|
|
350
|
+
const llmsTxtSize = Buffer.byteLength(llmsTxt, "utf-8");
|
|
351
|
+
const llmsFullSize = Buffer.byteLength(llmsFullTxt, "utf-8");
|
|
352
|
+
console.log(` Generated ${llmsTxtPath} (${formatBytes(llmsTxtSize)})`);
|
|
353
|
+
console.log(` Generated ${llmsFullTxtPath} (${formatBytes(llmsFullSize)})`);
|
|
354
|
+
}
|
|
315
355
|
rmSync(ssrOutDir, { recursive: true, force: true });
|
|
316
356
|
console.log(" Cleaned up SSR build artifacts.");
|
|
317
357
|
if (mermaidStrategy === "build") {
|
|
@@ -117,7 +117,8 @@ var ClearifyConfigSchema = z.object({
|
|
|
117
117
|
hubProject: HubProjectPartialSchema,
|
|
118
118
|
customCss: z.string().optional(),
|
|
119
119
|
headTags: z.array(z.string()).optional(),
|
|
120
|
-
includeReadme: z.boolean().default(false)
|
|
120
|
+
includeReadme: z.boolean().default(false),
|
|
121
|
+
generateLlmsTxt: z.boolean().default(true)
|
|
121
122
|
});
|
|
122
123
|
var ClearifyDataSchema = z.object({
|
|
123
124
|
name: z.string().optional(),
|
|
@@ -265,6 +266,11 @@ function resolveConfig(userConfig = {}, root) {
|
|
|
265
266
|
if (!userConfig.name && root) {
|
|
266
267
|
parsed.name = detectProjectName(root);
|
|
267
268
|
}
|
|
269
|
+
if (parsed.generateLlmsTxt && !parsed.siteUrl) {
|
|
270
|
+
throw new Error(
|
|
271
|
+
"clearify config: `generateLlmsTxt` is enabled (default) but `siteUrl` is not set. Set `siteUrl` to the production URL of your docs site, or set `generateLlmsTxt: false` to disable."
|
|
272
|
+
);
|
|
273
|
+
}
|
|
268
274
|
return parsed;
|
|
269
275
|
}
|
|
270
276
|
function slugify(str) {
|
package/dist/node/core/config.js
CHANGED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { ClearifyConfig } from '../types/index.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A doc entry as consumed by the llms.txt generators. Produced from the
|
|
5
|
+
* scanned section data by callers (e.g. the build pipeline) so these
|
|
6
|
+
* functions stay pure string builders.
|
|
7
|
+
*/
|
|
8
|
+
interface LlmsDocEntry {
|
|
9
|
+
/** Page title (from frontmatter or derived). */
|
|
10
|
+
title: string;
|
|
11
|
+
/** Route path on the site, e.g. `/getting-started`. */
|
|
12
|
+
routePath: string;
|
|
13
|
+
/** Section label the page belongs to, e.g. `Documentation`. */
|
|
14
|
+
sectionLabel: string;
|
|
15
|
+
/** Raw markdown source (frontmatter optional, handled by the generator). */
|
|
16
|
+
markdown: string;
|
|
17
|
+
/**
|
|
18
|
+
* Optional flag. When true the page goes under the `## Optional` bucket at
|
|
19
|
+
* the end of llms.txt rather than the main section list. Use for auxiliary
|
|
20
|
+
* content like a changelog or roadmap.
|
|
21
|
+
*/
|
|
22
|
+
optional?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Generate the `llms.txt` index file content.
|
|
26
|
+
*
|
|
27
|
+
* Format:
|
|
28
|
+
* # {name}
|
|
29
|
+
*
|
|
30
|
+
* > {tagline}
|
|
31
|
+
*
|
|
32
|
+
* ## {Section label}
|
|
33
|
+
*
|
|
34
|
+
* - [Title](https://site/path): first-paragraph summary
|
|
35
|
+
* ...
|
|
36
|
+
*
|
|
37
|
+
* ## Optional
|
|
38
|
+
* - [Title](https://site/path): summary
|
|
39
|
+
*/
|
|
40
|
+
declare function generateLlmsTxt(config: ClearifyConfig, docs: LlmsDocEntry[]): string;
|
|
41
|
+
/**
|
|
42
|
+
* Generate the `llms-full.txt` bundle file content. Concatenates the entire
|
|
43
|
+
* markdown body of every doc under an H2 with a `Source:` line, so an LLM
|
|
44
|
+
* with no browsing can ingest the whole site from one file.
|
|
45
|
+
*/
|
|
46
|
+
declare function generateLlmsFullTxt(config: ClearifyConfig, docs: LlmsDocEntry[]): string;
|
|
47
|
+
/**
|
|
48
|
+
* Read a markdown file from disk. Returned as-is, including frontmatter.
|
|
49
|
+
* Exists here so callers in the build pipeline stay thin and the unit tests
|
|
50
|
+
* can stub in-memory markdown without touching the filesystem.
|
|
51
|
+
*/
|
|
52
|
+
declare function readMarkdownFile(filePath: string): string;
|
|
53
|
+
|
|
54
|
+
export { type LlmsDocEntry, generateLlmsFullTxt, generateLlmsTxt, readMarkdownFile };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import '../types/index.js';
|
|
2
|
-
export { D as DocFile, R as RootFileOptions, S as SectionData, b as buildNavigation, a as buildRoutes, c as buildSectionData, s as scanDocs } from './search.js';
|
|
2
|
+
export { D as DocFile, R as RootFileOptions, S as SectionData, b as buildNavigation, a as buildRoutes, c as buildSectionData, i as inferDocType, s as scanDocs } from './search.js';
|
|
@@ -2,12 +2,14 @@ import {
|
|
|
2
2
|
buildNavigation,
|
|
3
3
|
buildRoutes,
|
|
4
4
|
buildSectionData,
|
|
5
|
+
inferDocType,
|
|
5
6
|
scanDocs
|
|
6
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-77IOLCAM.js";
|
|
7
8
|
import "../chunk-5TD7NQIW.js";
|
|
8
9
|
export {
|
|
9
10
|
buildNavigation,
|
|
10
11
|
buildRoutes,
|
|
11
12
|
buildSectionData,
|
|
13
|
+
inferDocType,
|
|
12
14
|
scanDocs
|
|
13
15
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PageFrontmatter, ResolvedSection, SectionNavigation, RouteEntry, NavigationItem } from '../types/index.js';
|
|
1
|
+
import { PageFrontmatter, ResolvedSection, SectionNavigation, RouteEntry, NavigationItem, DocType } from '../types/index.js';
|
|
2
2
|
|
|
3
3
|
interface SearchEntry {
|
|
4
4
|
id: number;
|
|
@@ -11,6 +11,13 @@ interface SearchEntry {
|
|
|
11
11
|
}
|
|
12
12
|
declare function buildSearchIndex(docs: DocFile[], sectionId?: string, sectionLabel?: string): SearchEntry[];
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Infer the document `type` from its file path when frontmatter omits it.
|
|
16
|
+
* Mirrors the path-inference rules in the shared contract:
|
|
17
|
+
* knowledge-base/standards/document-lifecycle.md (the single source of truth).
|
|
18
|
+
* Returns undefined when nothing matches, leaving `type` unset (never filtered).
|
|
19
|
+
*/
|
|
20
|
+
declare function inferDocType(filePath: string): DocType | undefined;
|
|
14
21
|
interface DocFile {
|
|
15
22
|
filePath: string;
|
|
16
23
|
routePath: string;
|
|
@@ -33,4 +40,4 @@ interface RootFileOptions {
|
|
|
33
40
|
}
|
|
34
41
|
declare function buildSectionData(section: ResolvedSection, rootFiles?: RootFileOptions, customNavigation?: NavigationItem[] | null): SectionData;
|
|
35
42
|
|
|
36
|
-
export { type DocFile as D, type RootFileOptions as R, type SectionData as S, type SearchEntry, buildRoutes as a, buildNavigation as b, buildSearchIndex, buildSectionData as c, scanDocs as s };
|
|
43
|
+
export { type DocFile as D, type RootFileOptions as R, type SectionData as S, type SearchEntry, buildRoutes as a, buildNavigation as b, buildSearchIndex, buildSectionData as c, inferDocType as i, scanDocs as s };
|
package/dist/node/node/build.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildSite
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-XAX53RY5.js";
|
|
4
4
|
import "../chunk-PRTER35L.js";
|
|
5
5
|
import "../chunk-SCZZB7OE.js";
|
|
6
|
-
import "../chunk-
|
|
6
|
+
import "../chunk-TVDWHKQF.js";
|
|
7
|
+
import "../chunk-LVPVSOXK.js";
|
|
7
8
|
import "../chunk-B2Q23JW3.js";
|
|
8
|
-
import "../chunk-
|
|
9
|
+
import "../chunk-ZWF6VCSQ.js";
|
|
9
10
|
import "../chunk-AJBCHKBP.js";
|
|
10
11
|
import "../chunk-V7LLYIRO.js";
|
|
11
|
-
import "../chunk-
|
|
12
|
+
import "../chunk-77IOLCAM.js";
|
|
12
13
|
import "../chunk-5TD7NQIW.js";
|
|
13
14
|
export {
|
|
14
15
|
buildSite
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
import { DocStatus, DocType } from '../types/index.js';
|
|
2
|
+
|
|
1
3
|
interface CheckOptions {
|
|
2
4
|
frontmatterOnly?: boolean;
|
|
3
5
|
}
|
|
6
|
+
declare const VALID_TYPES: DocType[];
|
|
7
|
+
declare const VALID_STATUSES: DocStatus[];
|
|
4
8
|
declare function checkFrontmatter(): Promise<{
|
|
5
9
|
errors: number;
|
|
6
10
|
warnings: number;
|
|
7
11
|
}>;
|
|
8
12
|
declare function checkLinks(options?: CheckOptions): Promise<void>;
|
|
9
13
|
|
|
10
|
-
export { type CheckOptions, checkFrontmatter, checkLinks };
|
|
14
|
+
export { type CheckOptions, VALID_STATUSES, VALID_TYPES, checkFrontmatter, checkLinks };
|
package/dist/node/node/check.js
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
|
+
VALID_STATUSES,
|
|
3
|
+
VALID_TYPES,
|
|
2
4
|
checkFrontmatter,
|
|
3
5
|
checkLinks
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
+
} from "../chunk-V5J36LF5.js";
|
|
7
|
+
import "../chunk-ZWF6VCSQ.js";
|
|
6
8
|
import "../chunk-AJBCHKBP.js";
|
|
7
9
|
import "../chunk-V7LLYIRO.js";
|
|
8
|
-
import "../chunk-
|
|
10
|
+
import "../chunk-77IOLCAM.js";
|
|
9
11
|
import "../chunk-5TD7NQIW.js";
|
|
10
12
|
export {
|
|
13
|
+
VALID_STATUSES,
|
|
14
|
+
VALID_TYPES,
|
|
11
15
|
checkFrontmatter,
|
|
12
16
|
checkLinks
|
|
13
17
|
};
|
|
@@ -2,6 +2,7 @@ import * as vite from 'vite';
|
|
|
2
2
|
export { buildSite as build } from './build.js';
|
|
3
3
|
export { init } from './init.js';
|
|
4
4
|
export { checkFrontmatter, checkLinks } from './check.js';
|
|
5
|
+
import '../types/index.js';
|
|
5
6
|
|
|
6
7
|
declare function createServer(options?: {
|
|
7
8
|
port?: number;
|
package/dist/node/node/index.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildSite
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-XAX53RY5.js";
|
|
4
4
|
import {
|
|
5
5
|
remarkMermaidToComponent
|
|
6
6
|
} from "../chunk-PRTER35L.js";
|
|
7
7
|
import "../chunk-SCZZB7OE.js";
|
|
8
|
+
import "../chunk-TVDWHKQF.js";
|
|
8
9
|
import {
|
|
9
10
|
clearifyPlugin
|
|
10
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-LVPVSOXK.js";
|
|
11
12
|
import "../chunk-B2Q23JW3.js";
|
|
12
13
|
import {
|
|
13
14
|
init
|
|
@@ -15,14 +16,14 @@ import {
|
|
|
15
16
|
import {
|
|
16
17
|
checkFrontmatter,
|
|
17
18
|
checkLinks
|
|
18
|
-
} from "../chunk-
|
|
19
|
+
} from "../chunk-V5J36LF5.js";
|
|
19
20
|
import {
|
|
20
21
|
loadUserConfig,
|
|
21
22
|
resolveConfig
|
|
22
|
-
} from "../chunk-
|
|
23
|
+
} from "../chunk-ZWF6VCSQ.js";
|
|
23
24
|
import "../chunk-AJBCHKBP.js";
|
|
24
25
|
import "../chunk-V7LLYIRO.js";
|
|
25
|
-
import "../chunk-
|
|
26
|
+
import "../chunk-77IOLCAM.js";
|
|
26
27
|
import "../chunk-5TD7NQIW.js";
|
|
27
28
|
|
|
28
29
|
// src/node/index.ts
|
|
@@ -62,6 +62,12 @@ interface ClearifyConfig {
|
|
|
62
62
|
customCss?: string;
|
|
63
63
|
headTags?: string[];
|
|
64
64
|
includeReadme?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* When true (default), `clearify build` writes `llms.txt` and
|
|
67
|
+
* `llms-full.txt` into the output directory for AI agents and crawlers.
|
|
68
|
+
* Requires `siteUrl` to be set. Set to `false` to skip generation.
|
|
69
|
+
*/
|
|
70
|
+
generateLlmsTxt?: boolean;
|
|
65
71
|
}
|
|
66
72
|
interface NavigationItem {
|
|
67
73
|
label: string;
|
|
@@ -71,17 +77,35 @@ interface NavigationItem {
|
|
|
71
77
|
badgeColor?: string;
|
|
72
78
|
children?: NavigationItem[];
|
|
73
79
|
}
|
|
74
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Document type vocabulary. Source of truth:
|
|
82
|
+
* knowledge-base/standards/document-lifecycle.md (the single contract both
|
|
83
|
+
* the Session Dashboard and Clearify read). Keep this union in sync with the
|
|
84
|
+
* "Type" table in that standard. `category` (the legacy field) and its values
|
|
85
|
+
* (`internal`, `research`, `decision`) were reconciled away in favor of `type`.
|
|
86
|
+
*/
|
|
87
|
+
type DocType = 'readme' | 'documentation' | 'plan' | 'roadmap' | 'changelog' | 'handover';
|
|
88
|
+
/**
|
|
89
|
+
* Document status vocabulary. Source of truth:
|
|
90
|
+
* knowledge-base/standards/document-lifecycle.md.
|
|
91
|
+
*
|
|
92
|
+
* For `type: plan` this tracks the workflow lifecycle (all six values).
|
|
93
|
+
* For `type: documentation` only `draft` is meaningful (omitted = published).
|
|
94
|
+
* Status is optional on every type and a missing status is never filtered.
|
|
95
|
+
*/
|
|
96
|
+
type DocStatus = 'draft' | 'decided' | 'in-progress' | 'completed' | 'archived' | 'rejected';
|
|
75
97
|
interface PageFrontmatter {
|
|
76
98
|
title?: string;
|
|
77
99
|
description?: string;
|
|
78
100
|
icon?: string;
|
|
79
101
|
order?: number;
|
|
80
102
|
summary?: string;
|
|
81
|
-
|
|
103
|
+
/** See {@link DocType}. Inferred from path when omitted. */
|
|
104
|
+
type?: DocType;
|
|
82
105
|
tags?: string[];
|
|
83
106
|
projects?: string[];
|
|
84
|
-
status
|
|
107
|
+
/** See {@link DocStatus}. Missing status is treated as unset (not filtered). */
|
|
108
|
+
status?: DocStatus;
|
|
85
109
|
date?: string;
|
|
86
110
|
}
|
|
87
111
|
interface RouteEntry {
|
|
@@ -193,4 +217,4 @@ interface ClearifyDataConfig {
|
|
|
193
217
|
}
|
|
194
218
|
declare function defineConfig(config: Partial<ClearifyConfig>): Partial<ClearifyConfig>;
|
|
195
219
|
|
|
196
|
-
export { type ClearifyConfig, type ClearifyDataConfig, type
|
|
220
|
+
export { type ClearifyConfig, type ClearifyDataConfig, type DocStatus, type DocType, type HubConfig, type HubProject, type HubProjectPartial, type HubProjectPlacement, type HubProjectSource, type NavigationItem, type PageFrontmatter, type RemoteGitSource, type ResolvedSection, type RouteEntry, type SectionConfig, type SectionNavigation, defineConfig };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
clearifyPlugin
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-LVPVSOXK.js";
|
|
4
4
|
import "../chunk-B2Q23JW3.js";
|
|
5
|
-
import "../chunk-
|
|
5
|
+
import "../chunk-ZWF6VCSQ.js";
|
|
6
6
|
import "../chunk-AJBCHKBP.js";
|
|
7
7
|
import "../chunk-V7LLYIRO.js";
|
|
8
|
-
import "../chunk-
|
|
8
|
+
import "../chunk-77IOLCAM.js";
|
|
9
9
|
import "../chunk-5TD7NQIW.js";
|
|
10
10
|
export {
|
|
11
11
|
clearifyPlugin
|
package/package.json
CHANGED