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
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { parseFrontmatter } from
|
|
2
|
-
import { parseSections, LO_SECTION_TYPES } from
|
|
3
|
-
import { parseWikilink, resolveWikilinkPath, hasRelativePath } from
|
|
4
|
-
import { detectFieldTypos } from
|
|
5
|
-
import { validateFrontmatter } from
|
|
6
|
-
import {
|
|
1
|
+
import { parseFrontmatter } from "./frontmatter.js";
|
|
2
|
+
import { parseSections, LO_SECTION_TYPES, } from "./sections.js";
|
|
3
|
+
import { parseWikilink, resolveWikilinkPath, hasRelativePath, } from "./wikilink.js";
|
|
4
|
+
import { detectFieldTypos } from "../validator/field-typos.js";
|
|
5
|
+
import { validateFrontmatter } from "../validator/validate-frontmatter.js";
|
|
6
|
+
import { validateTestSegments } from "../validator/test-segments.js";
|
|
7
|
+
import { convertSegment, stripAuthoringMarkup, LENS_SEGMENT_TYPES, } from "./lens.js";
|
|
7
8
|
export function parseLearningOutcome(content, file) {
|
|
8
9
|
const errors = [];
|
|
9
|
-
// Strip Obsidian comments before parsing
|
|
10
|
-
content =
|
|
10
|
+
// Strip authoring markup (CriticMarkup + Obsidian comments) before parsing
|
|
11
|
+
content = stripAuthoringMarkup(content);
|
|
11
12
|
// Step 1: Parse frontmatter and validate id field
|
|
12
13
|
const frontmatterResult = parseFrontmatter(content, file);
|
|
13
14
|
if (frontmatterResult.error) {
|
|
@@ -15,24 +16,25 @@ export function parseLearningOutcome(content, file) {
|
|
|
15
16
|
return { learningOutcome: null, errors };
|
|
16
17
|
}
|
|
17
18
|
const { frontmatter, body, bodyStartLine } = frontmatterResult;
|
|
18
|
-
const frontmatterErrors = validateFrontmatter(frontmatter,
|
|
19
|
+
const frontmatterErrors = validateFrontmatter(frontmatter, "learning-outcome", file);
|
|
19
20
|
errors.push(...frontmatterErrors);
|
|
20
|
-
if (frontmatterErrors.some(e => e.severity ===
|
|
21
|
+
if (frontmatterErrors.some((e) => e.severity === "error")) {
|
|
21
22
|
return { learningOutcome: null, errors };
|
|
22
23
|
}
|
|
23
24
|
// LO-specific: id must be a string
|
|
24
|
-
if (typeof frontmatter.id !==
|
|
25
|
+
if (typeof frontmatter.id !== "string") {
|
|
25
26
|
errors.push({
|
|
26
27
|
file,
|
|
27
28
|
line: 2,
|
|
28
29
|
message: `Field 'id' must be a string, got ${typeof frontmatter.id}`,
|
|
29
30
|
suggestion: "Use quotes: id: '12345'",
|
|
30
|
-
severity:
|
|
31
|
+
severity: "error",
|
|
31
32
|
});
|
|
32
33
|
return { learningOutcome: null, errors };
|
|
33
34
|
}
|
|
34
|
-
// Step 2: Parse sections with H2 level and LO_SECTION_TYPES
|
|
35
|
-
const
|
|
35
|
+
// Step 2: Parse sections with H2 level and LO_SECTION_TYPES + 'submodule'
|
|
36
|
+
const loSectionTypes = new Set([...LO_SECTION_TYPES, "submodule"]);
|
|
37
|
+
const sectionsResult = parseSections(body, 0, loSectionTypes, file);
|
|
36
38
|
// Adjust line numbers to account for frontmatter
|
|
37
39
|
for (const error of sectionsResult.errors) {
|
|
38
40
|
if (error.line) {
|
|
@@ -43,31 +45,85 @@ export function parseLearningOutcome(content, file) {
|
|
|
43
45
|
for (const section of sectionsResult.sections) {
|
|
44
46
|
section.line += bodyStartLine - 1;
|
|
45
47
|
}
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
let testRef;
|
|
49
|
-
for (const section of sectionsResult.sections) {
|
|
50
|
-
// Detect likely typos in field names
|
|
48
|
+
// Helper: extract a lens ref from a parsed section
|
|
49
|
+
function extractLensRef(section) {
|
|
51
50
|
const typoWarnings = detectFieldTypos(section.fields, file, section.line);
|
|
52
51
|
errors.push(...typoWarnings);
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
52
|
+
const source = section.fields.source;
|
|
53
|
+
if (!source) {
|
|
54
|
+
errors.push({
|
|
55
|
+
file,
|
|
56
|
+
line: section.line,
|
|
57
|
+
message: "Lens section missing source:: field",
|
|
58
|
+
suggestion: "Add 'source:: [[../Lenses/filename.md|Display]]' to the lens section",
|
|
59
|
+
severity: "error",
|
|
60
|
+
});
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
const wikilink = parseWikilink(source);
|
|
64
|
+
if (!wikilink || wikilink.error) {
|
|
65
|
+
const suggestion = wikilink?.correctedPath
|
|
66
|
+
? `Did you mean '[[${wikilink.correctedPath}]]'?`
|
|
67
|
+
: "Use format [[../Lenses/filename.md|Display Text]]";
|
|
68
|
+
errors.push({
|
|
69
|
+
file,
|
|
70
|
+
line: section.line,
|
|
71
|
+
message: wikilink?.error
|
|
72
|
+
? `${wikilink.error} in source:: field: ${source}`
|
|
73
|
+
: `Invalid wikilink format in source:: field: ${source}`,
|
|
74
|
+
suggestion,
|
|
75
|
+
severity: "error",
|
|
76
|
+
});
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
if (!hasRelativePath(wikilink.path)) {
|
|
80
|
+
errors.push({
|
|
81
|
+
file,
|
|
82
|
+
line: section.line,
|
|
83
|
+
message: `source:: path must be relative (contain /): ${wikilink.path}`,
|
|
84
|
+
suggestion: "Use format [[../Lenses/filename.md|Display Text]] with relative path",
|
|
85
|
+
severity: "error",
|
|
86
|
+
});
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
const resolvedPath = resolveWikilinkPath(wikilink.path, file);
|
|
90
|
+
const optional = section.fields.optional?.toLowerCase() === "true";
|
|
91
|
+
const hide = section.fields.hide?.toLowerCase() === "true";
|
|
92
|
+
return { source, resolvedPath, optional, hide };
|
|
93
|
+
}
|
|
94
|
+
// Helper: extract test ref from a parsed section
|
|
95
|
+
function extractTestRef(section) {
|
|
96
|
+
const id = section.fields.id;
|
|
97
|
+
if (!id) {
|
|
98
|
+
const hasSource = Boolean(section.fields.source);
|
|
99
|
+
const hasSegmentHeader = /^(#{1,6})\s+(Text|Question|Chat|Roleplay)(?::|\s*$)/im.test(section.body);
|
|
100
|
+
const hasKnownTestFields = [
|
|
101
|
+
"content",
|
|
102
|
+
"assessment-instructions",
|
|
103
|
+
"ai-instructions",
|
|
104
|
+
"opening-message",
|
|
105
|
+
"feedback",
|
|
106
|
+
].some((field) => section.fields[field] !== undefined);
|
|
107
|
+
if (!hasSource && !hasSegmentHeader && !hasKnownTestFields) {
|
|
108
|
+
return undefined;
|
|
64
109
|
}
|
|
65
|
-
|
|
110
|
+
errors.push({
|
|
111
|
+
file,
|
|
112
|
+
line: section.line,
|
|
113
|
+
message: "Test section missing required id:: field",
|
|
114
|
+
suggestion: "Add an id:: field with a UUID (e.g., id:: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)",
|
|
115
|
+
severity: "error",
|
|
116
|
+
});
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
const source = section.fields.source;
|
|
120
|
+
let resolvedPath;
|
|
121
|
+
if (source) {
|
|
66
122
|
const wikilink = parseWikilink(source);
|
|
67
123
|
if (!wikilink || wikilink.error) {
|
|
68
124
|
const suggestion = wikilink?.correctedPath
|
|
69
125
|
? `Did you mean '[[${wikilink.correctedPath}]]'?`
|
|
70
|
-
:
|
|
126
|
+
: "Use format [[../Tests/filename.md|Display Text]]";
|
|
71
127
|
errors.push({
|
|
72
128
|
file,
|
|
73
129
|
line: section.line,
|
|
@@ -75,80 +131,100 @@ export function parseLearningOutcome(content, file) {
|
|
|
75
131
|
? `${wikilink.error} in source:: field: ${source}`
|
|
76
132
|
: `Invalid wikilink format in source:: field: ${source}`,
|
|
77
133
|
suggestion,
|
|
78
|
-
severity:
|
|
134
|
+
severity: "error",
|
|
79
135
|
});
|
|
80
|
-
|
|
136
|
+
return undefined;
|
|
81
137
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
suggestion: 'Use format [[../Lenses/filename.md|Display Text]] with relative path',
|
|
89
|
-
severity: 'error',
|
|
90
|
-
});
|
|
91
|
-
continue;
|
|
138
|
+
resolvedPath = resolveWikilinkPath(wikilink.path, file);
|
|
139
|
+
}
|
|
140
|
+
const { sections: rawSegments, errors: segmentErrors } = parseSections(section.body, section.level, LENS_SEGMENT_TYPES, file, true);
|
|
141
|
+
for (const err of segmentErrors) {
|
|
142
|
+
if (err.line) {
|
|
143
|
+
err.line += bodyStartLine - 1;
|
|
92
144
|
}
|
|
93
|
-
const resolvedPath = resolveWikilinkPath(wikilink.path, file);
|
|
94
|
-
const optional = section.fields.optional?.toLowerCase() === 'true';
|
|
95
|
-
lenses.push({
|
|
96
|
-
source,
|
|
97
|
-
resolvedPath,
|
|
98
|
-
optional,
|
|
99
|
-
});
|
|
100
145
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const suggestion = wikilink?.correctedPath
|
|
109
|
-
? `Did you mean '[[${wikilink.correctedPath}]]'?`
|
|
110
|
-
: 'Use format [[../Tests/filename.md|Display Text]]';
|
|
111
|
-
errors.push({
|
|
112
|
-
file,
|
|
113
|
-
line: section.line,
|
|
114
|
-
message: wikilink?.error
|
|
115
|
-
? `${wikilink.error} in source:: field: ${source}`
|
|
116
|
-
: `Invalid wikilink format in source:: field: ${source}`,
|
|
117
|
-
suggestion,
|
|
118
|
-
severity: 'error',
|
|
119
|
-
});
|
|
120
|
-
continue;
|
|
121
|
-
}
|
|
122
|
-
resolvedPath = resolveWikilinkPath(wikilink.path, file);
|
|
146
|
+
errors.push(...segmentErrors);
|
|
147
|
+
// A Test is an assessment: only question/roleplay segments are rendered and
|
|
148
|
+
// scored. Flag any other segment type (e.g. intro text) — it is silently dropped.
|
|
149
|
+
const testSegmentErrors = validateTestSegments(rawSegments, file);
|
|
150
|
+
for (const err of testSegmentErrors) {
|
|
151
|
+
if (err.line) {
|
|
152
|
+
err.line += bodyStartLine - 1;
|
|
123
153
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
154
|
+
}
|
|
155
|
+
errors.push(...testSegmentErrors);
|
|
156
|
+
const testSegments = [];
|
|
157
|
+
for (const rawSeg of rawSegments) {
|
|
158
|
+
const { segment, errors: conversionErrors } = convertSegment(rawSeg, "lens", file);
|
|
159
|
+
for (const err of conversionErrors) {
|
|
128
160
|
if (err.line) {
|
|
129
161
|
err.line += bodyStartLine - 1;
|
|
130
162
|
}
|
|
131
163
|
}
|
|
132
|
-
errors.push(...
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
164
|
+
errors.push(...conversionErrors);
|
|
165
|
+
if (segment) {
|
|
166
|
+
testSegments.push(segment);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return { id, source, resolvedPath, segments: testSegments };
|
|
170
|
+
}
|
|
171
|
+
// Step 3: Check for submodule sections
|
|
172
|
+
const hasSubmodules = sectionsResult.sections.some((s) => s.type === "submodule");
|
|
173
|
+
const lenses = [];
|
|
174
|
+
let testRef;
|
|
175
|
+
let submodules;
|
|
176
|
+
if (hasSubmodules) {
|
|
177
|
+
// All-or-nothing: reject top-level lens/test sections when submodules exist
|
|
178
|
+
const orphanedSections = sectionsResult.sections.filter((s) => s.type !== "submodule");
|
|
179
|
+
if (orphanedSections.length > 0) {
|
|
180
|
+
errors.push({
|
|
181
|
+
file,
|
|
182
|
+
line: orphanedSections[0].line,
|
|
183
|
+
message: "Content found outside submodule boundaries — when using Submodule markers, all content must be inside a submodule",
|
|
184
|
+
suggestion: "Move this content into a Submodule section",
|
|
185
|
+
severity: "error",
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
submodules = [];
|
|
189
|
+
for (const section of sectionsResult.sections) {
|
|
190
|
+
if (section.type !== "submodule")
|
|
191
|
+
continue;
|
|
192
|
+
const group = {
|
|
193
|
+
title: section.title,
|
|
194
|
+
customSlug: section.fields.slug,
|
|
195
|
+
lenses: [],
|
|
196
|
+
};
|
|
197
|
+
// Process children (lens/test sections at H3)
|
|
198
|
+
if (section.children) {
|
|
199
|
+
for (const child of section.children) {
|
|
200
|
+
if (child.type === "lens") {
|
|
201
|
+
const ref = extractLensRef(child);
|
|
202
|
+
if (ref) {
|
|
203
|
+
group.lenses.push(ref);
|
|
204
|
+
lenses.push(ref); // Also add to flat list for validation
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
else if (child.type === "test") {
|
|
208
|
+
group.test = extractTestRef(child);
|
|
140
209
|
}
|
|
141
|
-
}
|
|
142
|
-
errors.push(...conversionErrors);
|
|
143
|
-
if (segment) {
|
|
144
|
-
testSegments.push(segment);
|
|
145
210
|
}
|
|
146
211
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
212
|
+
submodules.push(group);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
// Normal path: extract lens refs from top-level sections
|
|
217
|
+
for (const section of sectionsResult.sections) {
|
|
218
|
+
const typoWarnings = detectFieldTypos(section.fields, file, section.line);
|
|
219
|
+
errors.push(...typoWarnings);
|
|
220
|
+
if (section.type === "lens") {
|
|
221
|
+
const ref = extractLensRef(section);
|
|
222
|
+
if (ref)
|
|
223
|
+
lenses.push(ref);
|
|
224
|
+
}
|
|
225
|
+
else if (section.type === "test") {
|
|
226
|
+
testRef = extractTestRef(section);
|
|
227
|
+
}
|
|
152
228
|
}
|
|
153
229
|
}
|
|
154
230
|
// Step 4: Validate at least one lens exists
|
|
@@ -156,17 +232,22 @@ export function parseLearningOutcome(content, file) {
|
|
|
156
232
|
errors.push({
|
|
157
233
|
file,
|
|
158
234
|
line: bodyStartLine,
|
|
159
|
-
message:
|
|
235
|
+
message: "Learning Outcome must have at least one ## Lens: section",
|
|
160
236
|
suggestion: "Add a '## Lens: <title>' section with a source:: field",
|
|
161
|
-
severity:
|
|
237
|
+
severity: "error",
|
|
162
238
|
});
|
|
163
239
|
}
|
|
240
|
+
const loAddToAiContext = "add_to_ai_context" in frontmatter
|
|
241
|
+
? frontmatter.add_to_ai_context
|
|
242
|
+
: undefined;
|
|
164
243
|
// Return result even if there are errors (partial success)
|
|
165
244
|
const learningOutcome = {
|
|
166
245
|
id: frontmatter.id,
|
|
167
246
|
lenses,
|
|
168
247
|
test: testRef,
|
|
169
248
|
discussion: frontmatter.discussion,
|
|
249
|
+
submodules,
|
|
250
|
+
addToAiContext: loAddToAiContext,
|
|
170
251
|
};
|
|
171
252
|
return { learningOutcome, errors };
|
|
172
253
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learning-outcome.js","sourceRoot":"","sources":["../../src/parser/learning-outcome.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,
|
|
1
|
+
{"version":3,"file":"learning-outcome.js","sourceRoot":"","sources":["../../src/parser/learning-outcome.ts"],"names":[],"mappings":"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"}
|
package/dist/parser/lens.d.ts
CHANGED
|
@@ -6,22 +6,25 @@ export interface ParsedTextSegment {
|
|
|
6
6
|
}
|
|
7
7
|
export interface ParsedChatSegment {
|
|
8
8
|
type: 'chat';
|
|
9
|
-
title?: string;
|
|
10
9
|
instructions?: string;
|
|
11
10
|
hidePreviousContentFromUser?: boolean;
|
|
12
11
|
hidePreviousContentFromTutor?: boolean;
|
|
13
12
|
optional?: boolean;
|
|
14
13
|
}
|
|
15
|
-
export interface
|
|
16
|
-
type: 'article
|
|
14
|
+
export interface ParsedArticleSegment {
|
|
15
|
+
type: 'article';
|
|
16
|
+
source?: string;
|
|
17
|
+
resolvedPath?: string;
|
|
17
18
|
fromAnchor?: string;
|
|
18
19
|
toAnchor?: string;
|
|
19
20
|
optional?: boolean;
|
|
20
21
|
}
|
|
21
|
-
export interface
|
|
22
|
-
type: 'video
|
|
22
|
+
export interface ParsedVideoSegment {
|
|
23
|
+
type: 'video';
|
|
24
|
+
source?: string;
|
|
25
|
+
resolvedPath?: string;
|
|
23
26
|
fromTimeStr: string;
|
|
24
|
-
toTimeStr
|
|
27
|
+
toTimeStr?: string;
|
|
25
28
|
optional?: boolean;
|
|
26
29
|
}
|
|
27
30
|
export interface ParsedQuestionSegment {
|
|
@@ -34,37 +37,38 @@ export interface ParsedQuestionSegment {
|
|
|
34
37
|
optional?: boolean;
|
|
35
38
|
feedback?: boolean;
|
|
36
39
|
}
|
|
37
|
-
export
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
export interface ParsedRoleplaySegment {
|
|
41
|
+
type: 'roleplay';
|
|
42
|
+
id: string;
|
|
43
|
+
content: string;
|
|
44
|
+
aiInstructions: string;
|
|
45
|
+
openingMessage?: string;
|
|
46
|
+
assessmentInstructions?: string;
|
|
47
|
+
userCustomizable?: boolean;
|
|
48
|
+
optional?: boolean;
|
|
49
|
+
feedback?: boolean;
|
|
45
50
|
}
|
|
51
|
+
export type ParsedLensSegment = ParsedTextSegment | ParsedChatSegment | ParsedArticleSegment | ParsedVideoSegment | ParsedQuestionSegment | ParsedRoleplaySegment;
|
|
46
52
|
export interface ParsedLens {
|
|
47
53
|
id: string;
|
|
48
|
-
|
|
54
|
+
title?: string;
|
|
55
|
+
tldr?: string;
|
|
56
|
+
summaryForTutor?: string;
|
|
57
|
+
addToAiContext?: string[] | null;
|
|
58
|
+
segments: ParsedLensSegment[];
|
|
49
59
|
}
|
|
50
60
|
export interface LensParseResult {
|
|
51
61
|
lens: ParsedLens | null;
|
|
52
62
|
errors: ContentError[];
|
|
53
63
|
}
|
|
54
|
-
|
|
64
|
+
export declare const LENS_SEGMENT_TYPES: Set<string>;
|
|
65
|
+
/** Common interface for raw segments — compatible with ParsedSection */
|
|
66
|
+
export interface RawSegment {
|
|
55
67
|
type: string;
|
|
56
68
|
title?: string;
|
|
57
69
|
fields: Record<string, string>;
|
|
58
70
|
line: number;
|
|
59
71
|
}
|
|
60
|
-
/**
|
|
61
|
-
* Parse H4 segments from a section body.
|
|
62
|
-
* Segments are defined by `#### <type>` headers within a section.
|
|
63
|
-
*/
|
|
64
|
-
export declare function parseSegments(sectionBody: string, bodyStartLine: number, file: string): {
|
|
65
|
-
segments: RawSegment[];
|
|
66
|
-
errors: ContentError[];
|
|
67
|
-
};
|
|
68
72
|
/**
|
|
69
73
|
* Convert a raw segment to a typed ParsedLensSegment.
|
|
70
74
|
*/
|
|
@@ -77,12 +81,32 @@ export declare function convertSegment(raw: RawSegment, sectionType: string, fil
|
|
|
77
81
|
* Handles both inline (%% ... %% on same line) and block (multiline) comments.
|
|
78
82
|
*/
|
|
79
83
|
export declare function stripObsidianComments(content: string): string;
|
|
84
|
+
/**
|
|
85
|
+
* Strip CriticMarkup from content using reject-all-changes behavior:
|
|
86
|
+
* - {>>comments<<} -> removed
|
|
87
|
+
* - {++additions++} -> removed
|
|
88
|
+
* - {--deletions--} -> inner content kept (original preserved)
|
|
89
|
+
* - {~~old~>new~~} -> old text kept
|
|
90
|
+
* - {==highlights==} -> inner content kept, markers removed
|
|
91
|
+
*/
|
|
92
|
+
export declare function stripCriticMarkup(content: string): string;
|
|
93
|
+
/**
|
|
94
|
+
* Strip all authoring markup (CriticMarkup + Obsidian comments) from content.
|
|
95
|
+
* Call at the top of each parser before any processing.
|
|
96
|
+
*/
|
|
97
|
+
export declare function stripAuthoringMarkup(content: string): string;
|
|
98
|
+
/**
|
|
99
|
+
* Apply source inheritance for article and video segments.
|
|
100
|
+
* Each article/video segment inherits source:: from the previous segment of the same type.
|
|
101
|
+
* Errors if the first segment of a type has no source.
|
|
102
|
+
*
|
|
103
|
+
* Mutates segments in place. Returns any errors.
|
|
104
|
+
*/
|
|
105
|
+
export declare function applySourceInheritance(segments: ParsedLensSegment[], file: string): ContentError[];
|
|
80
106
|
/**
|
|
81
107
|
* Parse a lens file into structured lens data.
|
|
82
108
|
*
|
|
83
|
-
* Lens files
|
|
84
|
-
*
|
|
85
|
-
* - H4 (`####`) for segments: Text, Chat, Article-excerpt, Video-excerpt
|
|
109
|
+
* Lens files are flat: frontmatter + H4 segments directly.
|
|
110
|
+
* No H3 section headers. Source is on segments with inheritance.
|
|
86
111
|
*/
|
|
87
112
|
export declare function parseLens(content: string, file: string): LensParseResult;
|
|
88
|
-
export {};
|