@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.
@@ -0,0 +1,136 @@
1
+ import {
2
+ escapeJsonForScript,
3
+ } from '../custom-highlight/payload-utils.js'
4
+ import {
5
+ addTimingMs,
6
+ commentLineClass,
7
+ emitFenceDecision,
8
+ finalizeFenceTimings,
9
+ getNowMs,
10
+ orderTokenAttrs,
11
+ preWrapStyle,
12
+ splitFenceBlockToLines,
13
+ } from './render-shared.js'
14
+ import {
15
+ createApiPayloadForFence,
16
+ shouldApplyApiFallbackForReason,
17
+ } from './render-api-provider.js'
18
+ import {
19
+ customHighlightDataEnvKey,
20
+ customHighlightPreAttr,
21
+ customHighlightSeqEnvKey,
22
+ } from './render-api-constants.js'
23
+ import {
24
+ renderFenceMarkup,
25
+ } from './render-markup.js'
26
+
27
+ let fallbackCustomHighlightSeq = 0
28
+
29
+ const nextCustomHighlightId = (env, prefix) => {
30
+ if (env && typeof env === 'object') {
31
+ const n = Number.isSafeInteger(env[customHighlightSeqEnvKey]) ? env[customHighlightSeqEnvKey] + 1 : 1
32
+ env[customHighlightSeqEnvKey] = n
33
+ return `${prefix}${n}`
34
+ }
35
+ fallbackCustomHighlightSeq += 1
36
+ return `${prefix}${fallbackCustomHighlightSeq}`
37
+ }
38
+
39
+ const buildApiPreAttrs = (preWrapValue, wrapEnabled, opt) => {
40
+ const preAttrs = []
41
+ if (preWrapValue !== undefined) preAttrs.push(['data-pre-wrap', preWrapValue])
42
+ if (wrapEnabled && opt.setPreWrapStyle !== false) preAttrs.push(['style', preWrapStyle])
43
+ return preAttrs
44
+ }
45
+
46
+ const renderFenceApiOrPlain = (token, lang, md, opt, slf, env, startNumber, emphasizeLines, wrapEnabled, preWrapValue, commentMarkValue, includePayload, timings) => {
47
+ const isSamp = opt._sampReg.test(lang)
48
+ const tag = isSamp ? 'samp' : 'code'
49
+ let content = md.utils.escapeHtml(token.content)
50
+ const lineStrategy = opt.customHighlight.lineFeatureStrategy
51
+ const needLineNumber = lineStrategy === 'hybrid' && opt.setLineNumber && startNumber >= 0
52
+ const needEndSpan = lineStrategy === 'hybrid' && opt.lineEndSpanThreshold > 0
53
+ if (needLineNumber || needEndSpan) {
54
+ const splitStartedAt = timings ? getNowMs() : 0
55
+ const nlIndex = content.indexOf('\n')
56
+ const br = nlIndex > 0 && content[nlIndex - 1] === '\r' ? '\r\n' : '\n'
57
+ content = splitFenceBlockToLines(content, [], needLineNumber, false, needEndSpan, opt.lineEndSpanThreshold, opt.lineEndSpanClass, br, undefined, commentLineClass)
58
+ if (timings) addTimingMs(timings, 'lineSplitMs', getNowMs() - splitStartedAt)
59
+ }
60
+
61
+ orderTokenAttrs(token, opt)
62
+ const preAttrs = buildApiPreAttrs(preWrapValue, wrapEnabled, opt)
63
+ let inlinePayloadScript = ''
64
+
65
+ if (includePayload) {
66
+ const providerStartedAt = timings ? getNowMs() : 0
67
+ const payload = createApiPayloadForFence(token, lang, opt, md, env, emphasizeLines, commentMarkValue)
68
+ if (timings) addTimingMs(timings, 'providerMs', getNowMs() - providerStartedAt)
69
+ const id = nextCustomHighlightId(env, opt.customHighlight.idPrefix)
70
+ preAttrs.push([customHighlightPreAttr, id])
71
+
72
+ if (opt.customHighlight.transport === 'env' && env && typeof env === 'object') {
73
+ if (!env[customHighlightDataEnvKey] || typeof env[customHighlightDataEnvKey] !== 'object') env[customHighlightDataEnvKey] = {}
74
+ env[customHighlightDataEnvKey][id] = payload
75
+ } else {
76
+ const payloadJson = escapeJsonForScript(payload)
77
+ const scriptId = `pre-highlight-data-${id}`
78
+ inlinePayloadScript = `<script type="application/json" id="${scriptId}" ${customHighlightPreAttr}="${id}">${payloadJson}</script>\n`
79
+ }
80
+ }
81
+
82
+ if (preAttrs.length) orderTokenAttrs({ attrs: preAttrs }, opt)
83
+ const preAttrsText = preAttrs.length ? slf.renderAttrs({ attrs: preAttrs }) : ''
84
+ const html = `<pre${preAttrsText}><${tag}${slf.renderAttrs(token)}>${content}</${tag}></pre>\n`
85
+ return inlinePayloadScript ? html + inlinePayloadScript : html
86
+ }
87
+
88
+ const getFenceHtml = (context, md, opt, slf, env) => {
89
+ const token = context.token
90
+ const lang = context.lang
91
+ const timingEnabled = context.timingEnabled
92
+ const timings = context.timings
93
+ const fenceStartedAt = context.fenceStartedAt
94
+ const startNumber = context.startNumber
95
+ const emphasizeLines = context.emphasizeLines
96
+ const wrapEnabled = context.wrapEnabled
97
+ const preWrapValue = context.preWrapValue
98
+ const commentMarkValue = context.commentMarkValue
99
+
100
+ const apiDecisionBase = {
101
+ renderer: 'api',
102
+ includePayload: true,
103
+ fallbackUsed: false,
104
+ lineFeatureStrategy: opt.customHighlight.lineFeatureStrategy,
105
+ disabledFeatures: opt.customHighlight.lineFeatureStrategy === 'disable'
106
+ ? ['setLineNumber', 'lineEndSpanThreshold']
107
+ : [],
108
+ }
109
+ try {
110
+ const html = renderFenceApiOrPlain(token, lang, md, opt, slf, env, startNumber, emphasizeLines, wrapEnabled, preWrapValue, commentMarkValue, true, timings)
111
+ if (timingEnabled) apiDecisionBase.timings = finalizeFenceTimings(timings, fenceStartedAt)
112
+ emitFenceDecision(opt, apiDecisionBase)
113
+ return html
114
+ } catch (err) {
115
+ if (opt.customHighlight.fallback === 'plain' && shouldApplyApiFallbackForReason(opt.customHighlight, 'provider-error')) {
116
+ const fallbackDecision = {
117
+ renderer: 'api',
118
+ includePayload: false,
119
+ fallbackUsed: true,
120
+ fallback: 'plain',
121
+ reason: 'provider-error',
122
+ lineFeatureStrategy: opt.customHighlight.lineFeatureStrategy,
123
+ }
124
+ const html = renderFenceApiOrPlain(token, lang, md, opt, slf, env, startNumber, emphasizeLines, wrapEnabled, preWrapValue, commentMarkValue, false, timings)
125
+ if (timingEnabled) fallbackDecision.timings = finalizeFenceTimings(timings, fenceStartedAt)
126
+ emitFenceDecision(opt, fallbackDecision)
127
+ return html
128
+ }
129
+ }
130
+
131
+ return renderFenceMarkup(context, md, opt, slf)
132
+ }
133
+
134
+ export {
135
+ getFenceHtml,
136
+ }