lens-content-processor 0.64.0 → 0.66.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/content-schema.js +4 -2
- package/dist/content-schema.js.map +1 -1
- package/dist/flattener/index.js +20 -21
- package/dist/flattener/index.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/parser/lens.d.ts +6 -2
- package/dist/parser/lens.js +31 -2
- package/dist/parser/lens.js.map +1 -1
- package/dist/validator/card-module-membership.js +2 -10
- package/dist/validator/card-module-membership.js.map +1 -1
- package/dist/validator/directives.js +8 -0
- package/dist/validator/directives.js.map +1 -1
- package/dist/validator/lens-cards.d.ts +8 -0
- package/dist/validator/lens-cards.js +15 -0
- package/dist/validator/lens-cards.js.map +1 -0
- package/dist/validator/optional-lens-sets.d.ts +16 -0
- package/dist/validator/optional-lens-sets.js +157 -0
- package/dist/validator/optional-lens-sets.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { lensCardsIn } from "./lens-cards.js";
|
|
2
|
+
const NAME = "require_x_optional_lenses";
|
|
3
|
+
// A container fence: three or more colons, then a name (opener) or nothing
|
|
4
|
+
// (closer). A closer closes the innermost container whose fence is no
|
|
5
|
+
// longer than its own, as remark-directive reads it.
|
|
6
|
+
const FENCE_RE = /^\s*(:{3,})\s*([\w-]*)(\{[^}]*\})?\s*$/;
|
|
7
|
+
const X_ATTR_RE = /(?:^|[\s{])x\s*=\s*"?([^"\s}]*)"?/;
|
|
8
|
+
/** Each require_x_optional_lenses list in a text: its attributes and body
|
|
9
|
+
* (nested containers, such as a :::hide, stay inside the body). */
|
|
10
|
+
function listsIn(text) {
|
|
11
|
+
const lists = [];
|
|
12
|
+
const stack = [];
|
|
13
|
+
for (const line of text.split("\n")) {
|
|
14
|
+
const fence = line.match(FENCE_RE);
|
|
15
|
+
const open = stack.find((s) => s.list)?.list;
|
|
16
|
+
if (fence && fence[2]) {
|
|
17
|
+
stack.push({
|
|
18
|
+
fence: fence[1].length,
|
|
19
|
+
list: fence[2] === NAME && !open
|
|
20
|
+
? { attrs: fence[3] ?? "", body: [] }
|
|
21
|
+
: undefined,
|
|
22
|
+
});
|
|
23
|
+
if (open)
|
|
24
|
+
open.body.push(line);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (fence) {
|
|
28
|
+
let at = stack.length - 1;
|
|
29
|
+
while (at >= 0 && stack[at].fence > fence[1].length)
|
|
30
|
+
at -= 1;
|
|
31
|
+
if (at !== -1) {
|
|
32
|
+
const closed = stack.splice(at);
|
|
33
|
+
const list = closed.find((s) => s.list)?.list;
|
|
34
|
+
if (list)
|
|
35
|
+
lists.push({ attrs: list.attrs, body: list.body.join("\n") });
|
|
36
|
+
else if (open)
|
|
37
|
+
open.body.push(line);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (open)
|
|
42
|
+
open.body.push(line);
|
|
43
|
+
}
|
|
44
|
+
return lists;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Record every `:::require_x_optional_lenses` list on its section and check
|
|
48
|
+
* it: x a positive whole number no larger than the list; every card a lens
|
|
49
|
+
* of the same (sub)module, other than the lens itself, listed once; a
|
|
50
|
+
* required lens in the list warns, since it would stand in for an optional
|
|
51
|
+
* one; and a list on an optional lens warns, since optional lenses never
|
|
52
|
+
* gate. Same (sub)module only, so the page knows every listed lens's
|
|
53
|
+
* completion (a sibling submodule's is not loaded there).
|
|
54
|
+
*/
|
|
55
|
+
export function collectOptionalLensSets(modules) {
|
|
56
|
+
const errors = [];
|
|
57
|
+
for (const mod of modules) {
|
|
58
|
+
if (mod.slug.startsWith("lens/"))
|
|
59
|
+
continue;
|
|
60
|
+
const inModule = new Map();
|
|
61
|
+
for (const section of mod.sections) {
|
|
62
|
+
if (section.contentId)
|
|
63
|
+
inModule.set(section.contentId, section);
|
|
64
|
+
}
|
|
65
|
+
for (const section of mod.sections) {
|
|
66
|
+
const file = section.sourcePath ?? mod.sourcePath ?? `module:${mod.slug}`;
|
|
67
|
+
const sets = [];
|
|
68
|
+
section.segments.forEach((seg, segmentIndex) => {
|
|
69
|
+
if (seg.type !== "text" || !seg.content.includes(NAME))
|
|
70
|
+
return;
|
|
71
|
+
const lists = listsIn(seg.content);
|
|
72
|
+
if (lists.length === 0) {
|
|
73
|
+
errors.push({
|
|
74
|
+
file,
|
|
75
|
+
message: `"${NAME}" is not a list here: write it as a container, ':::${NAME}{x=2}' … ':::'`,
|
|
76
|
+
suggestion: `Put ':::${NAME}{x=2}' on its own line before the ::card lines, and ':::' on its own line after them`,
|
|
77
|
+
severity: "error",
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
for (const list of lists) {
|
|
81
|
+
const set = checkList(list, segmentIndex, file, section, inModule, mod.slug, errors);
|
|
82
|
+
if (set)
|
|
83
|
+
sets.push(set);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
if (sets.length === 0)
|
|
87
|
+
continue;
|
|
88
|
+
section.optionalLensSets = sets;
|
|
89
|
+
if (section.optional) {
|
|
90
|
+
errors.push({
|
|
91
|
+
file,
|
|
92
|
+
message: `":::${NAME}" is on the optional lens "${section.meta?.title ?? section.contentId}", which never gates`,
|
|
93
|
+
suggestion: "Put the list on a required lens, or remove optional:: true from this lens in the module file",
|
|
94
|
+
severity: "warning",
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return errors;
|
|
100
|
+
}
|
|
101
|
+
function checkList(list, segmentIndex, file, holder, inModule, moduleSlug, errors) {
|
|
102
|
+
const contentIds = [];
|
|
103
|
+
for (const card of lensCardsIn(list.body)) {
|
|
104
|
+
const name = card.title ?? card.contentId;
|
|
105
|
+
const target = card.contentId ? inModule.get(card.contentId) : undefined;
|
|
106
|
+
let problem = null;
|
|
107
|
+
if (card.targetType !== "lens" || !target) {
|
|
108
|
+
problem = `points to "${name}", which is not a lens of "${moduleSlug}"`;
|
|
109
|
+
}
|
|
110
|
+
else if (target === holder) {
|
|
111
|
+
problem = `points to "${name}", the lens that holds the list`;
|
|
112
|
+
}
|
|
113
|
+
else if (contentIds.includes(card.contentId)) {
|
|
114
|
+
problem = `lists "${name}" twice`;
|
|
115
|
+
}
|
|
116
|
+
if (problem) {
|
|
117
|
+
errors.push({
|
|
118
|
+
file,
|
|
119
|
+
message: `A card in ":::${NAME}" ${problem}`,
|
|
120
|
+
suggestion: "List each optional lens of this part once ({allow-external} does not apply here)",
|
|
121
|
+
severity: "error",
|
|
122
|
+
});
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (!target.optional) {
|
|
126
|
+
errors.push({
|
|
127
|
+
file,
|
|
128
|
+
message: `The card "${name}" in ":::${NAME}" is a required lens, so it would count toward the optional ones`,
|
|
129
|
+
suggestion: "Mark that lens optional:: true in the module file, or take it out of the list",
|
|
130
|
+
severity: "warning",
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
contentIds.push(card.contentId);
|
|
134
|
+
}
|
|
135
|
+
const raw = list.attrs.match(X_ATTR_RE)?.[1] ?? "";
|
|
136
|
+
const x = /^\d+$/.test(raw) ? parseInt(raw, 10) : 0;
|
|
137
|
+
if (x < 1) {
|
|
138
|
+
errors.push({
|
|
139
|
+
file,
|
|
140
|
+
message: `":::${NAME}" needs x as a positive number${raw ? `, got '${raw}'` : ""}`,
|
|
141
|
+
suggestion: `Write it as ':::${NAME}{x=2}'`,
|
|
142
|
+
severity: "error",
|
|
143
|
+
});
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
if (x > contentIds.length) {
|
|
147
|
+
errors.push({
|
|
148
|
+
file,
|
|
149
|
+
message: `":::${NAME}" asks for ${x}, but lists ${contentIds.length} lens${contentIds.length === 1 ? "" : "es"}`,
|
|
150
|
+
suggestion: "Lower x, or add ::card lines for more optional lenses",
|
|
151
|
+
severity: "error",
|
|
152
|
+
});
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
return { x, contentIds, segmentIndex };
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=optional-lens-sets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"optional-lens-sets.js","sourceRoot":"","sources":["../../src/validator/optional-lens-sets.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED