@cudoment/cudoc 0.3.0 → 0.5.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/README.md +1 -1
- package/dist/document.d.ts +11 -1
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +38 -3
- package/dist/document.js.map +1 -1
- package/dist/internal/core/mdx/imports.d.ts +21 -0
- package/dist/internal/core/mdx/imports.d.ts.map +1 -0
- package/dist/internal/core/mdx/imports.js +80 -0
- package/dist/internal/core/mdx/imports.js.map +1 -0
- package/dist/internal/core/mdx/index.d.ts +1 -0
- package/dist/internal/core/mdx/index.d.ts.map +1 -1
- package/dist/internal/core/mdx/index.js +1 -0
- package/dist/internal/core/mdx/index.js.map +1 -1
- package/dist/internal/transforms/table-column-layout/create-table.d.ts.map +1 -1
- package/dist/internal/transforms/table-column-layout/create-table.js +40 -17
- package/dist/internal/transforms/table-column-layout/create-table.js.map +1 -1
- package/dist/internal/transforms/table-column-layout/index.d.ts +32 -0
- package/dist/internal/transforms/table-column-layout/index.d.ts.map +1 -1
- package/dist/internal/transforms/table-column-layout/index.js +66 -0
- package/dist/internal/transforms/table-column-layout/index.js.map +1 -1
- package/dist/markdown.d.ts +8 -0
- package/dist/markdown.d.ts.map +1 -1
- package/dist/markdown.js +9 -1
- package/dist/markdown.js.map +1 -1
- package/dist/node/check.d.ts +61 -0
- package/dist/node/check.d.ts.map +1 -0
- package/dist/node/check.js +543 -0
- package/dist/node/check.js.map +1 -0
- package/dist/node/cli.js +57 -11
- package/dist/node/cli.js.map +1 -1
- package/dist/node/dataset.d.ts +14 -1
- package/dist/node/dataset.d.ts.map +1 -1
- package/dist/node/dataset.js +40 -4
- package/dist/node/dataset.js.map +1 -1
- package/dist/node/glob.d.ts +21 -0
- package/dist/node/glob.d.ts.map +1 -0
- package/dist/node/glob.js +61 -0
- package/dist/node/glob.js.map +1 -0
- package/dist/node/library.d.ts +70 -4
- package/dist/node/library.d.ts.map +1 -1
- package/dist/node/library.js +196 -32
- package/dist/node/library.js.map +1 -1
- package/dist/node/local-target.d.ts +63 -0
- package/dist/node/local-target.d.ts.map +1 -0
- package/dist/node/local-target.js +81 -0
- package/dist/node/local-target.js.map +1 -0
- package/dist/node/prepare-embeds.d.ts +16 -2
- package/dist/node/prepare-embeds.d.ts.map +1 -1
- package/dist/node/prepare-embeds.js +42 -9
- package/dist/node/prepare-embeds.js.map +1 -1
- package/dist/node/report.d.ts +9 -0
- package/dist/node/report.d.ts.map +1 -0
- package/dist/node/report.js +48 -0
- package/dist/node/report.js.map +1 -0
- package/dist/node/resolve-embed.d.ts +88 -1
- package/dist/node/resolve-embed.d.ts.map +1 -1
- package/dist/node/resolve-embed.js +321 -63
- package/dist/node/resolve-embed.js.map +1 -1
- package/dist/node/roots.d.ts +67 -0
- package/dist/node/roots.d.ts.map +1 -0
- package/dist/node/roots.js +134 -0
- package/dist/node/roots.js.map +1 -0
- package/dist/node/storage.d.ts +21 -3
- package/dist/node/storage.d.ts.map +1 -1
- package/dist/node/storage.js +41 -12
- package/dist/node/storage.js.map +1 -1
- package/dist/node/watch.d.ts +81 -0
- package/dist/node/watch.d.ts.map +1 -0
- package/dist/node/watch.js +140 -0
- package/dist/node/watch.js.map +1 -0
- package/dist/paged.d.ts +34 -0
- package/dist/paged.d.ts.map +1 -0
- package/dist/paged.js +44 -0
- package/dist/paged.js.map +1 -0
- package/package.json +27 -2
- package/styles.css +5 -2
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whole-library reference checking.
|
|
3
|
+
*
|
|
4
|
+
* The build deliberately stops at the first unresolvable reference, because a
|
|
5
|
+
* site with a broken link should not ship. That makes it a poor way to find out
|
|
6
|
+
* what is wrong: an author fixes one link, rebuilds, and learns about the next.
|
|
7
|
+
* This walks every document instead and returns everything at once.
|
|
8
|
+
*
|
|
9
|
+
* It resolves through the same code the build uses, so a reference this reports
|
|
10
|
+
* as fine is one the build can resolve.
|
|
11
|
+
*/
|
|
12
|
+
import { DEFAULT_TABLE_COLUMNS, buildEmbedRow, extractCell, parseEmbedSpec, } from "./resolve-embed.js";
|
|
13
|
+
import { collectSections } from "../sections.js";
|
|
14
|
+
import { isExternalPath, resolveLocalTarget, } from "./local-target.js";
|
|
15
|
+
import { resolveRoots } from "./roots.js";
|
|
16
|
+
/** A heading id that a slugger disambiguated, such as `overview-1`. */
|
|
17
|
+
const SUFFIXED = /-\d+$/;
|
|
18
|
+
const walkNodes = (node, visit) => {
|
|
19
|
+
visit(node);
|
|
20
|
+
node.children?.forEach((child) => walkNodes(child, visit));
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Every anchor a document offers, and whether the author wrote it.
|
|
24
|
+
*
|
|
25
|
+
* Both halves matter. The ids answer whether a link resolves; the origin
|
|
26
|
+
* answers whether it will keep resolving, because a generated id depends on how
|
|
27
|
+
* many same-named headings precede it.
|
|
28
|
+
*/
|
|
29
|
+
export function collectAnchors(tree) {
|
|
30
|
+
const anchors = [];
|
|
31
|
+
walkNodes(tree, (node) => {
|
|
32
|
+
if (node.type !== "heading")
|
|
33
|
+
return;
|
|
34
|
+
const id = node.data?.hProperties?.id;
|
|
35
|
+
if (typeof id === "string" && id)
|
|
36
|
+
anchors.push({ id, explicit: node.data?.cudoc?.explicitId === true });
|
|
37
|
+
});
|
|
38
|
+
return anchors;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Where a reference sits in the original Markdown.
|
|
42
|
+
*
|
|
43
|
+
* Collection strips positions from the stored tree on purpose: a persisted AST
|
|
44
|
+
* should not carry coordinates that go stale the moment the file is edited. The
|
|
45
|
+
* source snapshot is still here, so the first occurrence of the reference text
|
|
46
|
+
* gives an author somewhere real to jump to. A reference repeated in one
|
|
47
|
+
* document reports the first one; fixing it means fixing both anyway.
|
|
48
|
+
*/
|
|
49
|
+
/**
|
|
50
|
+
* The forms a reference might take in the original Markdown.
|
|
51
|
+
*
|
|
52
|
+
* The tree holds what the host compiler produced, and hosts rewrite link
|
|
53
|
+
* destinations: Nextra drops the extension, VitePress rewrites it to `.html`
|
|
54
|
+
* and prefixes `./`. The author wrote `reference.md#limit`, so searching the
|
|
55
|
+
* source for the compiled form finds nothing. These are tried in turn.
|
|
56
|
+
*/
|
|
57
|
+
const sourceForms = (reference) => {
|
|
58
|
+
const [pathname, anchor] = reference.split("#");
|
|
59
|
+
if (!pathname)
|
|
60
|
+
return [reference];
|
|
61
|
+
const bare = pathname.replace(/^\.\//, "").replace(/\.(?:mdx?|html?)$/i, "");
|
|
62
|
+
const suffix = anchor === undefined ? "" : `#${anchor}`;
|
|
63
|
+
return [
|
|
64
|
+
...new Set([
|
|
65
|
+
reference,
|
|
66
|
+
`${bare}.md${suffix}`,
|
|
67
|
+
`${bare}.mdx${suffix}`,
|
|
68
|
+
`${bare}${suffix}`,
|
|
69
|
+
]),
|
|
70
|
+
];
|
|
71
|
+
};
|
|
72
|
+
const locate = (text, reference, skip = 0) => {
|
|
73
|
+
// A reference is often a prefix of a longer one on an earlier line, as
|
|
74
|
+
// `guide.md#limit` is of `guide.md#limits`. Prefer an occurrence that ends
|
|
75
|
+
// where a Markdown destination ends, and fall back to a plain search.
|
|
76
|
+
const ends = new Set([")", "]", '"', "'", " ", "\t", "\n", ""]);
|
|
77
|
+
let at = -1;
|
|
78
|
+
let remaining = skip;
|
|
79
|
+
for (let i = text.indexOf(reference); i >= 0; i = text.indexOf(reference, i + 1))
|
|
80
|
+
if (ends.has(text[i + reference.length] ?? "")) {
|
|
81
|
+
if (remaining-- > 0)
|
|
82
|
+
continue;
|
|
83
|
+
at = i;
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
if (at < 0)
|
|
87
|
+
at = text.indexOf(reference);
|
|
88
|
+
if (at < 0)
|
|
89
|
+
return undefined;
|
|
90
|
+
const before = text.slice(0, at);
|
|
91
|
+
const line = before.split("\n").length;
|
|
92
|
+
const column = at - (before.lastIndexOf("\n") + 1) + 1;
|
|
93
|
+
const offset = at;
|
|
94
|
+
return {
|
|
95
|
+
start: { line, column, offset },
|
|
96
|
+
end: {
|
|
97
|
+
line,
|
|
98
|
+
column: column + reference.length,
|
|
99
|
+
offset: offset + reference.length,
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Components in a tree that no portable renderer can turn into HTML.
|
|
105
|
+
*
|
|
106
|
+
* `documentToHast` renders an unknown `mdx*` or directive node only when the
|
|
107
|
+
* caller supplies an explicit HTML callback for it, and throws otherwise. A
|
|
108
|
+
* component sitting in a document is the author's business, because the host
|
|
109
|
+
* that owns it renders it. A component sitting in a section that an embed
|
|
110
|
+
* copies is different: the copy lands in another document, and standalone HTML
|
|
111
|
+
* export then has to render a name it was never given.
|
|
112
|
+
*
|
|
113
|
+
* `mdxjsEsm` and `yaml` are excluded because the renderer drops them rather
|
|
114
|
+
* than failing.
|
|
115
|
+
*/
|
|
116
|
+
const unportableComponents = (tree) => {
|
|
117
|
+
const names = new Set();
|
|
118
|
+
walkNodes(tree, (node) => {
|
|
119
|
+
if (node.type === "mdxjsEsm" || node.type === "yaml")
|
|
120
|
+
return;
|
|
121
|
+
if (!node.type.startsWith("mdx") && !node.type.endsWith("Directive"))
|
|
122
|
+
return;
|
|
123
|
+
names.add(node.name ? `<${node.name}>` : node.type);
|
|
124
|
+
});
|
|
125
|
+
return [...names];
|
|
126
|
+
};
|
|
127
|
+
/** The visible text of a heading, used to spot an anchor that failed to parse. */
|
|
128
|
+
const headingText = (node) => {
|
|
129
|
+
let text = "";
|
|
130
|
+
walkNodes(node, (child) => {
|
|
131
|
+
if (child.type === "text" && typeof child.value === "string")
|
|
132
|
+
text += child.value;
|
|
133
|
+
});
|
|
134
|
+
return text;
|
|
135
|
+
};
|
|
136
|
+
/** The line each `cudoc-embed` fence opens on, in source order. */
|
|
137
|
+
const embedFenceLines = (text) => {
|
|
138
|
+
const lines = [];
|
|
139
|
+
text.split("\n").forEach((line, index) => {
|
|
140
|
+
if (/^\s*(?:`{3,}|~{3,})cudoc-embed\s*$/.test(line))
|
|
141
|
+
lines.push(index + 1);
|
|
142
|
+
});
|
|
143
|
+
return lines;
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Whether a rule finds anything, asked the way the resolver asks it.
|
|
147
|
+
*
|
|
148
|
+
* Rules run in order and each sees the previous one's output, so a later rule
|
|
149
|
+
* can legitimately depend on an earlier substitution. Testing them against the
|
|
150
|
+
* untouched slice would report those as unmatched.
|
|
151
|
+
*/
|
|
152
|
+
const matchedRules = (slice, rules) => {
|
|
153
|
+
const matched = [];
|
|
154
|
+
let value = slice;
|
|
155
|
+
rules.forEach((rule, index) => {
|
|
156
|
+
try {
|
|
157
|
+
if (rule.regex) {
|
|
158
|
+
const pattern = new RegExp(rule.find, rule.flags ?? "g");
|
|
159
|
+
matched[index] = pattern.test(value);
|
|
160
|
+
value = value.replace(new RegExp(rule.find, rule.flags ?? "g"), rule.replace);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
matched[index] = value.includes(rule.find);
|
|
164
|
+
value = value.split(rule.find).join(rule.replace);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
// An unusable pattern is the resolver's error to raise, not a miss.
|
|
169
|
+
matched[index] = true;
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
return matched;
|
|
173
|
+
};
|
|
174
|
+
export function checkReferences(library, options = {}) {
|
|
175
|
+
const roots = options.roots !== undefined || options.sourceRoot !== undefined
|
|
176
|
+
? resolveRoots(options)
|
|
177
|
+
: library.roots;
|
|
178
|
+
const targetRoots = {
|
|
179
|
+
assetDirs: options.assetDirs,
|
|
180
|
+
withoutBase: options.withoutBase,
|
|
181
|
+
externalPaths: options.externalPaths,
|
|
182
|
+
};
|
|
183
|
+
const ignore = new Set(options.ignore ?? []);
|
|
184
|
+
const issues = [];
|
|
185
|
+
let checkedReferences = 0;
|
|
186
|
+
// Where a copied component can render at all: an MDX host compiles the
|
|
187
|
+
// spliced nodes with its own component mapping, a Markdown host cannot.
|
|
188
|
+
const mdxHost = ["next", "docusaurus", "nextra"].includes(library.options.host ?? "");
|
|
189
|
+
const anchorsById = new Map(library.documents.map((doc) => [doc.id, collectAnchors(doc.tree)]));
|
|
190
|
+
const byId = new Map(library.documents.map((doc) => [doc.id, doc]));
|
|
191
|
+
const report = (doc,
|
|
192
|
+
/** A `position` given here wins; otherwise it is recovered from the source. */
|
|
193
|
+
issue,
|
|
194
|
+
/** Which occurrence of the reference to point at. A duplicate wants the later one. */
|
|
195
|
+
skip = 0) => {
|
|
196
|
+
if (ignore.has(issue.code))
|
|
197
|
+
return;
|
|
198
|
+
issues.push({
|
|
199
|
+
...issue,
|
|
200
|
+
documentId: doc.id,
|
|
201
|
+
sourcePath: doc.sourcePath,
|
|
202
|
+
position: issue.position ??
|
|
203
|
+
sourceForms(issue.reference).reduce((found, form) => found ?? locate(doc.source?.text ?? "", form, skip), undefined),
|
|
204
|
+
});
|
|
205
|
+
};
|
|
206
|
+
/** Resolves `other.md#anchor` or a bare `#anchor` against the library. */
|
|
207
|
+
const checkDocumentLink = (doc, url) => {
|
|
208
|
+
const [pathname, anchor] = url.split("#");
|
|
209
|
+
let target = doc;
|
|
210
|
+
if (pathname) {
|
|
211
|
+
const found = resolveDocument(doc, pathname);
|
|
212
|
+
if (!found)
|
|
213
|
+
return false; // not a document link; the asset pass handles it
|
|
214
|
+
target = found;
|
|
215
|
+
}
|
|
216
|
+
if (!anchor)
|
|
217
|
+
return true;
|
|
218
|
+
const anchors = anchorsById.get(target.id) ?? [];
|
|
219
|
+
const match = anchors.find((entry) => entry.id === anchor);
|
|
220
|
+
if (!match) {
|
|
221
|
+
report(doc, {
|
|
222
|
+
code: "missing-anchor",
|
|
223
|
+
severity: "error",
|
|
224
|
+
message: `${target.id} has no anchor #${anchor}`,
|
|
225
|
+
reference: url,
|
|
226
|
+
available: anchors.map((entry) => entry.id),
|
|
227
|
+
});
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
if (!match.explicit && SUFFIXED.test(match.id))
|
|
231
|
+
report(doc, {
|
|
232
|
+
code: "unstable-anchor-link",
|
|
233
|
+
severity: "warning",
|
|
234
|
+
message: `#${anchor} in ${target.id} is generated from a repeated heading; inserting another one above it moves this link to a different section. Give the target heading an explicit anchor.`,
|
|
235
|
+
reference: url,
|
|
236
|
+
});
|
|
237
|
+
return true;
|
|
238
|
+
};
|
|
239
|
+
/**
|
|
240
|
+
* The document a link names, if it names one in this library.
|
|
241
|
+
*
|
|
242
|
+
* Hosts do not agree on how a link looks once compiled. Docusaurus and
|
|
243
|
+
* Next.js leave `reference.md`, Nextra drops the extension, and VitePress
|
|
244
|
+
* rewrites it to the deployed `./reference.html`. All three mean the same
|
|
245
|
+
* document, so any of those endings resolves to the same id. A relative
|
|
246
|
+
* path resolves in the library's coordinates, so it can reach another root
|
|
247
|
+
* exactly when the bases mirror the directories; a root-relative one names
|
|
248
|
+
* a library path directly, and then once more with the deployment base
|
|
249
|
+
* removed, the way the exporter looks a route up.
|
|
250
|
+
*/
|
|
251
|
+
const resolveDocument = (doc, pathname) => {
|
|
252
|
+
if (/^(?:[a-z][\w+.-]*:|\/\/)/i.test(pathname))
|
|
253
|
+
return undefined;
|
|
254
|
+
const decoded = decodeURIComponent(pathname);
|
|
255
|
+
const toId = (value) => normalize(value).replace(/\.(?:mdx?|html?)$/i, "");
|
|
256
|
+
if (!decoded.startsWith("/"))
|
|
257
|
+
return byId.get(toId(posixJoin(dirname(doc.sourcePath), decoded)));
|
|
258
|
+
const direct = byId.get(toId(decoded.slice(1)));
|
|
259
|
+
if (direct || !options.withoutBase)
|
|
260
|
+
return direct;
|
|
261
|
+
return byId.get(toId(options.withoutBase(decoded).replace(/^\//, "")));
|
|
262
|
+
};
|
|
263
|
+
for (const doc of library.documents) {
|
|
264
|
+
// Anchors the document declares, before anything references them.
|
|
265
|
+
const seen = new Set();
|
|
266
|
+
const counts = new Map();
|
|
267
|
+
walkNodes(doc.tree, (node) => {
|
|
268
|
+
if (node.type !== "heading")
|
|
269
|
+
return;
|
|
270
|
+
const id = node.data?.hProperties?.id;
|
|
271
|
+
if (typeof id === "string" && id) {
|
|
272
|
+
const before = counts.get(id) ?? 0;
|
|
273
|
+
if (before)
|
|
274
|
+
report(doc, {
|
|
275
|
+
code: "duplicate-anchor",
|
|
276
|
+
severity: "error",
|
|
277
|
+
message: `duplicate heading anchor #${id}`,
|
|
278
|
+
reference: `#${id}`,
|
|
279
|
+
}, before);
|
|
280
|
+
counts.set(id, before + 1);
|
|
281
|
+
seen.add(id);
|
|
282
|
+
}
|
|
283
|
+
// An anchor marker with no id never becomes an anchor. It stays in the
|
|
284
|
+
// heading text instead, and silently joins the generated slug.
|
|
285
|
+
const text = headingText(node);
|
|
286
|
+
const empty = text.match(/\((#)\)|\{(#)\}/);
|
|
287
|
+
if (empty)
|
|
288
|
+
report(doc, {
|
|
289
|
+
code: "empty-anchor",
|
|
290
|
+
severity: "error",
|
|
291
|
+
message: `empty anchor marker left in the heading text: "${text.trim()}"`,
|
|
292
|
+
reference: empty[0],
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
walkNodes(doc.tree, (node) => {
|
|
296
|
+
const url = node.type === "link" || node.type === "image" ? node.url : undefined;
|
|
297
|
+
if (typeof url !== "string" || !url)
|
|
298
|
+
return;
|
|
299
|
+
// A heading permalink is machinery the host inserted, not something an
|
|
300
|
+
// author wrote. VitePress and Eleventy add one per heading, and counting
|
|
301
|
+
// them would report every generated anchor as an unstable link.
|
|
302
|
+
if (node.data?.cudoc?.kind === "permalink")
|
|
303
|
+
return;
|
|
304
|
+
checkedReferences++;
|
|
305
|
+
if (/^(?:[a-z][\w+.-]*:|\/\/)/i.test(url))
|
|
306
|
+
return; // external
|
|
307
|
+
// Another application's path on the same host: nothing here to check.
|
|
308
|
+
if (isExternalPath(url, options.externalPaths))
|
|
309
|
+
return;
|
|
310
|
+
if (node.type === "link" && checkDocumentLink(doc, url))
|
|
311
|
+
return;
|
|
312
|
+
if (url.startsWith("#"))
|
|
313
|
+
return; // handled above as a same-document anchor
|
|
314
|
+
if (!roots)
|
|
315
|
+
return;
|
|
316
|
+
const target = resolveLocalTarget(url, doc.sourcePath, {
|
|
317
|
+
...targetRoots,
|
|
318
|
+
roots,
|
|
319
|
+
});
|
|
320
|
+
if (target.kind === "missing")
|
|
321
|
+
report(doc, {
|
|
322
|
+
code: node.type === "image" ? "missing-asset" : "missing-document",
|
|
323
|
+
severity: "error",
|
|
324
|
+
message: node.type === "image"
|
|
325
|
+
? `no file for image ${url}; check the collection roots and assetDirs`
|
|
326
|
+
: `no document or file for ${url}`,
|
|
327
|
+
reference: url,
|
|
328
|
+
});
|
|
329
|
+
});
|
|
330
|
+
// Fence lines are read from the source because collection strips positions,
|
|
331
|
+
// and they are what turns a YAML error's own coordinate into a file one.
|
|
332
|
+
const fences = embedFenceLines(doc.source?.text ?? "");
|
|
333
|
+
let blockNumber = 0;
|
|
334
|
+
walkNodes(doc.tree, (node) => {
|
|
335
|
+
if (node.type !== "code" || node.lang !== "cudoc-embed")
|
|
336
|
+
return;
|
|
337
|
+
const fence = fences[blockNumber++];
|
|
338
|
+
let spec;
|
|
339
|
+
try {
|
|
340
|
+
spec = parseEmbedSpec(node.value ?? "");
|
|
341
|
+
}
|
|
342
|
+
catch (error) {
|
|
343
|
+
// The YAML parser counts from the start of the block; an author counts
|
|
344
|
+
// from the start of the file. Add the fence so both agree.
|
|
345
|
+
const at = error.linePos?.[0];
|
|
346
|
+
const line = fence === undefined ? undefined : fence + (at?.line ?? 0);
|
|
347
|
+
report(doc, {
|
|
348
|
+
code: "invalid-embed-spec",
|
|
349
|
+
severity: "error",
|
|
350
|
+
// The parser's own "at line 3, column 24" is dropped: it counts from
|
|
351
|
+
// the block, and the position below already says the same thing in
|
|
352
|
+
// the file's own coordinates.
|
|
353
|
+
message: error.message
|
|
354
|
+
.replace(/^cudoc: /, "")
|
|
355
|
+
.split("\n")[0]
|
|
356
|
+
.replace(/\s*at line \d+, column \d+:?\s*$/, "")
|
|
357
|
+
.trim(),
|
|
358
|
+
reference: `embed block ${blockNumber}`,
|
|
359
|
+
position: line === undefined
|
|
360
|
+
? undefined
|
|
361
|
+
: {
|
|
362
|
+
start: { line, column: at?.col ?? 1 },
|
|
363
|
+
end: { line, column: at?.col ?? 1 },
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
for (const reference of spec.sources ?? []) {
|
|
369
|
+
checkedReferences++;
|
|
370
|
+
const [pathname, anchor] = String(reference).split("#");
|
|
371
|
+
const target = pathname
|
|
372
|
+
? resolveDocument(doc, pathname)
|
|
373
|
+
: byId.get(doc.id);
|
|
374
|
+
if (!target) {
|
|
375
|
+
report(doc, {
|
|
376
|
+
code: "missing-embed-source",
|
|
377
|
+
severity: "error",
|
|
378
|
+
message: `embed source ${reference} does not name a collected document`,
|
|
379
|
+
reference: String(reference),
|
|
380
|
+
});
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
const anchors = anchorsById.get(target.id) ?? [];
|
|
384
|
+
if (anchor && !anchors.some((entry) => entry.id === anchor)) {
|
|
385
|
+
report(doc, {
|
|
386
|
+
code: "missing-embed-anchor",
|
|
387
|
+
severity: "error",
|
|
388
|
+
message: `${target.id} has no section #${anchor} to embed`,
|
|
389
|
+
reference: String(reference),
|
|
390
|
+
available: anchors.map((entry) => entry.id),
|
|
391
|
+
});
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
394
|
+
// The same selection the resolver will apply, so what is inspected is
|
|
395
|
+
// what would actually be copied. `select.anchors` can name a section
|
|
396
|
+
// that does not exist, which `collectSections` rejects; the build hits
|
|
397
|
+
// the same error, so it is reported rather than swallowed.
|
|
398
|
+
const selection = anchor ? { anchors: [anchor] } : spec.select;
|
|
399
|
+
let copied;
|
|
400
|
+
try {
|
|
401
|
+
copied = selection
|
|
402
|
+
? collectSections(target.tree, selection)
|
|
403
|
+
: [{ anchorId: undefined, tree: target.tree }];
|
|
404
|
+
}
|
|
405
|
+
catch (error) {
|
|
406
|
+
report(doc, {
|
|
407
|
+
code: "missing-embed-anchor",
|
|
408
|
+
severity: "error",
|
|
409
|
+
message: `${target.id}: ${error.message.replace(/^cudoc: /, "")}`,
|
|
410
|
+
reference: String(reference),
|
|
411
|
+
available: anchors.map((entry) => entry.id),
|
|
412
|
+
});
|
|
413
|
+
continue;
|
|
414
|
+
}
|
|
415
|
+
// Replacement runs on the original Markdown, not the tree, so the
|
|
416
|
+
// slices are recomputed the way `transformedSection` cuts them. A rule
|
|
417
|
+
// that matches no slice changed nothing, and the embed silently shows
|
|
418
|
+
// the source's own wording in a place written to expect otherwise.
|
|
419
|
+
const rules = spec.replace ?? [];
|
|
420
|
+
if (rules.length && target.source) {
|
|
421
|
+
const matched = rules.map(() => false);
|
|
422
|
+
for (const section of copied) {
|
|
423
|
+
const range = section.anchorId
|
|
424
|
+
? target.source.sections[section.anchorId]
|
|
425
|
+
: undefined;
|
|
426
|
+
const slice = range
|
|
427
|
+
? target.source.text.slice(range.start, spec.select?.includeChildren === false
|
|
428
|
+
? (range.ownEnd ?? range.end)
|
|
429
|
+
: range.end)
|
|
430
|
+
: target.source.text;
|
|
431
|
+
matchedRules(slice, rules).forEach((hit, index) => {
|
|
432
|
+
if (hit)
|
|
433
|
+
matched[index] = true;
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
rules.forEach((rule, index) => {
|
|
437
|
+
if (matched[index])
|
|
438
|
+
return;
|
|
439
|
+
report(doc, {
|
|
440
|
+
code: "unmatched-embed-replacement",
|
|
441
|
+
severity: "warning",
|
|
442
|
+
message: `replacement ${index + 1} found no "${rule.find}" in what this embed copies from ${target.id}, so nothing was changed. The source may have been reworded${rule.regex ? "" : "; literal rules are case-sensitive"}.`,
|
|
443
|
+
reference: rule.find,
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
// A table carries extracted text and nothing else, so whatever else
|
|
448
|
+
// the body holds never travels. What can go wrong is a column that
|
|
449
|
+
// finds nothing in a row: the resolver renders an empty cell, and the
|
|
450
|
+
// author would only notice by reading the page.
|
|
451
|
+
if (typeof spec.render === "object" && spec.render?.type === "table") {
|
|
452
|
+
const columns = spec.render.columns ?? DEFAULT_TABLE_COLUMNS;
|
|
453
|
+
for (const section of copied) {
|
|
454
|
+
const row = buildEmbedRow(target, section.anchorId, section.tree);
|
|
455
|
+
columns.forEach((column, index) => {
|
|
456
|
+
// A shorthand column is best effort: `summary` of a section
|
|
457
|
+
// that opens with a table is legitimately blank. A column
|
|
458
|
+
// written as a mapping states what every row must have.
|
|
459
|
+
if (typeof column === "string")
|
|
460
|
+
return;
|
|
461
|
+
let problem;
|
|
462
|
+
try {
|
|
463
|
+
problem = extractCell(library, column, row, {
|
|
464
|
+
documentId: doc.id,
|
|
465
|
+
}).problem;
|
|
466
|
+
}
|
|
467
|
+
catch (error) {
|
|
468
|
+
// An extractor the configuration does not register is a
|
|
469
|
+
// setting problem, reported once per column like a bad key.
|
|
470
|
+
report(doc, {
|
|
471
|
+
code: "invalid-embed-spec",
|
|
472
|
+
severity: "error",
|
|
473
|
+
message: error.message.replace(/^cudoc: /, ""),
|
|
474
|
+
reference: String(reference),
|
|
475
|
+
});
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
if (!problem)
|
|
479
|
+
return;
|
|
480
|
+
const header = typeof column === "string"
|
|
481
|
+
? column
|
|
482
|
+
: (column.header ??
|
|
483
|
+
(typeof column.value === "string" ? column.value : ""));
|
|
484
|
+
report(doc, {
|
|
485
|
+
code: "empty-embed-cell",
|
|
486
|
+
severity: "warning",
|
|
487
|
+
message: `column ${index + 1}${header ? ` "${header}"` : ""} is empty for the row from ${row.document.id}${row.section.anchorId ? `#${row.section.anchorId}` : ""}: ${problem}`,
|
|
488
|
+
reference: String(reference),
|
|
489
|
+
});
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
continue;
|
|
493
|
+
}
|
|
494
|
+
const names = [
|
|
495
|
+
...new Set(copied.flatMap((section) => unportableComponents(section.tree))),
|
|
496
|
+
];
|
|
497
|
+
if (names.length)
|
|
498
|
+
report(doc, {
|
|
499
|
+
code: "unportable-embed-component",
|
|
500
|
+
severity: "warning",
|
|
501
|
+
message: mdxHost
|
|
502
|
+
? `this embed copies ${names.join(", ")} out of ${target.id}. The host renders them where the copy is spliced in, but standalone HTML export has no renderer for them and fails. Keep embedded sections to Markdown, or pass a renderer for each name.`
|
|
503
|
+
: `this embed copies ${names.join(", ")} out of ${target.id}. Neither this host nor standalone HTML export can render them. Keep embedded sections to Markdown, or pass a renderer for each name.`,
|
|
504
|
+
reference: String(reference),
|
|
505
|
+
});
|
|
506
|
+
// A component the source file imports for itself does not travel
|
|
507
|
+
// with the copy: the export drops the import, and the embedding
|
|
508
|
+
// document has no binding for the name unless it imports it too.
|
|
509
|
+
const orphaned = names
|
|
510
|
+
.map((name) => name.replace(/^<|>$/g, "").split(".")[0])
|
|
511
|
+
.filter((name) => target.imports?.includes(name) && !doc.imports?.includes(name));
|
|
512
|
+
if (orphaned.length)
|
|
513
|
+
report(doc, {
|
|
514
|
+
code: "imported-embed-component",
|
|
515
|
+
severity: "error",
|
|
516
|
+
message: `this embed copies ${orphaned.map((name) => `<${name}>`).join(", ")} out of ${target.id}, which imports ${orphaned.length === 1 ? "it" : "them"} in its own file. ${doc.id} has no such import, so the spliced copy cannot render ${orphaned.length === 1 ? "it" : "them"}. Provide the component through the host's shared components, import it in ${doc.id} as well, or move it out of the embedded section.`,
|
|
517
|
+
reference: String(reference),
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
return { issues, documentCount: library.documents.length, checkedReferences };
|
|
523
|
+
}
|
|
524
|
+
// Posix path helpers, kept local so this module stays usable without importing
|
|
525
|
+
// the whole node path surface into a browser-safe boundary by accident.
|
|
526
|
+
const dirname = (value) => {
|
|
527
|
+
const at = value.lastIndexOf("/");
|
|
528
|
+
return at <= 0 ? "." : value.slice(0, at);
|
|
529
|
+
};
|
|
530
|
+
const posixJoin = (base, value) => base === "." ? value : `${base}/${value}`;
|
|
531
|
+
const normalize = (value) => {
|
|
532
|
+
const out = [];
|
|
533
|
+
for (const part of value.split("/")) {
|
|
534
|
+
if (!part || part === ".")
|
|
535
|
+
continue;
|
|
536
|
+
if (part === "..")
|
|
537
|
+
out.pop();
|
|
538
|
+
else
|
|
539
|
+
out.push(part);
|
|
540
|
+
}
|
|
541
|
+
return out.join("/");
|
|
542
|
+
};
|
|
543
|
+
//# sourceMappingURL=check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/node/check.ts"],"names":[],"mappings":"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"}
|
package/dist/node/cli.js
CHANGED
|
@@ -5,24 +5,70 @@ import { pathToFileURL } from "node:url";
|
|
|
5
5
|
import { buildDocuments, buildDocumentsAsync } from "./library.js";
|
|
6
6
|
import { prepareEmbeds } from "./prepare-embeds.js";
|
|
7
7
|
import { generateDataset } from "./dataset.js";
|
|
8
|
+
import { checkReferences } from "./check.js";
|
|
9
|
+
import { formatCheckResult } from "./report.js";
|
|
10
|
+
import { watchDocuments } from "./watch.js";
|
|
11
|
+
const USAGE = "Usage: cudoc <collect|check|dataset> --config config.mjs [--watch] [--format text|json] [--strict]";
|
|
8
12
|
try {
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
const argv = process.argv.slice(2);
|
|
14
|
+
const [command] = argv;
|
|
15
|
+
const flags = new Set(argv.filter((value) => value.startsWith("--")));
|
|
16
|
+
const configIndex = argv.indexOf("--config");
|
|
17
|
+
if (!["collect", "check", "dataset"].includes(command) ||
|
|
18
|
+
configIndex === -1 ||
|
|
19
|
+
!argv[configIndex + 1])
|
|
20
|
+
throw new Error(USAGE);
|
|
21
|
+
const configPath = argv[configIndex + 1];
|
|
22
|
+
const config = configPath.endsWith(".json")
|
|
23
|
+
? JSON.parse(fs.readFileSync(configPath, "utf8"))
|
|
24
|
+
: (await import(pathToFileURL(path.resolve(configPath)).href)).default;
|
|
25
|
+
const collect = async () => {
|
|
20
26
|
const library = config.compiler
|
|
21
27
|
? await buildDocumentsAsync({
|
|
22
28
|
...config,
|
|
23
29
|
compiler: async (...parameters) => config.compiler(...parameters),
|
|
24
30
|
})
|
|
25
31
|
: buildDocuments(config);
|
|
32
|
+
return library;
|
|
33
|
+
};
|
|
34
|
+
if (command === "dataset")
|
|
35
|
+
console.log(JSON.stringify(generateDataset(config)));
|
|
36
|
+
else if (command === "check") {
|
|
37
|
+
// Checking reads the same collection the build does, so it sees exactly
|
|
38
|
+
// what the site will render. It writes nothing.
|
|
39
|
+
const result = checkReferences(await collect(), config.check ?? {});
|
|
40
|
+
const json = argv[argv.indexOf("--format") + 1] === "json";
|
|
41
|
+
console.log(json ? JSON.stringify(result, null, 2) : formatCheckResult(result));
|
|
42
|
+
const blocking = result.issues.filter((issue) => issue.severity === "error" || flags.has("--strict"));
|
|
43
|
+
if (blocking.length)
|
|
44
|
+
process.exitCode = 1;
|
|
45
|
+
}
|
|
46
|
+
else if (flags.has("--watch")) {
|
|
47
|
+
// The first pass starts from whatever the output directory holds, and
|
|
48
|
+
// every pass reports what it compiled; a failed pass is a message and the
|
|
49
|
+
// last good output stays in place.
|
|
50
|
+
const watcher = watchDocuments(config, {
|
|
51
|
+
onPass: ({ documentCount, compiled, reused, blocks, reusedBlocks, outDir, elapsed, }) => console.log(JSON.stringify({
|
|
52
|
+
documentCount,
|
|
53
|
+
compiled,
|
|
54
|
+
reused,
|
|
55
|
+
blocks,
|
|
56
|
+
reusedBlocks,
|
|
57
|
+
outDir,
|
|
58
|
+
elapsed,
|
|
59
|
+
})),
|
|
60
|
+
onError: (error) => console.error(error),
|
|
61
|
+
});
|
|
62
|
+
const stop = () => {
|
|
63
|
+
watcher.close();
|
|
64
|
+
process.exit(0);
|
|
65
|
+
};
|
|
66
|
+
process.on("SIGINT", stop);
|
|
67
|
+
process.on("SIGTERM", stop);
|
|
68
|
+
await watcher.ready;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
const library = await collect();
|
|
26
72
|
await prepareEmbeds(library, config.outDir);
|
|
27
73
|
console.log(JSON.stringify({
|
|
28
74
|
documentCount: library.documents.length,
|