-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmarkdoc.config.ts
162 lines (144 loc) · 4.86 KB
/
markdoc.config.ts
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import Markdoc, { type ConfigType, type RenderableTreeNode } from '@markdoc/markdoc'
import { getSingletonHighlighter } from 'shiki'
import { transformerNotationHighlight } from '@shikijs/transformers'
import grammar from './src/lib/markdoc.tmLanguage.json'
/*
* Markdoc configuration pass into velite
*/
const markdocConfig: ConfigType = {
nodes: {
heading: {
children: ['inline'],
attributes: {
id: { type: String },
level: { type: Number, required: true, default: 1 },
link: { type: Boolean, default: true }
},
transform(node, config) {
const attributes = node.transformAttributes(config)
const children = node.transformChildren(config)
const id = generateID(children, attributes)
return new Markdoc.Tag(`h${node.attributes['level']}`, { ...attributes, id }, [
...children,
attributes['link'] &&
new Markdoc.Tag('a', { href: `#${id}`, 'aria-hidden': '', tabIndex: '-1' }, ['#'])
])
}
},
paragraph: {
attributes: {
/* Attributes for Image */
image_caption: { type: Boolean },
image_title: { type: String },
image_isvideo: { type: Boolean }
},
transform(node, config) {
/* Unwrap image from paragraph, transform image nodes */
const img = node.children[0].children[0]
if (img.type === 'image') {
/* Merge atrributes */
img.attributes = { ...img.attributes, ...node.attributes }
/* If src isn't a link, make it Cld id */
if (!img.attributes.src.startsWith('http')) {
img.attributes.id = img.attributes.src
delete img.attributes.src
}
/* Caption, todo: seperate caption and alt text */
let showcap = false
if (img.attributes.image_caption) showcap = true
/* Video */
if (img.attributes.image_isvideo)
return new Markdoc.Tag(
'vid',
img.transformAttributes(config),
img.transformChildren(config)
)
return new Markdoc.Tag(
'img',
{ ...img.transformAttributes(config), showcap },
img.transformChildren(config)
)
}
return new Markdoc.Tag(
'p',
node.transformAttributes(config),
node.transformChildren(config)
)
}
},
/* Code Block */
fence: {
children: ['inline', 'text'],
attributes: {
content: { type: String, render: false },
language: { type: String },
process: { type: Boolean, render: false },
highlight: { type: Array }
},
async transform(node, config) {
const attributes = node.transformAttributes(config)
const children = node.transformChildren(config)
const markdoc = {
id: 'Markdoc',
scopeName: 'text.html.markdoc',
grammar,
aliases: ['markdoc']
}
const lang = attributes.language || 'text'
const code = (typeof children[0] === 'string' && children[0]) || node.attributes.content
const highlighter = await getSingletonHighlighter({
themes: [],
langs: [lang, markdoc]
})
const shikiCode = highlighter.codeToHtml(code, {
lang,
themes: {
light: await import('./src/lib/tmr.json'),
dark: await import('./src/lib/tmr-night.json')
},
transformers: [transformerNotationHighlight()]
})
return new Markdoc.Tag('CodeBlock', { ...attributes, code: shikiCode }, [])
}
}
},
tags: {
/* Definition List */
deflist: {
render: 'dl',
children: ['paragraph', 'list'],
transform(node, config) {
const children: RenderableTreeNode[] = []
for (const child of node.children) {
/* Term */
if (child.type === 'paragraph') {
children.push(new Markdoc.Tag('dt', {}, child.transformChildren(config)))
}
/* Definitions */
if (child.type === 'list') {
/* list > item > inline > [what we want] */
const defs = child.children.map((item) => item.transformChildren(config))
for (const dd of defs) {
children.push(new Markdoc.Tag('dd', {}, [...dd]))
}
}
}
return new Markdoc.Tag('dl', node.transformAttributes(config), children)
}
},
/* Content Accordion */
expand: { render: 'Expand' }
}
}
export default markdocConfig
function generateID(children: Array<RenderableTreeNode>, attributes: Record<string, unknown>) {
if (attributes.id && typeof attributes.id === 'string') {
return attributes.id
}
return children
.filter((child) => typeof child === 'string')
.join(' ')
.replace(/[?]/g, '')
.replace(/\s+/g, '-')
.toLowerCase()
}