@lucasviola/specwiki 1.0.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/LICENSE +21 -0
- package/README.md +227 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +226 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/generate.d.ts +5 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +197 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/init.d.ts +5 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +91 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/open.d.ts +8 -0
- package/dist/commands/open.d.ts.map +1 -0
- package/dist/commands/open.js +150 -0
- package/dist/commands/open.js.map +1 -0
- package/dist/config/loader.d.ts +20 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +143 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/patterns.d.ts +9 -0
- package/dist/config/patterns.d.ts.map +1 -0
- package/dist/config/patterns.js +159 -0
- package/dist/config/patterns.js.map +1 -0
- package/dist/core/Logger.d.ts +8 -0
- package/dist/core/Logger.d.ts.map +1 -0
- package/dist/core/Logger.js +33 -0
- package/dist/core/Logger.js.map +1 -0
- package/dist/core/paths.d.ts +8 -0
- package/dist/core/paths.d.ts.map +1 -0
- package/dist/core/paths.js +45 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/discover/specs.d.ts +11 -0
- package/dist/discover/specs.d.ts.map +1 -0
- package/dist/discover/specs.js +157 -0
- package/dist/discover/specs.js.map +1 -0
- package/dist/output/html/assets/highlight.css +101 -0
- package/dist/output/html/assets/search.js +368 -0
- package/dist/output/html/assets/specwiki.css +905 -0
- package/dist/output/html/renderer.d.ts +21 -0
- package/dist/output/html/renderer.d.ts.map +1 -0
- package/dist/output/html/renderer.js +203 -0
- package/dist/output/html/renderer.js.map +1 -0
- package/dist/output/html/search-index.d.ts +20 -0
- package/dist/output/html/search-index.d.ts.map +1 -0
- package/dist/output/html/search-index.js +46 -0
- package/dist/output/html/search-index.js.map +1 -0
- package/dist/output/html/templates/article.mustache +85 -0
- package/dist/output/html/templates/index.mustache +80 -0
- package/dist/output/html/templates/layout.mustache +205 -0
- package/dist/output/llms.d.ts +4 -0
- package/dist/output/llms.d.ts.map +1 -0
- package/dist/output/llms.js +44 -0
- package/dist/output/llms.js.map +1 -0
- package/dist/output/readme-index.d.ts +17 -0
- package/dist/output/readme-index.d.ts.map +1 -0
- package/dist/output/readme-index.js +71 -0
- package/dist/output/readme-index.js.map +1 -0
- package/dist/output/wiki.d.ts +11 -0
- package/dist/output/wiki.d.ts.map +1 -0
- package/dist/output/wiki.js +400 -0
- package/dist/output/wiki.js.map +1 -0
- package/dist/parse/markdown.d.ts +6 -0
- package/dist/parse/markdown.d.ts.map +1 -0
- package/dist/parse/markdown.js +225 -0
- package/dist/parse/markdown.js.map +1 -0
- package/dist/types.d.ts +96 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<meta name="generator" content="specwiki">
|
|
7
|
+
<script data-specwiki-theme-init>
|
|
8
|
+
(function () {
|
|
9
|
+
"use strict";
|
|
10
|
+
try {
|
|
11
|
+
var theme = localStorage.getItem("specwiki-theme");
|
|
12
|
+
if (theme === "light" || theme === "dark") {
|
|
13
|
+
document.documentElement.dataset.theme = theme;
|
|
14
|
+
}
|
|
15
|
+
} catch {}
|
|
16
|
+
})();
|
|
17
|
+
</script>
|
|
18
|
+
<title>{{pageTitle}} — Spec Wiki</title>
|
|
19
|
+
<link rel="stylesheet" href="assets/specwiki.css">
|
|
20
|
+
{{#includeHighlightCss}}
|
|
21
|
+
<link rel="stylesheet" href="assets/highlight.css">
|
|
22
|
+
{{/includeHighlightCss}}
|
|
23
|
+
</head>
|
|
24
|
+
<body class="specwiki">
|
|
25
|
+
<header class="specwiki-header">
|
|
26
|
+
<div class="specwiki-header-inner">
|
|
27
|
+
<button
|
|
28
|
+
id="specwiki-nav-toggle"
|
|
29
|
+
type="button"
|
|
30
|
+
hidden
|
|
31
|
+
class="specwiki-nav-toggle"
|
|
32
|
+
aria-label="Open category navigation"
|
|
33
|
+
aria-controls="specwiki-nav-drawer"
|
|
34
|
+
aria-expanded="false"
|
|
35
|
+
>
|
|
36
|
+
<span aria-hidden="true">☰</span>
|
|
37
|
+
<span class="specwiki-nav-toggle-label">Menu</span>
|
|
38
|
+
</button>
|
|
39
|
+
<a href="index.html" class="specwiki-logo"><span class="specwiki-logo-bracket">[[</span>specwiki<span class="specwiki-logo-bracket">]]</span></a>
|
|
40
|
+
{{#includeSearch}}
|
|
41
|
+
<div class="specwiki-search">
|
|
42
|
+
<label for="specwiki-search-input" class="specwiki-search-label">Search</label>
|
|
43
|
+
<input
|
|
44
|
+
type="search"
|
|
45
|
+
id="specwiki-search-input"
|
|
46
|
+
class="specwiki-search-input"
|
|
47
|
+
placeholder="Search specs…"
|
|
48
|
+
autocomplete="off"
|
|
49
|
+
role="combobox"
|
|
50
|
+
aria-autocomplete="list"
|
|
51
|
+
aria-controls="specwiki-search-results"
|
|
52
|
+
aria-expanded="false"
|
|
53
|
+
>
|
|
54
|
+
<div
|
|
55
|
+
id="specwiki-search-results"
|
|
56
|
+
class="specwiki-search-results"
|
|
57
|
+
role="listbox"
|
|
58
|
+
hidden
|
|
59
|
+
>
|
|
60
|
+
<div id="specwiki-search-groups"></div>
|
|
61
|
+
<p
|
|
62
|
+
id="specwiki-search-status"
|
|
63
|
+
class="specwiki-search-empty"
|
|
64
|
+
role="status"
|
|
65
|
+
aria-live="polite"
|
|
66
|
+
hidden
|
|
67
|
+
></p>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
{{/includeSearch}}
|
|
71
|
+
<button
|
|
72
|
+
type="button"
|
|
73
|
+
id="specwiki-theme-toggle"
|
|
74
|
+
hidden
|
|
75
|
+
class="specwiki-theme-toggle"
|
|
76
|
+
aria-label="Switch color theme"
|
|
77
|
+
aria-pressed="false"
|
|
78
|
+
>
|
|
79
|
+
<span aria-hidden="true">◐</span>
|
|
80
|
+
<span>Theme</span>
|
|
81
|
+
</button>
|
|
82
|
+
</div>
|
|
83
|
+
</header>
|
|
84
|
+
<div class="specwiki-main">
|
|
85
|
+
{{{body}}}
|
|
86
|
+
</div>
|
|
87
|
+
<div
|
|
88
|
+
id="specwiki-nav-backdrop"
|
|
89
|
+
class="specwiki-nav-backdrop"
|
|
90
|
+
hidden
|
|
91
|
+
aria-hidden="true"
|
|
92
|
+
></div>
|
|
93
|
+
{{#includeSearch}}
|
|
94
|
+
<script type="application/json" id="search-index">{{{searchIndexJson}}}</script>
|
|
95
|
+
<script src="assets/lunr.min.js"></script>
|
|
96
|
+
<script src="assets/search.js"></script>
|
|
97
|
+
{{/includeSearch}}
|
|
98
|
+
<script data-specwiki-nav-drawer>
|
|
99
|
+
(function () {
|
|
100
|
+
"use strict";
|
|
101
|
+
var root = document.documentElement;
|
|
102
|
+
var toggle = document.getElementById("specwiki-nav-toggle");
|
|
103
|
+
var drawer = document.getElementById("specwiki-nav-drawer");
|
|
104
|
+
var close = document.getElementById("specwiki-nav-close");
|
|
105
|
+
var backdrop = document.getElementById("specwiki-nav-backdrop");
|
|
106
|
+
if (!toggle || !drawer || !close || !backdrop) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
var narrow = window.matchMedia("(max-width: 719px)");
|
|
111
|
+
|
|
112
|
+
function setOpen(open, restoreFocus) {
|
|
113
|
+
root.classList.toggle("specwiki-nav-open", open);
|
|
114
|
+
toggle.setAttribute("aria-expanded", String(open));
|
|
115
|
+
drawer.setAttribute("aria-hidden", String(!open));
|
|
116
|
+
drawer.inert = !open;
|
|
117
|
+
backdrop.hidden = !open;
|
|
118
|
+
if (restoreFocus) {
|
|
119
|
+
toggle.focus();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function syncViewport() {
|
|
124
|
+
if (narrow.matches) {
|
|
125
|
+
setOpen(false, false);
|
|
126
|
+
} else {
|
|
127
|
+
root.classList.remove("specwiki-nav-open");
|
|
128
|
+
toggle.setAttribute("aria-expanded", "false");
|
|
129
|
+
drawer.removeAttribute("aria-hidden");
|
|
130
|
+
drawer.inert = false;
|
|
131
|
+
backdrop.hidden = true;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
root.classList.add("specwiki-nav-enhanced");
|
|
136
|
+
toggle.hidden = false;
|
|
137
|
+
close.hidden = false;
|
|
138
|
+
toggle.addEventListener("click", function () {
|
|
139
|
+
setOpen(toggle.getAttribute("aria-expanded") !== "true", false);
|
|
140
|
+
});
|
|
141
|
+
close.addEventListener("click", function () {
|
|
142
|
+
setOpen(false, true);
|
|
143
|
+
});
|
|
144
|
+
backdrop.addEventListener("click", function () {
|
|
145
|
+
setOpen(false, true);
|
|
146
|
+
});
|
|
147
|
+
document.addEventListener("keydown", function (event) {
|
|
148
|
+
if (
|
|
149
|
+
event.key === "Escape" &&
|
|
150
|
+
toggle.getAttribute("aria-expanded") === "true"
|
|
151
|
+
) {
|
|
152
|
+
setOpen(false, true);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
if (narrow.addEventListener) {
|
|
156
|
+
narrow.addEventListener("change", syncViewport);
|
|
157
|
+
}
|
|
158
|
+
syncViewport();
|
|
159
|
+
})();
|
|
160
|
+
</script>
|
|
161
|
+
<script data-specwiki-theme-toggle>
|
|
162
|
+
(function () {
|
|
163
|
+
"use strict";
|
|
164
|
+
var root = document.documentElement;
|
|
165
|
+
var toggle = document.getElementById("specwiki-theme-toggle");
|
|
166
|
+
if (!toggle) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function isDark() {
|
|
171
|
+
if (root.dataset.theme) {
|
|
172
|
+
return root.dataset.theme === "dark";
|
|
173
|
+
}
|
|
174
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function syncToggle() {
|
|
178
|
+
var dark = isDark();
|
|
179
|
+
toggle.setAttribute("aria-pressed", String(dark));
|
|
180
|
+
toggle.title = dark ? "Switch to light theme" : "Switch to dark theme";
|
|
181
|
+
toggle.hidden = false;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
toggle.addEventListener("click", function () {
|
|
185
|
+
var theme = isDark() ? "light" : "dark";
|
|
186
|
+
root.dataset.theme = theme;
|
|
187
|
+
try {
|
|
188
|
+
localStorage.setItem("specwiki-theme", theme);
|
|
189
|
+
} catch {}
|
|
190
|
+
syncToggle();
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
var preference = window.matchMedia("(prefers-color-scheme: dark)");
|
|
194
|
+
if (preference.addEventListener) {
|
|
195
|
+
preference.addEventListener("change", function () {
|
|
196
|
+
if (!root.dataset.theme) {
|
|
197
|
+
syncToggle();
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
syncToggle();
|
|
202
|
+
})();
|
|
203
|
+
</script>
|
|
204
|
+
</body>
|
|
205
|
+
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llms.d.ts","sourceRoot":"","sources":["../../src/output/llms.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAG5C,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,CAiCtD;AAED,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,QAAQ,EAAE,GAChB,OAAO,CAAC,MAAM,CAAC,CAgBjB"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { CATEGORY_LABELS } from "../config/patterns.js";
|
|
4
|
+
import { log } from "../core/Logger.js";
|
|
5
|
+
import { assertPathConfined } from "./wiki.js";
|
|
6
|
+
export function buildLlmsTxt(pages) {
|
|
7
|
+
const byCategory = new Map();
|
|
8
|
+
for (const page of pages) {
|
|
9
|
+
const categoryPages = byCategory.get(page.category) ?? [];
|
|
10
|
+
categoryPages.push(page);
|
|
11
|
+
byCategory.set(page.category, categoryPages);
|
|
12
|
+
}
|
|
13
|
+
const lines = [
|
|
14
|
+
"# Spec Wiki",
|
|
15
|
+
"",
|
|
16
|
+
"> Generated index of documentation discovered by specwiki.",
|
|
17
|
+
];
|
|
18
|
+
const categories = [...byCategory.keys()].sort((left, right) => (CATEGORY_LABELS[left] ?? left).localeCompare(CATEGORY_LABELS[right] ?? right));
|
|
19
|
+
for (const category of categories) {
|
|
20
|
+
lines.push("", `## ${CATEGORY_LABELS[category] ?? category}`, "");
|
|
21
|
+
for (const page of byCategory.get(category)) {
|
|
22
|
+
const description = page.description.trim();
|
|
23
|
+
lines.push(`- [${page.title}](${page.slug}.md)${description ? `: ${description}` : ""}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return `${lines.join("\n")}\n`;
|
|
27
|
+
}
|
|
28
|
+
export async function writeLlmsTxt(outputDir, pages) {
|
|
29
|
+
const filePath = path.join(outputDir, "llms.txt");
|
|
30
|
+
assertPathConfined(outputDir, filePath, "llms.txt");
|
|
31
|
+
try {
|
|
32
|
+
await fs.writeFile(filePath, buildLlmsTxt(pages), "utf-8");
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
log.error("output.error", {
|
|
36
|
+
relativePath: "llms.txt",
|
|
37
|
+
message: err instanceof Error ? err.message : String(err),
|
|
38
|
+
});
|
|
39
|
+
throw err;
|
|
40
|
+
}
|
|
41
|
+
log.info("output.write", { relativePath: "llms.txt" });
|
|
42
|
+
return filePath;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=llms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llms.js","sourceRoot":"","sources":["../../src/output/llms.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAExC,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C,MAAM,UAAU,YAAY,CAAC,KAAiB;IAC5C,MAAM,UAAU,GAAG,IAAI,GAAG,EAAsB,CAAC;IAEjD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,aAAa,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC1D,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzB,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,KAAK,GAAG;QACZ,aAAa;QACb,EAAE;QACF,4DAA4D;KAC7D,CAAC;IAEF,MAAM,UAAU,GAAG,CAAC,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAC7D,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,aAAa,CAC3C,eAAe,CAAC,KAAK,CAAC,IAAI,KAAK,CAChC,CACF,CAAC;IAEF,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,eAAe,CAAC,QAAQ,CAAC,IAAI,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;QAElE,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAE,EAAE,CAAC;YAC7C,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;YAC5C,KAAK,CAAC,IAAI,CACR,MAAM,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,IAAI,OAAO,WAAW,CAAC,CAAC,CAAC,KAAK,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAC7E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACjC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,SAAiB,EACjB,KAAiB;IAEjB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAClD,kBAAkB,CAAC,SAAS,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;IAEpD,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC;IAC7D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,KAAK,CAAC,cAAc,EAAE;YACxB,YAAY,EAAE,UAAU;YACxB,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SAC1D,CAAC,CAAC;QACH,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,CAAC;IACvD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ParsedSpec } from "../types.js";
|
|
2
|
+
export interface CategoryReadmeIntro {
|
|
3
|
+
content: string;
|
|
4
|
+
sourcePaths: string[];
|
|
5
|
+
}
|
|
6
|
+
export interface ReadmeIndexBindings {
|
|
7
|
+
rootIntro: string | null;
|
|
8
|
+
rootIntroSource: string | null;
|
|
9
|
+
categoryIntros: Map<string, CategoryReadmeIntro>;
|
|
10
|
+
readmeIndexCount: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function isReadmeFile(relativePath: string): boolean;
|
|
13
|
+
export declare function isRootReadme(relativePath: string): boolean;
|
|
14
|
+
export declare function categoryHasNonReadmePages(specs: ParsedSpec[], category: string): boolean;
|
|
15
|
+
export declare function resolveReadmeIndexBindings(specs: ParsedSpec[]): ReadmeIndexBindings;
|
|
16
|
+
export declare function logIndexSummary(readmeIndexCount: number): void;
|
|
17
|
+
//# sourceMappingURL=readme-index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readme-index.d.ts","sourceRoot":"","sources":["../../src/output/readme-index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IACjD,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAG1D;AAED,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAE1D;AA2BD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,UAAU,EAAE,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAKT;AAED,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,UAAU,EAAE,GAClB,mBAAmB,CAiDrB;AAED,wBAAgB,eAAe,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAE9D"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { log } from "../core/Logger.js";
|
|
3
|
+
export function isReadmeFile(relativePath) {
|
|
4
|
+
const normalized = relativePath.replace(/\\/g, "/");
|
|
5
|
+
return path.posix.basename(normalized).toLowerCase() === "readme.md";
|
|
6
|
+
}
|
|
7
|
+
export function isRootReadme(relativePath) {
|
|
8
|
+
return isReadmeFile(relativePath) && directoryKey(relativePath) === "";
|
|
9
|
+
}
|
|
10
|
+
function directoryKey(relativePath) {
|
|
11
|
+
const normalized = relativePath.replace(/\\/g, "/");
|
|
12
|
+
const dir = path.posix.dirname(normalized);
|
|
13
|
+
return dir === "." ? "" : dir;
|
|
14
|
+
}
|
|
15
|
+
function specsInDirectory(specs, directory) {
|
|
16
|
+
return specs.filter((spec) => directoryKey(spec.file.relativePath) === directory);
|
|
17
|
+
}
|
|
18
|
+
function hasOtherSpecsInDirectory(specs, readmePath) {
|
|
19
|
+
const directory = directoryKey(readmePath);
|
|
20
|
+
return specsInDirectory(specs, directory).some((spec) => spec.file.relativePath !== readmePath);
|
|
21
|
+
}
|
|
22
|
+
export function categoryHasNonReadmePages(specs, category) {
|
|
23
|
+
return specs.some((spec) => spec.file.category === category && !isReadmeFile(spec.file.relativePath));
|
|
24
|
+
}
|
|
25
|
+
export function resolveReadmeIndexBindings(specs) {
|
|
26
|
+
const categoryIntros = new Map();
|
|
27
|
+
let rootIntro = null;
|
|
28
|
+
let rootIntroSource = null;
|
|
29
|
+
let readmeIndexCount = 0;
|
|
30
|
+
const readmeSpecs = specs
|
|
31
|
+
.filter((spec) => isReadmeFile(spec.file.relativePath))
|
|
32
|
+
.sort((a, b) => a.file.relativePath.localeCompare(b.file.relativePath));
|
|
33
|
+
for (const readme of readmeSpecs) {
|
|
34
|
+
const { relativePath, category } = readme.file;
|
|
35
|
+
if (isRootReadme(relativePath)) {
|
|
36
|
+
rootIntro = readme.rawContent;
|
|
37
|
+
rootIntroSource = relativePath;
|
|
38
|
+
readmeIndexCount += 1;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (!hasOtherSpecsInDirectory(specs, relativePath)) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (!categoryHasNonReadmePages(specs, category)) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
log.info("parse.readme-index", { relativePath, category });
|
|
48
|
+
const existing = categoryIntros.get(category);
|
|
49
|
+
if (existing) {
|
|
50
|
+
existing.content = `${existing.content}\n\n${readme.rawContent}`;
|
|
51
|
+
existing.sourcePaths.push(relativePath);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
categoryIntros.set(category, {
|
|
55
|
+
content: readme.rawContent,
|
|
56
|
+
sourcePaths: [relativePath],
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
readmeIndexCount += 1;
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
rootIntro,
|
|
63
|
+
rootIntroSource,
|
|
64
|
+
categoryIntros,
|
|
65
|
+
readmeIndexCount,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
export function logIndexSummary(readmeIndexCount) {
|
|
69
|
+
log.info("output.index", { readmeIndexCount });
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=readme-index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readme-index.js","sourceRoot":"","sources":["../../src/output/readme-index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ParsedSpec, WikiOutput, WriteHtmlWikiOptions } from "../types.js";
|
|
2
|
+
export declare class PathTraversalError extends Error {
|
|
3
|
+
constructor(relativePath: string);
|
|
4
|
+
}
|
|
5
|
+
export declare function assertPathConfined(outputDir: string, targetPath: string, relativePathForLog: string): void;
|
|
6
|
+
export declare function pageSlug(spec: ParsedSpec): string;
|
|
7
|
+
export declare function buildWiki(specs: ParsedSpec[]): WikiOutput;
|
|
8
|
+
export declare function writeWiki(outputDir: string, wiki: WikiOutput): Promise<string[]>;
|
|
9
|
+
export declare function writeHtmlWiki(outputDir: string, wiki: WikiOutput, options?: WriteHtmlWikiOptions): Promise<string[]>;
|
|
10
|
+
export declare function escapeHtml(text: string): string;
|
|
11
|
+
//# sourceMappingURL=wiki.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wiki.d.ts","sourceRoot":"","sources":["../../src/output/wiki.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EAEV,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAOrB,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,YAAY,EAAE,MAAM;CAIjC;AAED,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,kBAAkB,EAAE,MAAM,GACzB,IAAI,CAYN;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAQjD;AA0ID,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,UAAU,CA0BzD;AAED,wBAAsB,SAAS,CAC7B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,MAAM,EAAE,CAAC,CA6CnB;AAED,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,UAAU,EAChB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,MAAM,EAAE,CAAC,CA8MnB;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO/C"}
|