-
Notifications
You must be signed in to change notification settings - Fork 0
/
parser.js
102 lines (86 loc) · 3.57 KB
/
parser.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import { unified } from 'unified'
import remarkParse from 'remark-parse'
import remarkRehype from 'remark-rehype'
import remarkDirective from 'remark-directive'
import remarkDirectiveRehype from 'remark-directive-rehype'
import rehypeStringify from 'rehype-stringify'
//import rehypeMathjax from 'rehype-mathjax' -> breaks svelte if imported?
import remarkMath from 'remark-math'
import remarkGfm from 'remark-gfm'
import { visit } from 'unist-util-visit'
import { is } from 'unist-util-is'
// TODO extract to custom file with typings
// Remove any
function directive() {
return (tree , file) => {
// Adds a ID to the heading based on the format: # test heading {#id}
// TODO add typing
visit(tree, "heading", (node) => {
if (node.children.length === 1 && is(node.children[0], "text")) {
const textNode = node.children[0];
const matches = textNode.value.match("\{#(.*)\}");
if (matches != null && matches.length === 2) {
const id = matches[1];
const data = node.data || (node.data = {})
data.hProperties = { id: id }
textNode.value = textNode.value.substring(0, textNode.value.length - matches[0].length);
}
}
})
visit(tree, 'textDirective', (node) => {
if (node.name == 'author') {
const data = node.data || (node.data = {})
data.hName = 'p'
data.hProperties = {className: ['author']}
}
if (node.name == 'theorem') {
const data = node.data || (node.data = {})
data.hName = 'div'
data.hProperties = {className: ['theorem']}
}
if (node.name == 'lemma') {
const data = node.data || (node.data = {})
data.hName = 'div'
data.hProperties = {className: ['lemma']}
}
});
visit(tree, 'containerDirective', (node) => {
if (node.name == 'abstract') {
const data = node.data || (node.data = {})
data.hName = 'div'
data.hProperties = {className: ['abstract']}
}
if (node.name == 'theorem') {
const data = node.data || (node.data = {})
data.hName = 'div'
data.hProperties = {className: ['theorem']}
}
if (node.name == 'proof') {
// TODO TOC Should be auto generated
const data = node.data || (node.data = {})
data.hName = 'div'
data.hProperties = {className: ['proof']}
}
if (node.name == 'toc') {
// TODO TOC Should be auto generated
const data = node.data || (node.data = {})
data.hName = 'nav'
data.hProperties = {role: ["navigation"], className: ['toc']}
}
})
}
}
export async function convertMarkdownToHtml(value) {
const file = await unified()
.use(remarkParse) // Convert to Markdown AST
.use(remarkMath) // Support markdown math symbols
.use(remarkGfm) // Support Github Flavoured Markdown
.use(remarkDirective) // Support Markdown directives
.use(remarkDirectiveRehype) // Support directives in HTML
.use(directive) // Custom logic
.use(remarkRehype) // Convert to HTML AST
// .use(rehypeMathjax) // Convert span math to mathjax -> does not currently work. Breaks svelte?
.use(rehypeStringify) // To HTML string -> check XSS
.process(value)
return String(file)
}