@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.
Files changed (76) hide show
  1. package/README.md +1 -1
  2. package/dist/document.d.ts +11 -1
  3. package/dist/document.d.ts.map +1 -1
  4. package/dist/document.js +38 -3
  5. package/dist/document.js.map +1 -1
  6. package/dist/internal/core/mdx/imports.d.ts +21 -0
  7. package/dist/internal/core/mdx/imports.d.ts.map +1 -0
  8. package/dist/internal/core/mdx/imports.js +80 -0
  9. package/dist/internal/core/mdx/imports.js.map +1 -0
  10. package/dist/internal/core/mdx/index.d.ts +1 -0
  11. package/dist/internal/core/mdx/index.d.ts.map +1 -1
  12. package/dist/internal/core/mdx/index.js +1 -0
  13. package/dist/internal/core/mdx/index.js.map +1 -1
  14. package/dist/internal/transforms/table-column-layout/create-table.d.ts.map +1 -1
  15. package/dist/internal/transforms/table-column-layout/create-table.js +40 -17
  16. package/dist/internal/transforms/table-column-layout/create-table.js.map +1 -1
  17. package/dist/internal/transforms/table-column-layout/index.d.ts +32 -0
  18. package/dist/internal/transforms/table-column-layout/index.d.ts.map +1 -1
  19. package/dist/internal/transforms/table-column-layout/index.js +66 -0
  20. package/dist/internal/transforms/table-column-layout/index.js.map +1 -1
  21. package/dist/markdown.d.ts +8 -0
  22. package/dist/markdown.d.ts.map +1 -1
  23. package/dist/markdown.js +9 -1
  24. package/dist/markdown.js.map +1 -1
  25. package/dist/node/check.d.ts +61 -0
  26. package/dist/node/check.d.ts.map +1 -0
  27. package/dist/node/check.js +543 -0
  28. package/dist/node/check.js.map +1 -0
  29. package/dist/node/cli.js +57 -11
  30. package/dist/node/cli.js.map +1 -1
  31. package/dist/node/dataset.d.ts +14 -1
  32. package/dist/node/dataset.d.ts.map +1 -1
  33. package/dist/node/dataset.js +40 -4
  34. package/dist/node/dataset.js.map +1 -1
  35. package/dist/node/glob.d.ts +21 -0
  36. package/dist/node/glob.d.ts.map +1 -0
  37. package/dist/node/glob.js +61 -0
  38. package/dist/node/glob.js.map +1 -0
  39. package/dist/node/library.d.ts +70 -4
  40. package/dist/node/library.d.ts.map +1 -1
  41. package/dist/node/library.js +196 -32
  42. package/dist/node/library.js.map +1 -1
  43. package/dist/node/local-target.d.ts +63 -0
  44. package/dist/node/local-target.d.ts.map +1 -0
  45. package/dist/node/local-target.js +81 -0
  46. package/dist/node/local-target.js.map +1 -0
  47. package/dist/node/prepare-embeds.d.ts +16 -2
  48. package/dist/node/prepare-embeds.d.ts.map +1 -1
  49. package/dist/node/prepare-embeds.js +42 -9
  50. package/dist/node/prepare-embeds.js.map +1 -1
  51. package/dist/node/report.d.ts +9 -0
  52. package/dist/node/report.d.ts.map +1 -0
  53. package/dist/node/report.js +48 -0
  54. package/dist/node/report.js.map +1 -0
  55. package/dist/node/resolve-embed.d.ts +88 -1
  56. package/dist/node/resolve-embed.d.ts.map +1 -1
  57. package/dist/node/resolve-embed.js +321 -63
  58. package/dist/node/resolve-embed.js.map +1 -1
  59. package/dist/node/roots.d.ts +67 -0
  60. package/dist/node/roots.d.ts.map +1 -0
  61. package/dist/node/roots.js +134 -0
  62. package/dist/node/roots.js.map +1 -0
  63. package/dist/node/storage.d.ts +21 -3
  64. package/dist/node/storage.d.ts.map +1 -1
  65. package/dist/node/storage.js +41 -12
  66. package/dist/node/storage.js.map +1 -1
  67. package/dist/node/watch.d.ts +81 -0
  68. package/dist/node/watch.d.ts.map +1 -0
  69. package/dist/node/watch.js +140 -0
  70. package/dist/node/watch.js.map +1 -0
  71. package/dist/paged.d.ts +34 -0
  72. package/dist/paged.d.ts.map +1 -0
  73. package/dist/paged.js +44 -0
  74. package/dist/paged.js.map +1 -0
  75. package/package.json +27 -2
  76. 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 [command, ...args] = process.argv.slice(2);
10
- if (!["collect", "dataset"].includes(command) ||
11
- args.length !== 2 ||
12
- args[0] !== "--config")
13
- throw new Error("Usage: cudoc <collect|dataset> --config config.mjs");
14
- const config = args[1].endsWith(".json")
15
- ? JSON.parse(fs.readFileSync(args[1], "utf8"))
16
- : (await import(pathToFileURL(path.resolve(args[1])).href)).default;
17
- if (command === "dataset")
18
- console.log(JSON.stringify(generateDataset(config)));
19
- else {
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,