lens-content-processor 0.2.2 → 0.4.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 (63) hide show
  1. package/dist/bundler/article.d.ts +7 -2
  2. package/dist/bundler/article.js +23 -24
  3. package/dist/bundler/article.js.map +1 -1
  4. package/dist/cli.d.ts +1 -2
  5. package/dist/cli.js +6 -10
  6. package/dist/cli.js.map +1 -1
  7. package/dist/content-schema.js +8 -6
  8. package/dist/content-schema.js.map +1 -1
  9. package/dist/flattener/index.d.ts +41 -2
  10. package/dist/flattener/index.js +699 -48
  11. package/dist/flattener/index.js.map +1 -1
  12. package/dist/flattener/test-helpers.d.ts +23 -0
  13. package/dist/flattener/test-helpers.js +58 -0
  14. package/dist/flattener/test-helpers.js.map +1 -0
  15. package/dist/fs/read-vault.d.ts +1 -4
  16. package/dist/fs/read-vault.js +4 -8
  17. package/dist/fs/read-vault.js.map +1 -1
  18. package/dist/index.d.ts +34 -6
  19. package/dist/index.js +170 -33
  20. package/dist/index.js.map +1 -1
  21. package/dist/parser/article.d.ts +1 -1
  22. package/dist/parser/article.js +14 -4
  23. package/dist/parser/article.js.map +1 -1
  24. package/dist/parser/course.d.ts +2 -2
  25. package/dist/parser/course.js +16 -23
  26. package/dist/parser/course.js.map +1 -1
  27. package/dist/parser/learning-outcome.d.ts +11 -2
  28. package/dist/parser/learning-outcome.js +135 -62
  29. package/dist/parser/learning-outcome.js.map +1 -1
  30. package/dist/parser/lens.d.ts +63 -1
  31. package/dist/parser/lens.js +138 -11
  32. package/dist/parser/lens.js.map +1 -1
  33. package/dist/parser/module.d.ts +1 -1
  34. package/dist/parser/module.js +14 -9
  35. package/dist/parser/module.js.map +1 -1
  36. package/dist/parser/sections.d.ts +2 -0
  37. package/dist/parser/sections.js +57 -21
  38. package/dist/parser/sections.js.map +1 -1
  39. package/dist/parser/video-transcript.js +3 -0
  40. package/dist/parser/video-transcript.js.map +1 -1
  41. package/dist/parser/wikilink.js +6 -1
  42. package/dist/parser/wikilink.js.map +1 -1
  43. package/dist/utils/slug.d.ts +5 -0
  44. package/dist/utils/slug.js +16 -0
  45. package/dist/utils/slug.js.map +1 -0
  46. package/dist/validator/chat-precedence.d.ts +9 -0
  47. package/dist/validator/chat-precedence.js +32 -0
  48. package/dist/validator/chat-precedence.js.map +1 -0
  49. package/dist/validator/directives.d.ts +12 -0
  50. package/dist/validator/directives.js +428 -0
  51. package/dist/validator/directives.js.map +1 -0
  52. package/dist/validator/field-typos.js +0 -9
  53. package/dist/validator/field-typos.js.map +1 -1
  54. package/dist/validator/field-values.js +14 -0
  55. package/dist/validator/field-values.js.map +1 -1
  56. package/dist/validator/tier.d.ts +18 -0
  57. package/dist/validator/tier.js +74 -0
  58. package/dist/validator/tier.js.map +1 -0
  59. package/dist/validator/url-reachability.js +3 -1
  60. package/dist/validator/url-reachability.js.map +1 -1
  61. package/dist/validator/uuid.js +9 -6
  62. package/dist/validator/uuid.js.map +1 -1
  63. package/package.json +5 -5
@@ -0,0 +1,428 @@
1
+ import { levenshtein } from './field-typos.js';
2
+ const SUPPORTED_DIRECTIVES = {
3
+ note: { container: true, leaf: true, text: true, open: false },
4
+ collapse: { container: true, leaf: false, text: true, open: false },
5
+ footnote: { container: false, leaf: true, text: true, open: false },
6
+ };
7
+ const UNSUPPORTED_NAMES = new Set([
8
+ 'warning', 'info', 'tip', 'caution', 'important',
9
+ 'danger', 'details', 'summary', 'aside', 'callout', 'admonition',
10
+ ]);
11
+ const ALL_DIRECTIVE_NAMES = new Set([...Object.keys(SUPPORTED_DIRECTIVES), ...UNSUPPORTED_NAMES]);
12
+ /**
13
+ * Check if a name is a near-miss typo of a supported directive name.
14
+ * Returns the closest match if levenshtein distance ≤ 2, else undefined.
15
+ */
16
+ function findNearMissDirective(name) {
17
+ let bestMatch;
18
+ let bestDist = Infinity;
19
+ for (const supported of Object.keys(SUPPORTED_DIRECTIVES)) {
20
+ const dist = levenshtein(name.toLowerCase(), supported);
21
+ if (dist > 0 && dist <= 2 && dist < bestDist) {
22
+ bestDist = dist;
23
+ bestMatch = supported;
24
+ }
25
+ }
26
+ return bestMatch;
27
+ }
28
+ // Regex patterns
29
+ const CONTAINER_OPEN = /^:::([\w-]+)(?:\{([^}]*)\})?/;
30
+ const CONTAINER_CLOSE_BARE = /^:::\s*$/;
31
+ const CONTAINER_CLOSE_ATTR = /^:::\s*\{([^}]*)\}/;
32
+ const CODE_FENCE = /^(?:```|~~~)/;
33
+ const LEAF_DIRECTIVE_PRE = /^::([\w-]+)(?:\{([^}]*)\})?\[/;
34
+ const LEAF_DIRECTIVE_POST = /^::([\w-]+)\[[^\]]*\]\{([^}]*)\}/;
35
+ const TEXT_DIRECTIVE_PRE = /(?:^|[^:]):(\w[\w-]*)(?:\{([^}]*)\})?\[/;
36
+ const TEXT_DIRECTIVE_POST = /(?:^|[^:]):(\w[\w-]*)\[[^\]]*\]\{([^}]*)\}/;
37
+ // Unclosed bracket patterns — match ::name[ or :name[ without closing ]
38
+ const LEAF_UNCLOSED = /^::([\w-]+)(?:\{[^}]*\})?\[[^\]]*$/;
39
+ const TEXT_UNCLOSED = /(?:^|[^:]):([\w][\w-]*)(?:\{[^}]*\})?\[[^\]]*$/;
40
+ /**
41
+ * Check if an attribute value looks like a typo of "open".
42
+ */
43
+ function isOpenTypo(attr) {
44
+ if (attr === 'open')
45
+ return false;
46
+ if (!attr)
47
+ return false;
48
+ // Case-insensitive match
49
+ if (attr.toLowerCase() === 'open')
50
+ return true;
51
+ // Contains = (like open=true)
52
+ if (attr.includes('=')) {
53
+ const key = attr.split('=')[0];
54
+ if (key.toLowerCase() === 'open')
55
+ return true;
56
+ }
57
+ // Levenshtein distance
58
+ if (levenshtein(attr.toLowerCase(), 'open') <= 2)
59
+ return true;
60
+ return false;
61
+ }
62
+ /**
63
+ * Check attribute validity on a supported directive and return warnings.
64
+ */
65
+ function checkAttribute(name, attr, file, line) {
66
+ const errors = [];
67
+ if (attr === undefined)
68
+ return errors;
69
+ const info = SUPPORTED_DIRECTIVES[name];
70
+ if (!info)
71
+ return errors;
72
+ if (attr === '') {
73
+ errors.push({
74
+ file,
75
+ line,
76
+ message: `Directive '${name}' has an empty attribute '{}'`,
77
+ suggestion: 'Remove the empty braces, or use {open} to make the directive open by default',
78
+ severity: 'warning',
79
+ });
80
+ return errors;
81
+ }
82
+ if (attr === 'open') {
83
+ // Valid attribute — but check if this directive supports it
84
+ if (!info.open) {
85
+ errors.push({
86
+ file,
87
+ line,
88
+ message: `Directive '${name}' does not support {open}`,
89
+ suggestion: `Remove {open} — '${name}' does not support the open attribute`,
90
+ severity: 'warning',
91
+ });
92
+ }
93
+ }
94
+ else if (isOpenTypo(attr)) {
95
+ errors.push({
96
+ file,
97
+ line,
98
+ message: `Possible attribute typo '{${attr}}' on directive '${name}'`,
99
+ suggestion: `Did you mean {open}?`,
100
+ severity: 'warning',
101
+ });
102
+ }
103
+ else {
104
+ // Completely unrecognized attribute
105
+ errors.push({
106
+ file,
107
+ line,
108
+ message: `Unrecognized attribute '{${attr}}' on directive '${name}'`,
109
+ suggestion: info.open ? `The only supported attribute is {open}` : `'${name}' does not support any attributes`,
110
+ severity: 'warning',
111
+ });
112
+ }
113
+ return errors;
114
+ }
115
+ /**
116
+ * Main validator for article body content.
117
+ * Checks for unclosed containers, unsupported names, empty containers,
118
+ * attribute typos, and {open} on closing markers.
119
+ */
120
+ export function validateDirectives(body, file, bodyStartLine) {
121
+ const errors = [];
122
+ const lines = body.split('\n');
123
+ const stack = [];
124
+ let inCodeBlock = false;
125
+ for (let i = 0; i < lines.length; i++) {
126
+ const line = lines[i];
127
+ const absLine = bodyStartLine + i;
128
+ // Toggle code block state
129
+ if (CODE_FENCE.test(line)) {
130
+ inCodeBlock = !inCodeBlock;
131
+ continue;
132
+ }
133
+ if (inCodeBlock)
134
+ continue;
135
+ // Check container close with attribute (error: {open} on closing marker)
136
+ const closeAttrMatch = line.match(CONTAINER_CLOSE_ATTR);
137
+ if (closeAttrMatch) {
138
+ const attrOnClose = closeAttrMatch[1];
139
+ const top = stack.pop();
140
+ if (top) {
141
+ errors.push({
142
+ file,
143
+ line: absLine,
144
+ message: `Attribute {${attrOnClose}} on closing ':::' marker has no effect`,
145
+ suggestion: `Move to opening marker: :::${top.name}{${attrOnClose}}`,
146
+ severity: 'error',
147
+ });
148
+ // Check empty container
149
+ if (!top.hasContent) {
150
+ errors.push({
151
+ file,
152
+ line: top.line,
153
+ message: `Empty container directive ':::${top.name}' has no content`,
154
+ suggestion: 'Add content between the opening and closing markers',
155
+ severity: 'warning',
156
+ });
157
+ }
158
+ }
159
+ continue;
160
+ }
161
+ // Check bare container close
162
+ if (CONTAINER_CLOSE_BARE.test(line)) {
163
+ const top = stack.pop();
164
+ if (top && !top.hasContent) {
165
+ errors.push({
166
+ file,
167
+ line: top.line,
168
+ message: `Empty container directive ':::${top.name}' has no content`,
169
+ suggestion: 'Add content between the opening and closing markers',
170
+ severity: 'warning',
171
+ });
172
+ }
173
+ continue;
174
+ }
175
+ // Check container open
176
+ const openMatch = line.match(CONTAINER_OPEN);
177
+ if (openMatch) {
178
+ const name = openMatch[1];
179
+ const attr = openMatch[2];
180
+ if (UNSUPPORTED_NAMES.has(name)) {
181
+ errors.push({
182
+ file,
183
+ line: absLine,
184
+ message: `Unsupported directive ':::${name}'`,
185
+ suggestion: `Supported container directives: ${Object.entries(SUPPORTED_DIRECTIVES).filter(([, v]) => v.container).map(([k]) => k).join(', ')}`,
186
+ severity: 'error',
187
+ });
188
+ }
189
+ else if (SUPPORTED_DIRECTIVES[name]) {
190
+ if (!SUPPORTED_DIRECTIVES[name].container) {
191
+ errors.push({
192
+ file,
193
+ line: absLine,
194
+ message: `Directive '${name}' does not support the container ':::' form`,
195
+ suggestion: `Use the leaf form '::${name}[text]' or inline form ':${name}[text]' instead`,
196
+ severity: 'error',
197
+ });
198
+ }
199
+ errors.push(...checkAttribute(name, attr, file, absLine));
200
+ }
201
+ else {
202
+ const nearMiss = findNearMissDirective(name);
203
+ if (nearMiss) {
204
+ errors.push({
205
+ file,
206
+ line: absLine,
207
+ message: `Unknown directive ':::${name}' — did you mean ':::${nearMiss}'?`,
208
+ suggestion: `Supported container directives: ${Object.entries(SUPPORTED_DIRECTIVES).filter(([, v]) => v.container).map(([k]) => k).join(', ')}`,
209
+ severity: 'error',
210
+ });
211
+ }
212
+ }
213
+ stack.push({ name, line: absLine, hasContent: false });
214
+ continue;
215
+ }
216
+ // Check leaf directive (::name[...)
217
+ // First check for unclosed bracket: ::name[ without ]
218
+ const leafUnclosedMatch = line.match(LEAF_UNCLOSED);
219
+ if (leafUnclosedMatch) {
220
+ const name = leafUnclosedMatch[1];
221
+ if (SUPPORTED_DIRECTIVES[name] || UNSUPPORTED_NAMES.has(name) || findNearMissDirective(name)) {
222
+ errors.push({
223
+ file,
224
+ line: absLine,
225
+ message: `Unclosed bracket in leaf directive '::${name}[' — missing closing ']'`,
226
+ suggestion: `Add a closing bracket: ::${name}[content]`,
227
+ severity: 'error',
228
+ });
229
+ if (stack.length > 0) {
230
+ stack[stack.length - 1].hasContent = true;
231
+ }
232
+ continue;
233
+ }
234
+ }
235
+ // Try POST first to capture post-bracket attributes, fall back to PRE
236
+ const leafMatchPost = line.match(LEAF_DIRECTIVE_POST);
237
+ const leafMatchPre = line.match(LEAF_DIRECTIVE_PRE);
238
+ const leafMatch = leafMatchPost ?? leafMatchPre;
239
+ if (leafMatch) {
240
+ const name = leafMatch[1];
241
+ // Prefer post-bracket attr if available
242
+ const attr = leafMatchPost?.[2] ?? leafMatchPre?.[2];
243
+ if (UNSUPPORTED_NAMES.has(name)) {
244
+ errors.push({
245
+ file,
246
+ line: absLine,
247
+ message: `Unsupported directive '::${name}'`,
248
+ suggestion: `Supported leaf directives: ${Object.entries(SUPPORTED_DIRECTIVES).filter(([, v]) => v.leaf).map(([k]) => k).join(', ')}`,
249
+ severity: 'error',
250
+ });
251
+ }
252
+ else if (SUPPORTED_DIRECTIVES[name]) {
253
+ if (!SUPPORTED_DIRECTIVES[name].leaf) {
254
+ errors.push({
255
+ file,
256
+ line: absLine,
257
+ message: `Directive '${name}' does not support the leaf '::' form`,
258
+ suggestion: `Use the container form ':::${name}' or inline form ':${name}[text]' instead`,
259
+ severity: 'warning',
260
+ });
261
+ }
262
+ errors.push(...checkAttribute(name, attr, file, absLine));
263
+ }
264
+ else {
265
+ const nearMiss = findNearMissDirective(name);
266
+ if (nearMiss) {
267
+ errors.push({
268
+ file,
269
+ line: absLine,
270
+ message: `Unknown directive '::${name}' — did you mean '::${nearMiss}'?`,
271
+ suggestion: `Supported leaf directives: ${Object.entries(SUPPORTED_DIRECTIVES).filter(([, v]) => v.leaf).map(([k]) => k).join(', ')}`,
272
+ severity: 'error',
273
+ });
274
+ }
275
+ }
276
+ // Mark parent container as having content
277
+ if (stack.length > 0) {
278
+ stack[stack.length - 1].hasContent = true;
279
+ }
280
+ continue;
281
+ }
282
+ // Check for unclosed text directive brackets (:name[ without ])
283
+ const textUnclosedMatches = line.matchAll(new RegExp(TEXT_UNCLOSED, 'g'));
284
+ for (const m of textUnclosedMatches) {
285
+ const name = m[1];
286
+ const matchIndex = m.index;
287
+ const beforeMatch = line.substring(0, matchIndex + (m[0].startsWith(':') ? 0 : 1));
288
+ if (/https?$|ftp$|mailto$|tel$/.test(beforeMatch))
289
+ continue;
290
+ if (SUPPORTED_DIRECTIVES[name] || UNSUPPORTED_NAMES.has(name) || findNearMissDirective(name)) {
291
+ errors.push({
292
+ file,
293
+ line: absLine,
294
+ message: `Unclosed bracket in text directive ':${name}[' — missing closing ']'`,
295
+ suggestion: `Add a closing bracket: :${name}[content]`,
296
+ severity: 'error',
297
+ });
298
+ }
299
+ }
300
+ // Check text/inline directive (:name[...)
301
+ // Must not be preceded by another colon (to avoid matching ::name)
302
+ // Check both :name{attr}[text] and :name[text]{attr} forms
303
+ const seenTextDirectives = new Set(); // track by match index to avoid duplicates
304
+ // Check POST first so :name[text]{attr} captures the attribute before PRE sees it without attr
305
+ for (const pattern of [TEXT_DIRECTIVE_POST, TEXT_DIRECTIVE_PRE]) {
306
+ const textMatches = line.matchAll(new RegExp(pattern, 'g'));
307
+ for (const textMatch of textMatches) {
308
+ const matchIndex = textMatch.index;
309
+ if (seenTextDirectives.has(matchIndex))
310
+ continue;
311
+ seenTextDirectives.add(matchIndex);
312
+ const name = textMatch[1];
313
+ const attr = textMatch[2];
314
+ // Skip URL-like patterns (http:, https:, ftp:, etc.)
315
+ const beforeMatch = line.substring(0, matchIndex + (textMatch[0].startsWith(':') ? 0 : 1));
316
+ if (/https?$|ftp$|mailto$|tel$/.test(beforeMatch))
317
+ continue;
318
+ if (UNSUPPORTED_NAMES.has(name)) {
319
+ errors.push({
320
+ file,
321
+ line: absLine,
322
+ message: `Unsupported directive ':${name}'`,
323
+ suggestion: `Supported text directives: ${Object.entries(SUPPORTED_DIRECTIVES).filter(([, v]) => v.text).map(([k]) => k).join(', ')}`,
324
+ severity: 'error',
325
+ });
326
+ }
327
+ else if (SUPPORTED_DIRECTIVES[name]) {
328
+ errors.push(...checkAttribute(name, attr, file, absLine));
329
+ }
330
+ else {
331
+ const nearMiss = findNearMissDirective(name);
332
+ if (nearMiss) {
333
+ errors.push({
334
+ file,
335
+ line: absLine,
336
+ message: `Unknown directive ':${name}' — did you mean ':${nearMiss}'?`,
337
+ suggestion: `Supported text directives: ${Object.entries(SUPPORTED_DIRECTIVES).filter(([, v]) => v.text).map(([k]) => k).join(', ')}`,
338
+ severity: 'error',
339
+ });
340
+ }
341
+ }
342
+ // Mark parent container as having content
343
+ if (stack.length > 0) {
344
+ stack[stack.length - 1].hasContent = true;
345
+ }
346
+ }
347
+ }
348
+ // Mark content in parent container (non-blank, non-directive line)
349
+ if (stack.length > 0 && line.trim() !== '') {
350
+ stack[stack.length - 1].hasContent = true;
351
+ }
352
+ }
353
+ // Report unclosed containers
354
+ for (const entry of stack) {
355
+ errors.push({
356
+ file,
357
+ line: entry.line,
358
+ message: `Unclosed container directive ':::${entry.name}'`,
359
+ suggestion: 'Add a closing ::: marker',
360
+ severity: 'error',
361
+ });
362
+ }
363
+ return errors;
364
+ }
365
+ /**
366
+ * Lightweight check for directives in non-article content (e.g., lens text segments).
367
+ * Returns a single warning per match since directives won't render outside articles.
368
+ */
369
+ export function detectDirectivesInNonArticle(content, file, line) {
370
+ const lines = content.split('\n');
371
+ let inCodeBlock = false;
372
+ for (const l of lines) {
373
+ if (CODE_FENCE.test(l)) {
374
+ inCodeBlock = !inCodeBlock;
375
+ continue;
376
+ }
377
+ if (inCodeBlock)
378
+ continue;
379
+ // Container directive
380
+ if (CONTAINER_OPEN.test(l)) {
381
+ const match = l.match(CONTAINER_OPEN);
382
+ if (ALL_DIRECTIVE_NAMES.has(match[1])) {
383
+ return [{
384
+ file,
385
+ line,
386
+ message: `Directive ':::${match[1]}' found in non-article content — directives only render in article files`,
387
+ suggestion: 'Move this content to an article file (articles/*.md) or remove the directive syntax',
388
+ severity: 'warning',
389
+ }];
390
+ }
391
+ }
392
+ // Leaf directive
393
+ const leafMatch = l.match(LEAF_DIRECTIVE_PRE);
394
+ if (leafMatch && ALL_DIRECTIVE_NAMES.has(leafMatch[1])) {
395
+ return [{
396
+ file,
397
+ line,
398
+ message: `Directive '::${leafMatch[1]}' found in non-article content — directives only render in article files`,
399
+ suggestion: 'Move this content to an article file (articles/*.md) or remove the directive syntax',
400
+ severity: 'warning',
401
+ }];
402
+ }
403
+ // Text/inline directive — scan for :name[ patterns (both pre and post attribute forms)
404
+ for (const pattern of [TEXT_DIRECTIVE_PRE, TEXT_DIRECTIVE_POST]) {
405
+ const textRegex = new RegExp(pattern, 'g');
406
+ let textMatch;
407
+ while ((textMatch = textRegex.exec(l)) !== null) {
408
+ const name = textMatch[1];
409
+ // Skip URL-like patterns
410
+ const matchIndex = textMatch.index;
411
+ const beforeMatch = l.substring(0, matchIndex + (textMatch[0].startsWith(':') ? 0 : 1));
412
+ if (/https?$|ftp$|mailto$|tel$/.test(beforeMatch))
413
+ continue;
414
+ if (ALL_DIRECTIVE_NAMES.has(name)) {
415
+ return [{
416
+ file,
417
+ line,
418
+ message: `Directive ':${name}' found in non-article content — directives only render in article files`,
419
+ suggestion: 'Move this content to an article file (articles/*.md) or remove the directive syntax',
420
+ severity: 'warning',
421
+ }];
422
+ }
423
+ }
424
+ }
425
+ }
426
+ return [];
427
+ }
428
+ //# sourceMappingURL=directives.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directives.js","sourceRoot":"","sources":["../../src/validator/directives.ts"],"names":[],"mappings":"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"}
@@ -98,15 +98,6 @@ export function detectFrontmatterTypos(frontmatter, validFields, file) {
98
98
  severity: 'warning',
99
99
  });
100
100
  }
101
- else {
102
- warnings.push({
103
- file,
104
- line: 2,
105
- message: `Unrecognized frontmatter field '${fieldName}'`,
106
- suggestion: `Valid fields: ${validFields.join(', ')}`,
107
- severity: 'warning',
108
- });
109
- }
110
101
  }
111
102
  return warnings;
112
103
  }
@@ -1 +1 @@
1
- {"version":3,"file":"field-typos.js","sourceRoot":"","sources":["../../src/validator/field-typos.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"field-typos.js","sourceRoot":"","sources":["../../src/validator/field-typos.ts"],"names":[],"mappings":"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"}
@@ -60,6 +60,10 @@ export function validateSlugFormat(slug, file, line) {
60
60
  }
61
61
  return null;
62
62
  }
63
+ function isEmptyValue(value) {
64
+ const trimmed = value.trim();
65
+ return trimmed === '' || trimmed === '""' || trimmed === "''";
66
+ }
63
67
  /**
64
68
  * Validate field values, checking for appropriate types.
65
69
  * Currently validates that boolean fields contain 'true' or 'false'.
@@ -72,6 +76,16 @@ export function validateSlugFormat(slug, file, line) {
72
76
  export function validateFieldValues(fields, file, line) {
73
77
  const warnings = [];
74
78
  for (const [name, value] of Object.entries(fields)) {
79
+ // Check for empty 'from' field
80
+ if (name === 'from' && isEmptyValue(value)) {
81
+ warnings.push({
82
+ file,
83
+ line,
84
+ message: `Field 'from' is empty and can be omitted`,
85
+ suggestion: 'Without a from:: field, the content shows from the start',
86
+ severity: 'warning',
87
+ });
88
+ }
75
89
  // Check if this is a boolean field
76
90
  if (ALL_BOOLEAN_FIELDS.includes(name)) {
77
91
  const normalizedValue = value.toLowerCase();
@@ -1 +1 @@
1
- {"version":3,"file":"field-values.js","sourceRoot":"","sources":["../../src/validator/field-values.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D;;;GAGG;AACH,MAAM,kBAAkB,GAAG,0BAA0B,CAAC;AAEtD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAAY,EACZ,IAAY,EACZ,IAAY;IAEZ,4DAA4D;IAC5D,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO;YACL,IAAI;YACJ,IAAI;YACJ,OAAO,EAAE,wBAAwB,IAAI,+BAA+B;YACpE,UAAU,EAAE,4BAA4B,IAAI,CAAC,WAAW,EAAE,GAAG;YAC7D,QAAQ,EAAE,OAAO;SAClB,CAAC;IACJ,CAAC;IAED,2BAA2B;IAC3B,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,OAAO;YACL,IAAI;YACJ,IAAI;YACJ,OAAO,EAAE,wBAAwB,IAAI,+BAA+B;YACpE,UAAU,EAAE,2BAA2B;YACvC,QAAQ,EAAE,OAAO;SAClB,CAAC;IACJ,CAAC;IAED,4BAA4B;IAC5B,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO;YACL,IAAI;YACJ,IAAI;YACJ,OAAO,EAAE,wBAAwB,IAAI,6BAA6B;YAClE,UAAU,EAAE,4BAA4B;YACxC,QAAQ,EAAE,OAAO;SAClB,CAAC;IACJ,CAAC;IAED,2DAA2D;IAC3D,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,OAAO;YACL,IAAI;YACJ,IAAI;YACJ,OAAO,EAAE,wBAAwB,IAAI,8DAA8D;YACnG,UAAU,EAAE,oCAAoC;YAChD,QAAQ,EAAE,OAAO;SAClB,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAA8B,EAC9B,IAAY,EACZ,IAAY;IAEZ,MAAM,QAAQ,GAAmB,EAAE,CAAC;IAEpC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnD,mCAAmC;QACnC,IAAI,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACtC,MAAM,eAAe,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;YAC5C,IAAI,eAAe,KAAK,MAAM,IAAI,eAAe,KAAK,OAAO,EAAE,CAAC;gBAC9D,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI;oBACJ,IAAI;oBACJ,OAAO,EAAE,UAAU,IAAI,4BAA4B,KAAK,GAAG;oBAC3D,UAAU,EAAE,4BAA4B;oBACxC,QAAQ,EAAE,SAAS;iBACpB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"field-values.js","sourceRoot":"","sources":["../../src/validator/field-values.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D;;;GAGG;AACH,MAAM,kBAAkB,GAAG,0BAA0B,CAAC;AAEtD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAAY,EACZ,IAAY,EACZ,IAAY;IAEZ,4DAA4D;IAC5D,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO;YACL,IAAI;YACJ,IAAI;YACJ,OAAO,EAAE,wBAAwB,IAAI,+BAA+B;YACpE,UAAU,EAAE,4BAA4B,IAAI,CAAC,WAAW,EAAE,GAAG;YAC7D,QAAQ,EAAE,OAAO;SAClB,CAAC;IACJ,CAAC;IAED,2BAA2B;IAC3B,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,OAAO;YACL,IAAI;YACJ,IAAI;YACJ,OAAO,EAAE,wBAAwB,IAAI,+BAA+B;YACpE,UAAU,EAAE,2BAA2B;YACvC,QAAQ,EAAE,OAAO;SAClB,CAAC;IACJ,CAAC;IAED,4BAA4B;IAC5B,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO;YACL,IAAI;YACJ,IAAI;YACJ,OAAO,EAAE,wBAAwB,IAAI,6BAA6B;YAClE,UAAU,EAAE,4BAA4B;YACxC,QAAQ,EAAE,OAAO;SAClB,CAAC;IACJ,CAAC;IAED,2DAA2D;IAC3D,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,OAAO;YACL,IAAI;YACJ,IAAI;YACJ,OAAO,EAAE,wBAAwB,IAAI,8DAA8D;YACnG,UAAU,EAAE,oCAAoC;YAChD,QAAQ,EAAE,OAAO;SAClB,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,OAAO,OAAO,KAAK,EAAE,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,IAAI,CAAC;AAChE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAA8B,EAC9B,IAAY,EACZ,IAAY;IAEZ,MAAM,QAAQ,GAAmB,EAAE,CAAC;IAEpC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnD,+BAA+B;QAC/B,IAAI,IAAI,KAAK,MAAM,IAAI,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3C,QAAQ,CAAC,IAAI,CAAC;gBACZ,IAAI;gBACJ,IAAI;gBACJ,OAAO,EAAE,0CAA0C;gBACnD,UAAU,EACR,0DAA0D;gBAC5D,QAAQ,EAAE,SAAS;aACpB,CAAC,CAAC;QACL,CAAC;QAED,mCAAmC;QACnC,IAAI,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACtC,MAAM,eAAe,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;YAC5C,IAAI,eAAe,KAAK,MAAM,IAAI,eAAe,KAAK,OAAO,EAAE,CAAC;gBAC9D,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI;oBACJ,IAAI;oBACJ,OAAO,EAAE,UAAU,IAAI,4BAA4B,KAAK,GAAG;oBAC3D,UAAU,EAAE,4BAA4B;oBACxC,QAAQ,EAAE,SAAS;iBACpB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { ContentError } from '../index.js';
2
+ export type ContentTier = 'production' | 'wip' | 'ignored';
3
+ /**
4
+ * Determine content tier from frontmatter tags.
5
+ * - tags containing 'validator-ignore' → 'ignored'
6
+ * - tags containing 'wip' → 'wip'
7
+ * - otherwise → 'production'
8
+ */
9
+ export declare function getTierFromFrontmatter(frontmatter: Record<string, unknown>): ContentTier;
10
+ /**
11
+ * Build a tier map for all .md files by parsing their frontmatter tags.
12
+ */
13
+ export declare function buildTierMap(files: Map<string, string>): Map<string, ContentTier>;
14
+ /**
15
+ * Check for tier violations when a parent references a child.
16
+ * Returns a ContentError if the reference violates tier rules, null otherwise.
17
+ */
18
+ export declare function checkTierViolation(parentPath: string, parentTier: ContentTier, childPath: string, childTier: ContentTier, childLabel: string, line?: number): ContentError | null;
@@ -0,0 +1,74 @@
1
+ import { parseFrontmatter } from '../parser/frontmatter.js';
2
+ /**
3
+ * Determine content tier from frontmatter tags.
4
+ * - tags containing 'validator-ignore' → 'ignored'
5
+ * - tags containing 'wip' → 'wip'
6
+ * - otherwise → 'production'
7
+ */
8
+ export function getTierFromFrontmatter(frontmatter) {
9
+ const tags = frontmatter.tags;
10
+ if (!Array.isArray(tags))
11
+ return 'production';
12
+ const normalized = tags.map((t) => String(t).toLowerCase());
13
+ if (normalized.includes('validator-ignore'))
14
+ return 'ignored';
15
+ if (normalized.includes('wip') || normalized.includes('work-in-progress'))
16
+ return 'wip';
17
+ return 'production';
18
+ }
19
+ /**
20
+ * Build a tier map for all .md files by parsing their frontmatter tags.
21
+ */
22
+ export function buildTierMap(files) {
23
+ const tierMap = new Map();
24
+ for (const [path, content] of files.entries()) {
25
+ if (!path.endsWith('.md'))
26
+ continue;
27
+ const { frontmatter } = parseFrontmatter(content, path);
28
+ tierMap.set(path, getTierFromFrontmatter(frontmatter));
29
+ }
30
+ return tierMap;
31
+ }
32
+ /**
33
+ * Check for tier violations when a parent references a child.
34
+ * Returns a ContentError if the reference violates tier rules, null otherwise.
35
+ */
36
+ export function checkTierViolation(parentPath, parentTier, childPath, childTier, childLabel, line) {
37
+ // Ignored parents are never processed (filtered upstream)
38
+ if (parentTier === 'ignored')
39
+ return null;
40
+ // Production parent → child must be production
41
+ if (parentTier === 'production' && childTier === 'wip') {
42
+ return {
43
+ file: parentPath,
44
+ line,
45
+ message: `References WIP ${childLabel}: ${childPath}`,
46
+ suggestion: `Remove the WIP tag from ${childPath}, or add tags: [wip] to this file`,
47
+ severity: 'error',
48
+ category: 'production',
49
+ };
50
+ }
51
+ if (parentTier === 'production' && childTier === 'ignored') {
52
+ return {
53
+ file: parentPath,
54
+ line,
55
+ message: `References ignored ${childLabel}: ${childPath}`,
56
+ suggestion: `Remove the validator-ignore tag from ${childPath}, or add tags: [wip] to this file`,
57
+ severity: 'error',
58
+ category: 'production',
59
+ };
60
+ }
61
+ // WIP parent → child must not be ignored
62
+ if (parentTier === 'wip' && childTier === 'ignored') {
63
+ return {
64
+ file: parentPath,
65
+ line,
66
+ message: `References ignored ${childLabel}: ${childPath}`,
67
+ suggestion: `Remove the validator-ignore tag from ${childPath}`,
68
+ severity: 'error',
69
+ category: 'wip',
70
+ };
71
+ }
72
+ return null;
73
+ }
74
+ //# sourceMappingURL=tier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tier.js","sourceRoot":"","sources":["../../src/validator/tier.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAI5D;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,WAAoC;IACzE,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC;IAC9B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,YAAY,CAAC;IAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IACrE,IAAI,UAAU,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QAAE,OAAO,SAAS,CAAC;IAC9D,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QAAE,OAAO,KAAK,CAAC;IACxF,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,KAA0B;IACrD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC/C,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAC9C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,SAAS;QACpC,MAAM,EAAE,WAAW,EAAE,GAAG,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACxD,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,sBAAsB,CAAC,WAAW,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAChC,UAAkB,EAClB,UAAuB,EACvB,SAAiB,EACjB,SAAsB,EACtB,UAAkB,EAClB,IAAa;IAEb,0DAA0D;IAC1D,IAAI,UAAU,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAE1C,+CAA+C;IAC/C,IAAI,UAAU,KAAK,YAAY,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;QACvD,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,IAAI;YACJ,OAAO,EAAE,kBAAkB,UAAU,KAAK,SAAS,EAAE;YACrD,UAAU,EAAE,2BAA2B,SAAS,mCAAmC;YACnF,QAAQ,EAAE,OAAO;YACjB,QAAQ,EAAE,YAAY;SACvB,CAAC;IACJ,CAAC;IACD,IAAI,UAAU,KAAK,YAAY,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC3D,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,IAAI;YACJ,OAAO,EAAE,sBAAsB,UAAU,KAAK,SAAS,EAAE;YACzD,UAAU,EAAE,wCAAwC,SAAS,mCAAmC;YAChG,QAAQ,EAAE,OAAO;YACjB,QAAQ,EAAE,YAAY;SACvB,CAAC;IACJ,CAAC;IAED,yCAAyC;IACzC,IAAI,UAAU,KAAK,KAAK,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QACpD,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,IAAI;YACJ,OAAO,EAAE,sBAAsB,UAAU,KAAK,SAAS,EAAE;YACzD,UAAU,EAAE,wCAAwC,SAAS,EAAE;YAC/D,QAAQ,EAAE,OAAO;YACjB,QAAQ,EAAE,KAAK;SAChB,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -2,6 +2,8 @@ const CONCURRENCY = 10;
2
2
  const TIMEOUT_MS = 15_000;
3
3
  // Status codes that mean "server is alive" even though response.ok is false
4
4
  const REACHABLE_STATUSES = new Set([429]);
5
+ // Status codes that definitively mean the resource doesn't exist
6
+ const NOT_FOUND_STATUSES = new Set([404, 410]);
5
7
  async function fetchWithTimeout(url, method, signal) {
6
8
  return fetch(url, { method, signal });
7
9
  }
@@ -20,7 +22,7 @@ async function checkUrl(entry) {
20
22
  file: entry.file,
21
23
  line: entry.line,
22
24
  message: `${entry.label} returned HTTP ${response.status}: ${entry.url}`,
23
- severity: 'warning',
25
+ severity: NOT_FOUND_STATUSES.has(response.status) ? 'error' : 'warning',
24
26
  };
25
27
  }
26
28
  return null;