lens-content-processor 0.26.0 → 0.28.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.
@@ -0,0 +1,86 @@
1
+ import katex from "katex";
2
+ import { stripAuthoringMarkup } from "../authoring-markup.js";
3
+ const INLINE_MATH_RE = /(?<!\$)\$(?!\$)([^\s$](?:[^$\n]*?[^\s$])?)\$(?![\d$])/g;
4
+ function maskNonMathMarkdown(content) {
5
+ const authored = stripAuthoringMarkup(content);
6
+ const lines = authored.split("\n");
7
+ let inFrontmatter = lines[0]?.trim() === "---";
8
+ let inFence = null;
9
+ return lines
10
+ .map((line, index) => {
11
+ if (inFrontmatter) {
12
+ if (index > 0 && line.trim() === "---")
13
+ inFrontmatter = false;
14
+ return "";
15
+ }
16
+ const fence = line.match(/^\s*(`{3,}|~{3,})/);
17
+ if (fence) {
18
+ const marker = fence[1][0];
19
+ if (inFence === marker)
20
+ inFence = null;
21
+ else if (inFence === null)
22
+ inFence = marker;
23
+ return "";
24
+ }
25
+ if (inFence)
26
+ return "";
27
+ // Inline code is opaque to the markdown math plugins too.
28
+ return line.replace(/(`+)(.*?)\1/g, (match) => " ".repeat(match.length));
29
+ })
30
+ .join("\n");
31
+ }
32
+ function lineAt(content, offset) {
33
+ return content.slice(0, offset).split("\n").length;
34
+ }
35
+ function parseError(tex, file, line) {
36
+ try {
37
+ katex.renderToString(tex, { throwOnError: true, strict: "ignore" });
38
+ return null;
39
+ }
40
+ catch (error) {
41
+ const detail = error instanceof Error ? error.message : String(error);
42
+ return {
43
+ file,
44
+ line,
45
+ severity: "error",
46
+ message: `Invalid LaTeX math: ${detail}`,
47
+ suggestion: "Fix the KaTeX syntax or replace/define the unsupported command in this math expression.",
48
+ };
49
+ }
50
+ }
51
+ /** Validate math exactly as isolated KaTeX expressions, matching Lens rendering. */
52
+ export function validateMath(content, file) {
53
+ const source = maskNonMathMarkdown(content);
54
+ const errors = [];
55
+ const withoutDisplay = source.split("");
56
+ const displayRe = /\$\$([\s\S]*?)\$\$/g;
57
+ for (const match of source.matchAll(displayRe)) {
58
+ const offset = match.index ?? 0;
59
+ const error = parseError(match[1], file, lineAt(source, offset));
60
+ if (error)
61
+ errors.push(error);
62
+ for (let index = offset; index < offset + match[0].length; index += 1) {
63
+ if (withoutDisplay[index] !== "\n")
64
+ withoutDisplay[index] = " ";
65
+ }
66
+ }
67
+ const inlineSource = withoutDisplay.join("");
68
+ const unclosedDisplay = inlineSource.indexOf("$$");
69
+ if (unclosedDisplay !== -1) {
70
+ errors.push({
71
+ file,
72
+ line: lineAt(inlineSource, unclosedDisplay),
73
+ severity: "error",
74
+ message: "Invalid LaTeX math: unclosed $$ display-math delimiter.",
75
+ suggestion: "Add the closing $$ delimiter.",
76
+ });
77
+ }
78
+ for (const match of inlineSource.matchAll(INLINE_MATH_RE)) {
79
+ const offset = match.index ?? 0;
80
+ const error = parseError(match[1], file, lineAt(inlineSource, offset));
81
+ if (error)
82
+ errors.push(error);
83
+ }
84
+ return errors;
85
+ }
86
+ //# sourceMappingURL=math.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"math.js","sourceRoot":"","sources":["../../src/validator/math.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lens-content-processor",
3
- "version": "0.26.0",
3
+ "version": "0.28.0",
4
4
  "description": "Parser and validator for Lens educational content (Markdown modules, lenses, learning outcomes)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -40,6 +40,7 @@
40
40
  "vitest": "^3.0.0"
41
41
  },
42
42
  "dependencies": {
43
+ "katex": "^0.16.47",
43
44
  "yaml": "^2.8.2"
44
45
  }
45
46
  }