lens-content-processor 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/dist/bundler/article.d.ts +7 -2
- package/dist/bundler/article.js +19 -8
- package/dist/bundler/article.js.map +1 -1
- package/dist/bundler/video.d.ts +12 -6
- package/dist/bundler/video.js +57 -34
- package/dist/bundler/video.js.map +1 -1
- package/dist/cli.d.ts +11 -2
- package/dist/cli.js +36 -19
- package/dist/cli.js.map +1 -1
- package/dist/content-schema.js +64 -15
- package/dist/content-schema.js.map +1 -1
- package/dist/dedupe-errors.d.ts +14 -0
- package/dist/dedupe-errors.js +33 -0
- package/dist/dedupe-errors.js.map +1 -0
- package/dist/flattener/index.d.ts +22 -28
- package/dist/flattener/index.js +773 -613
- package/dist/flattener/index.js.map +1 -1
- package/dist/flattener/resolve-text-links.d.ts +25 -0
- package/dist/flattener/resolve-text-links.js +248 -0
- package/dist/flattener/resolve-text-links.js.map +1 -0
- package/dist/flattener/test-helpers.d.ts +23 -0
- package/dist/flattener/test-helpers.js +56 -0
- package/dist/flattener/test-helpers.js.map +1 -0
- package/dist/index.d.ts +66 -20
- package/dist/index.js +327 -152
- package/dist/index.js.map +1 -1
- package/dist/parser/article.d.ts +3 -2
- package/dist/parser/article.js +80 -12
- package/dist/parser/article.js.map +1 -1
- package/dist/parser/course.d.ts +1 -1
- package/dist/parser/course.js +88 -28
- package/dist/parser/course.js.map +1 -1
- package/dist/parser/frontmatter.d.ts +1 -1
- package/dist/parser/frontmatter.js +38 -12
- package/dist/parser/frontmatter.js.map +1 -1
- package/dist/parser/learning-outcome.d.ts +12 -2
- package/dist/parser/learning-outcome.js +177 -96
- package/dist/parser/learning-outcome.js.map +1 -1
- package/dist/parser/lens.d.ts +52 -28
- package/dist/parser/lens.js +283 -260
- package/dist/parser/lens.js.map +1 -1
- package/dist/parser/module.d.ts +7 -15
- package/dist/parser/module.js +139 -170
- package/dist/parser/module.js.map +1 -1
- package/dist/parser/sections.d.ts +14 -1
- package/dist/parser/sections.js +94 -81
- package/dist/parser/sections.js.map +1 -1
- package/dist/parser/video-transcript.d.ts +2 -1
- package/dist/parser/video-transcript.js +10 -6
- package/dist/parser/video-transcript.js.map +1 -1
- package/dist/reference-graph.d.ts +8 -0
- package/dist/reference-graph.js +105 -0
- package/dist/reference-graph.js.map +1 -0
- package/dist/validator/card-module-membership.d.ts +2 -0
- package/dist/validator/card-module-membership.js +80 -0
- package/dist/validator/card-module-membership.js.map +1 -0
- package/dist/validator/directives.d.ts +12 -0
- package/dist/validator/directives.js +428 -0
- package/dist/validator/directives.js.map +1 -0
- package/dist/validator/field-values.js +14 -0
- package/dist/validator/field-values.js.map +1 -1
- package/dist/validator/output-integrity.js +5 -5
- package/dist/validator/output-integrity.js.map +1 -1
- package/dist/validator/segment-fields.d.ts +1 -1
- package/dist/validator/segment-fields.js +2 -2
- package/dist/validator/segment-fields.js.map +1 -1
- package/dist/validator/test-segments.d.ts +12 -0
- package/dist/validator/test-segments.js +40 -0
- package/dist/validator/test-segments.js.map +1 -0
- package/dist/validator/url-reachability.d.ts +2 -1
- package/dist/validator/url-reachability.js +42 -20
- package/dist/validator/url-reachability.js.map +1 -1
- package/dist/validator/uuid.js +9 -6
- package/dist/validator/uuid.js.map +1 -1
- package/package.json +1 -1
- package/dist/validator/chat-precedence.d.ts +0 -9
- package/dist/validator/chat-precedence.js +0 -32
- package/dist/validator/chat-precedence.js.map +0 -1
|
@@ -2,43 +2,65 @@ 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
|
-
|
|
6
|
-
|
|
5
|
+
// Status codes that definitively mean the resource doesn't exist
|
|
6
|
+
const NOT_FOUND_STATUSES = new Set([404, 410]);
|
|
7
|
+
// Shown on every "could not confirm reachable" warning, pointing at the opt-out.
|
|
8
|
+
const OVERRIDE_HINT = "If you have verified this URL works in a browser, add 'allowUnreachableUrl: true' to the frontmatter to suppress this warning.";
|
|
9
|
+
// Each call gets its own timeout so HEAD and a retried GET don't share one budget.
|
|
10
|
+
async function fetchWithTimeout(url, method) {
|
|
11
|
+
const controller = new AbortController();
|
|
12
|
+
const timeout = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
13
|
+
try {
|
|
14
|
+
return await fetch(url, { method, signal: controller.signal });
|
|
15
|
+
}
|
|
16
|
+
finally {
|
|
17
|
+
clearTimeout(timeout);
|
|
18
|
+
}
|
|
7
19
|
}
|
|
8
20
|
async function checkUrl(entry) {
|
|
9
21
|
try {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
//
|
|
14
|
-
|
|
15
|
-
|
|
22
|
+
let response = await fetchWithTimeout(entry.url, "HEAD");
|
|
23
|
+
// A HEAD that isn't a definitive answer (not OK, not a known 404/410 or
|
|
24
|
+
// rate-limit) may just mean the server rejects the HEAD method: some do so
|
|
25
|
+
// with 405, others unconventionally with 403. Retry with GET to get the true
|
|
26
|
+
// status; this also surfaces a real 404/410 that a HEAD rejection could mask.
|
|
27
|
+
if (!response.ok &&
|
|
28
|
+
!NOT_FOUND_STATUSES.has(response.status) &&
|
|
29
|
+
!REACHABLE_STATUSES.has(response.status)) {
|
|
30
|
+
response = await fetchWithTimeout(entry.url, "GET");
|
|
16
31
|
}
|
|
17
|
-
clearTimeout(timeout);
|
|
18
32
|
if (!response.ok && !REACHABLE_STATUSES.has(response.status)) {
|
|
33
|
+
// 404/410 are definitively dead: an error, never overridable. Any other
|
|
34
|
+
// status means we could not confirm reachability (a 403 bot/WAF block, a
|
|
35
|
+
// 5xx, etc.); that warning can be vouched for by hand via allowUnreachable.
|
|
36
|
+
const isNotFound = NOT_FOUND_STATUSES.has(response.status);
|
|
37
|
+
if (!isNotFound && entry.allowUnreachable)
|
|
38
|
+
return null;
|
|
19
39
|
return {
|
|
20
40
|
file: entry.file,
|
|
21
41
|
line: entry.line,
|
|
22
42
|
message: `${entry.label} returned HTTP ${response.status}: ${entry.url}`,
|
|
23
|
-
severity:
|
|
43
|
+
severity: isNotFound ? "error" : "warning",
|
|
44
|
+
...(isNotFound ? {} : { suggestion: OVERRIDE_HINT }),
|
|
24
45
|
};
|
|
25
46
|
}
|
|
26
47
|
return null;
|
|
27
48
|
}
|
|
28
49
|
catch (error) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
};
|
|
36
|
-
}
|
|
50
|
+
// A timeout or network failure is "could not confirm" too (our own network, a
|
|
51
|
+
// transient DNS hiccup, or a flaky host), not a definitive 404/410, so it is
|
|
52
|
+
// overridable as well.
|
|
53
|
+
if (entry.allowUnreachable)
|
|
54
|
+
return null;
|
|
55
|
+
const aborted = error instanceof DOMException && error.name === "AbortError";
|
|
37
56
|
return {
|
|
38
57
|
file: entry.file,
|
|
39
58
|
line: entry.line,
|
|
40
|
-
message:
|
|
41
|
-
|
|
59
|
+
message: aborted
|
|
60
|
+
? `${entry.label} timed out: ${entry.url}`
|
|
61
|
+
: `${entry.label} unreachable: ${entry.url}`,
|
|
62
|
+
suggestion: OVERRIDE_HINT,
|
|
63
|
+
severity: "warning",
|
|
42
64
|
};
|
|
43
65
|
}
|
|
44
66
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url-reachability.js","sourceRoot":"","sources":["../../src/validator/url-reachability.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"url-reachability.js","sourceRoot":"","sources":["../../src/validator/url-reachability.ts"],"names":[],"mappings":"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"}
|
package/dist/validator/uuid.js
CHANGED
|
@@ -30,12 +30,15 @@ export function validateUuids(entries) {
|
|
|
30
30
|
// Duplicate detection
|
|
31
31
|
const existing = seenUuids.get(lowerUuid);
|
|
32
32
|
if (existing) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
// Allow same-file, same-field duplicates (e.g., contentId shared across submodule groups)
|
|
34
|
+
if (existing.file !== entry.file || existing.field !== entry.field) {
|
|
35
|
+
errors.push({
|
|
36
|
+
file: entry.file,
|
|
37
|
+
message: `Duplicate UUID '${entry.uuid}' - also used in ${existing.file} (${existing.field})`,
|
|
38
|
+
suggestion: 'Each UUID must be unique across the entire vault',
|
|
39
|
+
severity: 'error',
|
|
40
|
+
});
|
|
41
|
+
}
|
|
39
42
|
}
|
|
40
43
|
else {
|
|
41
44
|
seenUuids.set(lowerUuid, entry);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uuid.js","sourceRoot":"","sources":["../../src/validator/uuid.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,UAAU,GAAG,iEAAiE,CAAC;AAErF;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC;AAYD;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,OAAoB;IAChD,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAqB,CAAC,CAAC,2BAA2B;IAE3E,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QAE3C,oBAAoB;QACpB,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,OAAO,EAAE,2BAA2B,KAAK,CAAC,KAAK,MAAM,KAAK,CAAC,IAAI,GAAG;gBAClE,UAAU,EAAE,0FAA0F;gBACtG,QAAQ,EAAE,OAAO;aAClB,CAAC,CAAC;YACH,SAAS,CAAC,yCAAyC;QACrD,CAAC;QAED,sBAAsB;QACtB,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1C,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"uuid.js","sourceRoot":"","sources":["../../src/validator/uuid.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,UAAU,GAAG,iEAAiE,CAAC;AAErF;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC;AAYD;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,OAAoB;IAChD,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAqB,CAAC,CAAC,2BAA2B;IAE3E,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QAE3C,oBAAoB;QACpB,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,OAAO,EAAE,2BAA2B,KAAK,CAAC,KAAK,MAAM,KAAK,CAAC,IAAI,GAAG;gBAClE,UAAU,EAAE,0FAA0F;gBACtG,QAAQ,EAAE,OAAO;aAClB,CAAC,CAAC;YACH,SAAS,CAAC,yCAAyC;QACrD,CAAC;QAED,sBAAsB;QACtB,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1C,IAAI,QAAQ,EAAE,CAAC;YACb,0FAA0F;YAC1F,IAAI,QAAQ,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,IAAI,QAAQ,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,EAAE,CAAC;gBACnE,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,OAAO,EAAE,mBAAmB,KAAK,CAAC,IAAI,oBAAoB,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,KAAK,GAAG;oBAC7F,UAAU,EAAE,kDAAkD;oBAC9D,QAAQ,EAAE,OAAO;iBAClB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;aAAM,CAAC;YACN,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,CAAC;AACpB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { ContentError } from '../index.js';
|
|
2
|
-
/**
|
|
3
|
-
* Validate that every Chat segment is immediately preceded by a Text segment.
|
|
4
|
-
* Students need instructions (Text) before every interactive discussion (Chat).
|
|
5
|
-
*/
|
|
6
|
-
export declare function validateChatPrecedence(segments: {
|
|
7
|
-
type: string;
|
|
8
|
-
line: number;
|
|
9
|
-
}[], file: string): ContentError[];
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Validate that every Chat segment is immediately preceded by a Text segment.
|
|
3
|
-
* Students need instructions (Text) before every interactive discussion (Chat).
|
|
4
|
-
*/
|
|
5
|
-
export function validateChatPrecedence(segments, file) {
|
|
6
|
-
const errors = [];
|
|
7
|
-
for (let i = 0; i < segments.length; i++) {
|
|
8
|
-
if (segments[i].type !== 'chat')
|
|
9
|
-
continue;
|
|
10
|
-
const prev = segments[i - 1];
|
|
11
|
-
if (!prev) {
|
|
12
|
-
errors.push({
|
|
13
|
-
file,
|
|
14
|
-
line: segments[i].line,
|
|
15
|
-
message: "'#### Chat' must be immediately preceded by a '#### Text' segment, but it is the first segment in the section",
|
|
16
|
-
suggestion: "Add a '#### Text' segment with content:: before this '#### Chat'",
|
|
17
|
-
severity: 'error',
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
else if (prev.type !== 'text') {
|
|
21
|
-
errors.push({
|
|
22
|
-
file,
|
|
23
|
-
line: segments[i].line,
|
|
24
|
-
message: `'#### Chat' must be immediately preceded by a '#### Text' segment, but found '#### ${prev.type}' instead`,
|
|
25
|
-
suggestion: "Add a '#### Text' segment with content:: before this '#### Chat'",
|
|
26
|
-
severity: 'error',
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return errors;
|
|
31
|
-
}
|
|
32
|
-
//# sourceMappingURL=chat-precedence.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"chat-precedence.js","sourceRoot":"","sources":["../../src/validator/chat-precedence.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,QAA0C,EAC1C,IAAY;IAEZ,MAAM,MAAM,GAAmB,EAAE,CAAC;IAElC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM;YAAE,SAAS;QAE1C,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAE7B,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI;gBACJ,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI;gBACtB,OAAO,EAAE,+GAA+G;gBACxH,UAAU,EAAE,kEAAkE;gBAC9E,QAAQ,EAAE,OAAO;aAClB,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAChC,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI;gBACJ,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI;gBACtB,OAAO,EAAE,sFAAsF,IAAI,CAAC,IAAI,WAAW;gBACnH,UAAU,EAAE,kEAAkE;gBAC9E,QAAQ,EAAE,OAAO;aAClB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|