markdown2typst 0.1.5 → 0.1.7
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/markdown2typst.browser.js +13716 -13727
- package/dist/markdown2typst.browser.js.map +4 -4
- package/dist/markdown2typst.browser.min.js +62 -61
- package/dist/markdown2typst.js +15357 -15371
- package/dist/markdown2typst.js.map +4 -4
- package/dist/markdown2typst.min.js +62 -61
- package/package.json +1 -1
- package/src/block-renderer.ts +1 -15
- package/src/parser.ts +3 -1
- package/src/remark-fix-math.ts +59 -0
package/package.json
CHANGED
package/src/block-renderer.ts
CHANGED
|
@@ -97,22 +97,8 @@ export function renderBlock(
|
|
|
97
97
|
* @returns Rendered Typst math block
|
|
98
98
|
*/
|
|
99
99
|
function renderMathBlock(node: MathNode, indentLevel: number, context: RenderContext): string {
|
|
100
|
-
// Reconstruct the full LaTeX string.
|
|
101
|
-
// If a LaTeX environment is adjacent to $$, remark-math treats the adjacent text as `meta`,
|
|
102
|
-
// and may absorb the trailing $$ into `value` if it's on the same line as the environment closure.
|
|
103
|
-
let rawLatex = node.value || '';
|
|
104
|
-
const meta = (node as any).meta;
|
|
105
|
-
if (meta) {
|
|
106
|
-
rawLatex = meta + (rawLatex ? '\n' + rawLatex : '');
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Check if the closing $$ was absorbed into the value
|
|
110
|
-
if (rawLatex.endsWith('$$')) {
|
|
111
|
-
rawLatex = rawLatex.slice(0, -2);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
100
|
// Convert LaTeX to Typst math syntax
|
|
115
|
-
const value =
|
|
101
|
+
const value = node.value.trim();
|
|
116
102
|
try {
|
|
117
103
|
const typstMath = tex2typst(value);
|
|
118
104
|
return indentLines(`$ ${typstMath} $`, indentLevel);
|
package/src/parser.ts
CHANGED
|
@@ -8,6 +8,7 @@ import remarkFrontmatter from 'remark-frontmatter';
|
|
|
8
8
|
import remarkGfm from 'remark-gfm';
|
|
9
9
|
import remarkMath from 'remark-math';
|
|
10
10
|
import remarkParse from 'remark-parse';
|
|
11
|
+
import { remarkFixAdjacentMath } from './remark-fix-math.js';
|
|
11
12
|
import type { Root } from 'mdast';
|
|
12
13
|
import type { ErrorCallback } from './types.js';
|
|
13
14
|
import { ErrorSeverity } from './types.js';
|
|
@@ -31,7 +32,8 @@ export function parseMarkdown(markdown: string, onError?: ErrorCallback): Root {
|
|
|
31
32
|
.use(remarkParse)
|
|
32
33
|
.use(remarkFrontmatter, ['yaml'])
|
|
33
34
|
.use(remarkGfm, { singleTilde: false })
|
|
34
|
-
.use(remarkMath)
|
|
35
|
+
.use(remarkMath)
|
|
36
|
+
.use(remarkFixAdjacentMath);
|
|
35
37
|
|
|
36
38
|
const parsedTree = processor.parse(markdown);
|
|
37
39
|
const tree = processor.runSync(parsedTree) as Root;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { visit } from 'unist-util-visit';
|
|
2
|
+
import { unified } from 'unified';
|
|
3
|
+
import remarkParse from 'remark-parse';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Remark plugin to fix math blocks that swallowed adjacent text because
|
|
7
|
+
* of a missing newline before the closing $$.
|
|
8
|
+
*/
|
|
9
|
+
export function remarkFixAdjacentMath() {
|
|
10
|
+
return (tree: any) => {
|
|
11
|
+
// First pass: fix the nodes and store the extracted nodes
|
|
12
|
+
visit(tree, 'math', (node: any) => {
|
|
13
|
+
let value = node.value || '';
|
|
14
|
+
const meta = node.meta;
|
|
15
|
+
|
|
16
|
+
// Reconstruct the full string because remark-math treats adjacent text as meta
|
|
17
|
+
if (meta) {
|
|
18
|
+
value = meta + (value ? '\n' + value : '');
|
|
19
|
+
node.meta = null; // Clear meta since it was actually part of the math
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Look for the first occurrence of $$ in the value
|
|
23
|
+
const match = value.match(/\$\$/);
|
|
24
|
+
|
|
25
|
+
if (match) {
|
|
26
|
+
// Found a stray $$ inside the math block!
|
|
27
|
+
// This means the math block swallowed the closing delimiter and everything after it.
|
|
28
|
+
|
|
29
|
+
const splitIndex = match.index;
|
|
30
|
+
const mathContent = value.substring(0, splitIndex);
|
|
31
|
+
const remainder = value.substring(splitIndex + 2); // skip $$
|
|
32
|
+
|
|
33
|
+
// Fix the math node
|
|
34
|
+
node.value = mathContent.trim();
|
|
35
|
+
|
|
36
|
+
// We need to append the remainder as new parsed markdown nodes after this node
|
|
37
|
+
if (remainder.trim().length > 0) {
|
|
38
|
+
// Parse the remainder
|
|
39
|
+
const processor = unified().use(remarkParse);
|
|
40
|
+
const remainderAst = processor.parse(remainder.trim());
|
|
41
|
+
|
|
42
|
+
// Store the nodes to be inserted
|
|
43
|
+
node.data = node.data || {};
|
|
44
|
+
node.data.insertAfter = remainderAst.children;
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
node.value = value.trim();
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Second pass: insert the extracted nodes
|
|
52
|
+
visit(tree, (node: any, index: number | undefined, parent: any) => {
|
|
53
|
+
if (node.data && node.data.insertAfter && parent && index !== undefined) {
|
|
54
|
+
parent.children.splice(index + 1, 0, ...node.data.insertAfter);
|
|
55
|
+
delete node.data.insertAfter;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
}
|