@peaceroad/markdown-it-renderer-fence 0.4.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/README.md +440 -112
- package/THIRD_PARTY_NOTICES.md +56 -0
- package/index.js +33 -479
- package/package.json +29 -3
- package/src/custom-highlight/option-validator.js +152 -0
- package/src/custom-highlight/payload-utils.js +43 -0
- package/src/custom-highlight/runtime-utils.js +83 -0
- package/src/custom-highlight/shiki-keyword-rules.js +407 -0
- package/src/custom-highlight/shiki-keyword.js +417 -0
- package/src/entry/custom-highlight-runtime.js +11 -0
- package/src/entry/custom-highlight.js +25 -0
- package/src/entry/markup-highlight.js +40 -0
- package/src/fence/render-api-constants.js +34 -0
- package/src/fence/render-api-provider.js +810 -0
- package/src/fence/render-api-renderer.js +136 -0
- package/src/fence/render-api-runtime.js +712 -0
- package/src/fence/render-api.js +117 -0
- package/src/fence/render-markup.js +161 -0
- package/src/fence/render-shared.js +428 -0
- package/src/utils/attr-utils.js +120 -0
- package/src/utils/pre-code-wrapper-parser.js +114 -0
package/index.js
CHANGED
|
@@ -1,485 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
let next = addition.trim()
|
|
19
|
-
if (!next) return style
|
|
20
|
-
if (!next.endsWith(';')) next += ';'
|
|
21
|
-
if (!style) return next
|
|
22
|
-
const base = style.trimEnd()
|
|
23
|
-
const separator = base.endsWith(';') ? ' ' : '; '
|
|
24
|
-
return base + separator + next
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const parseHtmlAttrs = (attrText) => {
|
|
28
|
-
const attrs = []
|
|
29
|
-
if (!attrText) return attrs
|
|
30
|
-
htmlAttrReg.lastIndex = 0
|
|
31
|
-
let match
|
|
32
|
-
while ((match = htmlAttrReg.exec(attrText)) !== null) {
|
|
33
|
-
const name = match[1]
|
|
34
|
-
const val = match[2] ?? match[3] ?? match[4] ?? ''
|
|
35
|
-
attrs.push([name, val])
|
|
36
|
-
}
|
|
37
|
-
return attrs
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const mergeAttrSets = (target, source) => {
|
|
41
|
-
if (!source || source.length === 0) return
|
|
42
|
-
const index = new Map()
|
|
43
|
-
for (let i = 0; i < target.length; i++) index.set(target[i][0], i)
|
|
44
|
-
for (const [name, val] of source) {
|
|
45
|
-
const idx = index.get(name)
|
|
46
|
-
if (name === 'class') {
|
|
47
|
-
if (idx === undefined) {
|
|
48
|
-
target.push([name, val])
|
|
49
|
-
index.set(name, target.length - 1)
|
|
50
|
-
} else if (val) {
|
|
51
|
-
const existing = target[idx][1]
|
|
52
|
-
target[idx][1] = existing ? existing + ' ' + val : val
|
|
53
|
-
}
|
|
54
|
-
continue
|
|
55
|
-
}
|
|
56
|
-
if (name === 'style') {
|
|
57
|
-
if (idx === undefined) {
|
|
58
|
-
target.push([name, val])
|
|
59
|
-
index.set(name, target.length - 1)
|
|
60
|
-
} else {
|
|
61
|
-
target[idx][1] = appendStyleValue(target[idx][1], val)
|
|
62
|
-
}
|
|
63
|
-
continue
|
|
64
|
-
}
|
|
65
|
-
if (idx === undefined) {
|
|
66
|
-
target.push([name, val])
|
|
67
|
-
index.set(name, target.length - 1)
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const getEmphasizeLines = (attrVal) => {
|
|
73
|
-
const lines = []
|
|
74
|
-
for (const range of attrVal.split(',')) {
|
|
75
|
-
const part = range.trim()
|
|
76
|
-
if (!part) continue
|
|
77
|
-
const dash = part.indexOf('-')
|
|
78
|
-
if (dash > -1) {
|
|
79
|
-
const left = part.slice(0, dash).trim()
|
|
80
|
-
const right = part.slice(dash + 1).trim()
|
|
81
|
-
const s = left ? parseInt(left, 10) : null
|
|
82
|
-
const e = right ? parseInt(right, 10) : null
|
|
83
|
-
if (s !== null && (!Number.isFinite(s) || s <= 0)) continue
|
|
84
|
-
if (e !== null && (!Number.isFinite(e) || e <= 0)) continue
|
|
85
|
-
if (s === null && e === null) {
|
|
86
|
-
lines.push([null, null])
|
|
87
|
-
} else {
|
|
88
|
-
lines.push([s, e])
|
|
89
|
-
}
|
|
90
|
-
} else {
|
|
91
|
-
const s = parseInt(part, 10)
|
|
92
|
-
if (!Number.isFinite(s) || s <= 0) continue
|
|
93
|
-
lines.push([s, s])
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return lines
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const splitFenceBlockToLines = (content, emphasizeLines, needLineNumber, needEmphasis, needEndSpan, threshold, lineEndSpanClass, br, commentLines, commentClass) => {
|
|
100
|
-
const lines = content.split(br)
|
|
101
|
-
const len = lines.length
|
|
102
|
-
const endSpanTag = needEndSpan ? `<span class="${lineEndSpanClass}"></span>` : ''
|
|
103
|
-
const needComment = !!(commentLines && commentClass)
|
|
104
|
-
const maxLine = len - (lines[len - 1] === '' ? 1 : 0)
|
|
105
|
-
let emIdx = 0
|
|
106
|
-
let emStart
|
|
107
|
-
let emEnd
|
|
108
|
-
let doEmphasis = false
|
|
109
|
-
if (needEmphasis && maxLine > 0) {
|
|
110
|
-
const normalized = []
|
|
111
|
-
for (const range of emphasizeLines) {
|
|
112
|
-
let [s, e] = range
|
|
113
|
-
if (s == null) s = 1
|
|
114
|
-
if (e == null) e = maxLine
|
|
115
|
-
if (!Number.isFinite(s) || !Number.isFinite(e) || s <= 0 || e <= 0) continue
|
|
116
|
-
if (s > e) {
|
|
117
|
-
const tmp = s
|
|
118
|
-
s = e
|
|
119
|
-
e = tmp
|
|
120
|
-
}
|
|
121
|
-
if (s > maxLine || e < 1) continue
|
|
122
|
-
if (e > maxLine) e = maxLine
|
|
123
|
-
normalized.push([s, e])
|
|
124
|
-
}
|
|
125
|
-
if (normalized.length > 0) {
|
|
126
|
-
doEmphasis = true
|
|
127
|
-
emphasizeLines = normalized
|
|
128
|
-
;[emStart, emEnd] = emphasizeLines[0]
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
for (let n = 0; n < len; n++) {
|
|
132
|
-
let line = lines[n]
|
|
133
|
-
|
|
134
|
-
if (needEndSpan) {
|
|
135
|
-
let lineLen = line.length
|
|
136
|
-
if (lineLen < threshold) {
|
|
137
|
-
lineLen = 0
|
|
138
|
-
for (let i = 0, L = line.length; i < L; i++) {
|
|
139
|
-
lineLen += line.charCodeAt(i) > 255 ? 2 : 1
|
|
140
|
-
if (lineLen >= threshold) break
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
if (lineLen >= threshold) {
|
|
144
|
-
if (line.slice(-closeTagLen) === closeTag) {
|
|
145
|
-
line = line.slice(0, -closeTagLen) + endSpanTag + closeTag
|
|
146
|
-
} else {
|
|
147
|
-
line = line + endSpanTag
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if (needLineNumber && n !== len - 1) {
|
|
153
|
-
if (line.indexOf('<') !== -1) {
|
|
154
|
-
const tagStack = []
|
|
155
|
-
tagReg.lastIndex = 0
|
|
156
|
-
let match
|
|
157
|
-
while ((match = tagReg.exec(line)) !== null) {
|
|
158
|
-
const [fullMatch, tagName] = match
|
|
159
|
-
const tagNameLower = tagName.toLowerCase()
|
|
160
|
-
if (fullMatch.startsWith('</')) {
|
|
161
|
-
if (tagStack[tagStack.length-1] === tagNameLower) tagStack.pop()
|
|
162
|
-
} else if (!fullMatch.endsWith('/>') && !voidTags.has(tagNameLower)) {
|
|
163
|
-
tagStack.push(tagNameLower)
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
for (let i = tagStack.length-1; i >= 0; i--) {
|
|
167
|
-
const tagName = tagStack[i]
|
|
168
|
-
line += `</${tagName}>`
|
|
169
|
-
lines[n+1] = `<${tagName}>` + (lines[n+1]||'')
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (needComment && commentLines[n]) {
|
|
175
|
-
line = `<span class="${commentClass}">` + line + closeTag
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (needLineNumber && n !== len - 1) {
|
|
179
|
-
line = preLineTag + line + closeTag
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
if (doEmphasis) {
|
|
183
|
-
if (emStart === n + 1) line = emphOpenTag + line
|
|
184
|
-
if (emEnd === n) {
|
|
185
|
-
line = closeTag + line
|
|
186
|
-
emIdx++
|
|
187
|
-
[emStart, emEnd] = emphasizeLines[emIdx] || []
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
lines[n] = line
|
|
191
|
-
}
|
|
192
|
-
return lines.join(br)
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
const getInfoAttr = (infoAttr) => {
|
|
196
|
-
let attrSets = infoAttr.trim().split(interAttrsSpaceReg)
|
|
197
|
-
let arr = []
|
|
198
|
-
for (let attrSet of attrSets) {
|
|
199
|
-
const str = attrReg.exec(attrSet)
|
|
200
|
-
if (str) {
|
|
201
|
-
if (str[1] === '.') str[1] = 'class'
|
|
202
|
-
if (str[1] === '#') str[1] = 'id'
|
|
203
|
-
if (str[3]) {
|
|
204
|
-
str[1] = str[3]
|
|
205
|
-
str[2] = str[5] ? str[5].replace(/^['"]/, '').replace(/['"]$/, '') : ''
|
|
206
|
-
}
|
|
207
|
-
arr.push([str[1], str[2]])
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
return arr
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const orderTokenAttrs = (token, opt) => {
|
|
214
|
-
if (!token.attrs) return
|
|
215
|
-
const order = opt.attrsOrder || []
|
|
216
|
-
token.attrs.sort((a, b) => {
|
|
217
|
-
const idx = (name) => {
|
|
218
|
-
for (let i = 0; i < order.length; i++) {
|
|
219
|
-
const key = order[i]
|
|
220
|
-
if (key.endsWith('*')) {
|
|
221
|
-
const prefix = key.slice(0, -1)
|
|
222
|
-
if (name.startsWith(prefix)) return i
|
|
223
|
-
} else if (name === key) {
|
|
224
|
-
return i
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
return order.length
|
|
228
|
-
}
|
|
229
|
-
return idx(a[0]) - idx(b[0])
|
|
230
|
-
})
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
const getFenceHtml = (tokens, idx, md, opt, slf) => {
|
|
234
|
-
const token = tokens[idx]
|
|
235
|
-
let content = token.content
|
|
236
|
-
const info = token.info.trim()
|
|
237
|
-
const match = info.match(infoReg)
|
|
238
|
-
let lang = match ? match[1] : ''
|
|
239
|
-
|
|
240
|
-
if (match && match[2]) {
|
|
241
|
-
getInfoAttr(match[2]).forEach(([name, val]) => token.attrJoin(name, val))
|
|
242
|
-
}
|
|
243
|
-
let langClass = ''
|
|
244
|
-
if (lang && lang !== 'samp') {
|
|
245
|
-
langClass = opt.langPrefix + lang
|
|
246
|
-
const existingClass = token.attrGet('class')
|
|
247
|
-
token.attrSet('class', existingClass ? langClass + ' ' + existingClass : langClass)
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
let startNumber = -1
|
|
251
|
-
let emphasizeLines = []
|
|
252
|
-
let wrapEnabled = false
|
|
253
|
-
let preWrapValue
|
|
254
|
-
let commentLineValue
|
|
255
|
-
|
|
256
|
-
if (token.attrs) {
|
|
257
|
-
const newAttrs = []
|
|
258
|
-
let dataPreStartIndex = -1
|
|
259
|
-
let dataPreEmphasisIndex = -1
|
|
260
|
-
let styleIndex = -1
|
|
261
|
-
let dataPreCommentIndex = -1
|
|
262
|
-
let startValue
|
|
263
|
-
let emphasisValue
|
|
264
|
-
let styleValue
|
|
265
|
-
let sawCommentLine = false
|
|
266
|
-
let sawStartAttr = false
|
|
267
|
-
let sawEmphasisAttr = false
|
|
268
|
-
const appendOrder = []
|
|
269
|
-
|
|
270
|
-
for (const attr of token.attrs) {
|
|
271
|
-
const name = attr[0]
|
|
272
|
-
const val = attr[1]
|
|
273
|
-
|
|
274
|
-
switch (name) {
|
|
275
|
-
case 'class': {
|
|
276
|
-
if (val.indexOf(opt.langPrefix) !== -1) {
|
|
277
|
-
const hasClassLang = opt._langReg.exec(val)
|
|
278
|
-
if (hasClassLang) lang = hasClassLang[1]
|
|
279
|
-
}
|
|
280
|
-
newAttrs.push(attr)
|
|
281
|
-
break
|
|
282
|
-
}
|
|
283
|
-
case 'style':
|
|
284
|
-
styleIndex = newAttrs.length
|
|
285
|
-
styleValue = val
|
|
286
|
-
newAttrs.push(attr)
|
|
287
|
-
break
|
|
288
|
-
case 'data-pre-start':
|
|
289
|
-
startNumber = +val
|
|
290
|
-
startValue = val
|
|
291
|
-
dataPreStartIndex = newAttrs.length
|
|
292
|
-
newAttrs.push(attr)
|
|
293
|
-
break
|
|
294
|
-
case 'start':
|
|
295
|
-
case 'pre-start':
|
|
296
|
-
startNumber = +val
|
|
297
|
-
startValue = val
|
|
298
|
-
if (!sawStartAttr) {
|
|
299
|
-
appendOrder.push('start')
|
|
300
|
-
sawStartAttr = true
|
|
301
|
-
}
|
|
302
|
-
break
|
|
303
|
-
case 'data-pre-emphasis':
|
|
304
|
-
dataPreEmphasisIndex = newAttrs.length
|
|
305
|
-
newAttrs.push(attr)
|
|
306
|
-
break
|
|
307
|
-
case 'data-pre-comment-line':
|
|
308
|
-
dataPreCommentIndex = newAttrs.length
|
|
309
|
-
commentLineValue = val
|
|
310
|
-
newAttrs.push(attr)
|
|
311
|
-
break
|
|
312
|
-
case 'em-lines':
|
|
313
|
-
case 'emphasize-lines':
|
|
314
|
-
emphasizeLines = getEmphasizeLines(val)
|
|
315
|
-
emphasisValue = val
|
|
316
|
-
if (!sawEmphasisAttr) {
|
|
317
|
-
appendOrder.push('emphasis')
|
|
318
|
-
sawEmphasisAttr = true
|
|
319
|
-
}
|
|
320
|
-
break
|
|
321
|
-
case 'comment-line':
|
|
322
|
-
commentLineValue = val
|
|
323
|
-
if (!sawCommentLine) {
|
|
324
|
-
appendOrder.push('comment')
|
|
325
|
-
sawCommentLine = true
|
|
326
|
-
}
|
|
327
|
-
break
|
|
328
|
-
case 'data-pre-wrap':
|
|
329
|
-
preWrapValue = val
|
|
330
|
-
if (val === '' || val === 'true') wrapEnabled = true
|
|
331
|
-
break
|
|
332
|
-
case 'wrap':
|
|
333
|
-
case 'pre-wrap':
|
|
334
|
-
if (val === '' || val === 'true') {
|
|
335
|
-
wrapEnabled = true
|
|
336
|
-
}
|
|
337
|
-
break
|
|
338
|
-
default:
|
|
339
|
-
newAttrs.push(attr)
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
if (startValue !== undefined && dataPreStartIndex >= 0) {
|
|
344
|
-
newAttrs[dataPreStartIndex][1] = startValue
|
|
345
|
-
}
|
|
346
|
-
if (emphasisValue !== undefined && dataPreEmphasisIndex >= 0) {
|
|
347
|
-
newAttrs[dataPreEmphasisIndex][1] = emphasisValue
|
|
348
|
-
}
|
|
349
|
-
if (commentLineValue !== undefined && dataPreCommentIndex >= 0) {
|
|
350
|
-
newAttrs[dataPreCommentIndex][1] = commentLineValue
|
|
351
|
-
}
|
|
352
|
-
for (const kind of appendOrder) {
|
|
353
|
-
if (kind === 'start') {
|
|
354
|
-
if (dataPreStartIndex === -1 && startValue !== undefined) {
|
|
355
|
-
newAttrs.push(['data-pre-start', startValue])
|
|
356
|
-
}
|
|
357
|
-
} else if (kind === 'emphasis') {
|
|
358
|
-
if (dataPreEmphasisIndex === -1 && emphasisValue !== undefined) {
|
|
359
|
-
newAttrs.push(['data-pre-emphasis', emphasisValue])
|
|
360
|
-
}
|
|
361
|
-
} else if (kind === 'comment') {
|
|
362
|
-
if (dataPreCommentIndex === -1 && commentLineValue !== undefined) {
|
|
363
|
-
newAttrs.push(['data-pre-comment-line', commentLineValue])
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
if (startNumber !== -1) {
|
|
368
|
-
styleValue = appendStyleValue(styleValue, 'counter-set:pre-line-number ' + startNumber + ';')
|
|
369
|
-
}
|
|
370
|
-
if (styleIndex >= 0) {
|
|
371
|
-
if (styleValue !== undefined) newAttrs[styleIndex][1] = styleValue
|
|
372
|
-
} else if (styleValue) {
|
|
373
|
-
newAttrs.push(['style', styleValue])
|
|
374
|
-
}
|
|
375
|
-
if (wrapEnabled) preWrapValue = 'true'
|
|
376
|
-
token.attrs = newAttrs
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
const isSamp = opt._sampReg.test(lang)
|
|
380
|
-
let commentLines
|
|
381
|
-
let needComment = false
|
|
382
|
-
if (commentLineValue) {
|
|
383
|
-
const rawLines = token.content.split(/\r?\n/)
|
|
384
|
-
commentLines = new Array(rawLines.length)
|
|
385
|
-
for (let i = 0; i < rawLines.length; i++) {
|
|
386
|
-
const isComment = rawLines[i].trimStart().startsWith(commentLineValue)
|
|
387
|
-
commentLines[i] = isComment
|
|
388
|
-
if (isComment) needComment = true
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
if (opt.setHighlight && md.options.highlight) {
|
|
393
|
-
if (lang && lang !== 'samp' ) {
|
|
394
|
-
content = md.options.highlight(content, lang)
|
|
395
|
-
} else {
|
|
396
|
-
content = md.utils.escapeHtml(token.content)
|
|
397
|
-
}
|
|
398
|
-
} else {
|
|
399
|
-
content = md.utils.escapeHtml(token.content)
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
let preAttrsFromHighlight
|
|
403
|
-
let hasHighlightPre = false
|
|
404
|
-
const hasPreTag = (content.indexOf('<pre') !== -1 || content.indexOf('<PRE') !== -1)
|
|
405
|
-
if (hasPreTag) {
|
|
406
|
-
const preMatch = content.match(preCodeWrapperReg)
|
|
407
|
-
if (preMatch) {
|
|
408
|
-
hasHighlightPre = true
|
|
409
|
-
preAttrsFromHighlight = parseHtmlAttrs(preMatch[1])
|
|
410
|
-
const codeAttrsFromHighlight = parseHtmlAttrs(preMatch[2])
|
|
411
|
-
content = preMatch[3]
|
|
412
|
-
if (codeAttrsFromHighlight.length) {
|
|
413
|
-
if (!token.attrs) token.attrs = []
|
|
414
|
-
mergeAttrSets(token.attrs, codeAttrsFromHighlight)
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
if (opt.useHighlightPre && hasPreTag && !hasHighlightPre) {
|
|
419
|
-
return content.endsWith('\n') ? content : content + '\n'
|
|
420
|
-
}
|
|
421
|
-
orderTokenAttrs(token, opt)
|
|
422
|
-
|
|
423
|
-
let preAttrs = preAttrsFromHighlight ? preAttrsFromHighlight.slice() : []
|
|
424
|
-
if (preWrapValue !== undefined) {
|
|
425
|
-
const idx = preAttrs.findIndex(attr => attr[0] === 'data-pre-wrap')
|
|
426
|
-
if (idx === -1) {
|
|
427
|
-
preAttrs.push(['data-pre-wrap', preWrapValue])
|
|
428
|
-
} else {
|
|
429
|
-
preAttrs[idx][1] = preWrapValue
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
if (wrapEnabled && opt.setPreWrapStyle !== false) {
|
|
433
|
-
const idx = preAttrs.findIndex(attr => attr[0] === 'style')
|
|
434
|
-
if (idx === -1) {
|
|
435
|
-
preAttrs.push(['style', preWrapStyle])
|
|
436
|
-
} else {
|
|
437
|
-
preAttrs[idx][1] = appendStyleValue(preAttrs[idx][1], preWrapStyle)
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
if (preAttrs.length) orderTokenAttrs({ attrs: preAttrs }, opt)
|
|
441
|
-
const preAttrsText = preAttrs.length ? slf.renderAttrs({ attrs: preAttrs }) : ''
|
|
442
|
-
|
|
443
|
-
const needLineNumber = opt.setLineNumber && startNumber >= 0
|
|
444
|
-
const needEmphasis = opt.setEmphasizeLines && emphasizeLines.length > 0
|
|
445
|
-
const needEndSpan = opt.lineEndSpanThreshold > 0
|
|
446
|
-
const useHighlightPre = opt.useHighlightPre && hasHighlightPre
|
|
447
|
-
if (!useHighlightPre && (needLineNumber || needEmphasis || needEndSpan || needComment)) {
|
|
448
|
-
const nlIndex = content.indexOf('\n')
|
|
449
|
-
const br = nlIndex > 0 && content[nlIndex - 1] === '\r' ? '\r\n' : '\n'
|
|
450
|
-
content = splitFenceBlockToLines(content, emphasizeLines, needLineNumber, needEmphasis, needEndSpan, opt.lineEndSpanThreshold, opt.lineEndSpanClass, br, commentLines, commentLineClass)
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
const tag = isSamp ? 'samp' : 'code'
|
|
454
|
-
return `<pre${preAttrsText}><${tag}${slf.renderAttrs(token)}>${content}</${tag}></pre>\n`
|
|
1
|
+
import mditRendererFenceMarkup from './src/entry/markup-highlight.js'
|
|
2
|
+
import mditRendererFenceCustomHighlight, {
|
|
3
|
+
applyCustomHighlights,
|
|
4
|
+
clearCustomHighlights,
|
|
5
|
+
customHighlightPayloadSchemaVersion,
|
|
6
|
+
customHighlightPayloadSupportedVersions,
|
|
7
|
+
getCustomHighlightPayloadMap,
|
|
8
|
+
observeCustomHighlights,
|
|
9
|
+
renderCustomHighlightPayloadScript,
|
|
10
|
+
renderCustomHighlightScopeStyleTag,
|
|
11
|
+
shouldRuntimeFallback,
|
|
12
|
+
} from './src/entry/custom-highlight.js'
|
|
13
|
+
|
|
14
|
+
const normalizeHighlightRenderer = (value) => {
|
|
15
|
+
const key = String(value || '').trim().toLowerCase()
|
|
16
|
+
if (key === 'api' || key === 'custom-highlight-api') return 'api'
|
|
17
|
+
return 'markup'
|
|
455
18
|
}
|
|
456
19
|
|
|
457
20
|
const mditRendererFence = (md, option) => {
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
opt._sampReg = new RegExp('^(?:samp|' + opt.sampLang.split(',').join('|') + ')$')
|
|
478
|
-
opt._langReg = new RegExp(opt.langPrefix + '([A-Za-z0-9-]+)')
|
|
479
|
-
|
|
480
|
-
md.renderer.rules['fence'] = (tokens, idx, options, env, slf) => {
|
|
481
|
-
return getFenceHtml(tokens, idx, md, opt, slf)
|
|
482
|
-
}
|
|
21
|
+
if (normalizeHighlightRenderer(option && option.highlightRenderer) === 'api') {
|
|
22
|
+
return mditRendererFenceCustomHighlight(md, option)
|
|
23
|
+
}
|
|
24
|
+
return mditRendererFenceMarkup(md, option)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export {
|
|
28
|
+
applyCustomHighlights,
|
|
29
|
+
clearCustomHighlights,
|
|
30
|
+
customHighlightPayloadSchemaVersion,
|
|
31
|
+
customHighlightPayloadSupportedVersions,
|
|
32
|
+
getCustomHighlightPayloadMap,
|
|
33
|
+
observeCustomHighlights,
|
|
34
|
+
renderCustomHighlightPayloadScript,
|
|
35
|
+
renderCustomHighlightScopeStyleTag,
|
|
36
|
+
shouldRuntimeFallback,
|
|
483
37
|
}
|
|
484
38
|
|
|
485
39
|
export default mditRendererFence
|
package/package.json
CHANGED
|
@@ -1,22 +1,48 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peaceroad/markdown-it-renderer-fence",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "In code blocks, the `<samp>` tag is used with the language keywords `samp`, `shell`, and `console`, and provides an option to display line numbers.",
|
|
5
5
|
"main": "index.js",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./index.js",
|
|
8
|
+
"./custom-highlight": "./src/entry/custom-highlight.js",
|
|
9
|
+
"./custom-highlight-runtime": "./src/entry/custom-highlight-runtime.js",
|
|
10
|
+
"./markup-highlight": "./src/entry/markup-highlight.js"
|
|
11
|
+
},
|
|
6
12
|
"files": [
|
|
7
13
|
"index.js",
|
|
14
|
+
"src",
|
|
8
15
|
"LICENSE",
|
|
16
|
+
"THIRD_PARTY_NOTICES.md",
|
|
9
17
|
"README.md"
|
|
10
18
|
],
|
|
11
19
|
"type": "module",
|
|
20
|
+
"customHighlightPayload": {
|
|
21
|
+
"schemaVersion": 1,
|
|
22
|
+
"supportedVersions": [
|
|
23
|
+
1
|
|
24
|
+
]
|
|
25
|
+
},
|
|
12
26
|
"scripts": {
|
|
13
|
-
"test": "node test/test.js"
|
|
27
|
+
"test": "node test/test.js && node test/custom-highlight/provider-contract.test.js && node test/custom-highlight/provider-keyword-coverage.test.js && node test/custom-highlight/provider-keyword-holdout-parity.test.js && node -e \"console.log('Passed all test.')\"",
|
|
28
|
+
"test:provider:contract": "node test/custom-highlight/provider-contract.test.js",
|
|
29
|
+
"test:provider:keyword": "node test/custom-highlight/provider-keyword-coverage.test.js",
|
|
30
|
+
"test:provider:keyword:holdout": "node test/custom-highlight/provider-keyword-holdout-parity.test.js",
|
|
31
|
+
"test:provider:keyword:mismatch": "node test/custom-highlight/provider-keyword-mismatch-report.js",
|
|
32
|
+
"test:provider:matrix": "node test/custom-highlight/provider-matrix-audit.js",
|
|
33
|
+
"build:demo:provider:keyword": "node test/custom-highlight/build-provider-keyword-demos.js",
|
|
34
|
+
"build:example:custom-highlight": "node example/build-custom-highlight-compare.js",
|
|
35
|
+
"test:performance": "node test/performance/benchmark.js",
|
|
36
|
+
"test:performance:highlighter": "node test/performance/highlighter-benchmark.js",
|
|
37
|
+
"test:performance:provider-modes": "node test/performance/provider-mode-benchmark.js",
|
|
38
|
+
"test:performance:runtime": "node test/performance/runtime-apply-benchmark.js",
|
|
39
|
+
"test:performance:keyword": "node test/performance/provider-mode-benchmark.js"
|
|
14
40
|
},
|
|
15
41
|
"author": "peaceroad <peaceroad@gmail.com>",
|
|
16
42
|
"repository": "https://github.com/peaceroad/p7d-markdown-it-renderer-fence",
|
|
17
43
|
"license": "MIT",
|
|
18
44
|
"devDependencies": {
|
|
19
|
-
"@peaceroad/markdown-it-figure-with-p-caption": "^0.
|
|
45
|
+
"@peaceroad/markdown-it-figure-with-p-caption": "^0.16.0",
|
|
20
46
|
"highlight.js": "^11.11.1",
|
|
21
47
|
"markdown-it": "^14.1.0",
|
|
22
48
|
"markdown-it-attrs": "^4.3.1",
|