@peaceroad/markdown-it-renderer-fence 0.2.0 → 0.3.1

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 CHANGED
@@ -17,15 +17,15 @@ import mditRendererFence from '@peaceroad/markdown-it-renderer-fence'
17
17
  const md = mdit({
18
18
  langPrefix: 'language-',
19
19
  highlight: (str, lang) => {
20
- if (lang && highlightjs.getLanguage(lang)) {
21
- try {
22
- return highlightjs.highlight(str, { language: lang }).value
23
- } catch (__) {}
20
+ if (lang && highlightjs.getLanguage(lang)) {
21
+ try {
22
+ return highlightjs.highlight(str, { language: lang }).value
23
+ } catch (__) {}
24
+ }
25
+ return md.utils.escapeHtml(str)
24
26
  }
25
- return str
26
27
  }).use(mditAttrs).use(mditRendererFence)
27
28
 
28
-
29
29
  const htmlCont = md.render('...')
30
30
  ```
31
31
 
@@ -92,6 +92,7 @@ CSS example: <https://codepen.io/peaceroad/pen/qBGpYGK>
92
92
  ## Add span elements to add background color to the row ranges.
93
93
 
94
94
  Add `em-lines` or `emphasize-lines` attribute by by adding attributes used markdown-it-attrs.
95
+ Open-ended ranges are supported: `-5` (1..5), `3-` (3..last), `-` (all).
95
96
 
96
97
  ~~~md
97
98
  ``` {em-lines="2,4-5"}
@@ -115,6 +116,23 @@ Add `em-lines` or `emphasize-lines` attribute by by adding attributes used markd
115
116
  </code></pre>
116
117
  ~~~
117
118
 
119
+ ## Enable pre-wrap for code blocks
120
+
121
+ Add `wrap` or `pre-wrap` attribute (optionally `="true"`) by adding attributes used markdown-it-attrs.
122
+
123
+ ~~~md
124
+ ```js {wrap}
125
+ const longLine = 'This line is long but wraps.'
126
+ ```
127
+ ~~~
128
+
129
+ ~~~html
130
+ <pre data-pre-wrap="true" style="white-space: pre-wrap; overflow-wrap: anywhere;"><code class="language-js">const longLine = 'This line is long but wraps.'
131
+ </code></pre>
132
+ ~~~
133
+
134
+ When `setPreWrapStyle` is set to false, only `data-pre-wrap="true"` is added and the inline style is omitted.
135
+
118
136
 
119
137
  ## Options
120
138
 
@@ -126,5 +144,6 @@ The following options can be specified when initializing the plugin:
126
144
  - setEmphasizeLines: default true — enable emphasis based on emphasize-lines attribute.
127
145
  - setLineEndSpan: default 0 — character count threshold to append end-of-line span (0 to disable).
128
146
  - lineEndSpanClass: default 'pre-lineend-spacer' — CSS class for end-of-line span.
147
+ - setPreWrapStyle: default true — include inline pre-wrap styles on `<pre>` when wrap is enabled.
129
148
  - sampLang: default 'shell,console' — comma-separated list of languages (in addition to 'samp') that will be rendered using `<samp>`.
130
149
  - langPrefix: default md.options.langPrefix || 'language-' — prefix for language class on code blocks.
package/index.js CHANGED
@@ -1,7 +1,4 @@
1
1
  const infoReg = /^([^{\s]*)(?:\s*\{(.*)\})?$/
2
- const startReg = /^(?:(?:data-)?pre-)?start$/
3
- const startFilterReg = /^(?:pre-)?start$/
4
- const emphasisReg = /^em(?:phasize)?-lines$/
5
2
 
6
3
  const attrReg = /^(?:([.#])(.+)|(.+?)(?:=(["'])?(.*?)\1)?)$/
7
4
  const interAttrsSpaceReg = / +/
@@ -10,35 +7,136 @@ const preLineTag = '<span class="pre-line">'
10
7
  const emphOpenTag = '<span class="pre-lines-emphasis">'
11
8
  const closeTag = '</span>'
12
9
  const closeTagLen = closeTag.length
10
+ const preWrapStyle = 'white-space: pre-wrap; overflow-wrap: anywhere;'
11
+ const preCodeWrapperReg = /^\s*<pre\b([^>]*)>\s*<code\b([^>]*)>([\s\S]*?)<\/code>\s*<\/pre>\s*$/i
12
+ const htmlAttrReg = /([^\s=]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g
13
+ const voidTags = new Set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr'])
14
+
15
+ const appendStyleValue = (style, addition) => {
16
+ if (!addition) return style
17
+ let next = addition.trim()
18
+ if (!next) return style
19
+ if (!next.endsWith(';')) next += ';'
20
+ if (!style) return next
21
+ const base = style.trimEnd()
22
+ const separator = base.endsWith(';') ? ' ' : '; '
23
+ return base + separator + next
24
+ }
25
+
26
+ const parseHtmlAttrs = (attrText) => {
27
+ const attrs = []
28
+ if (!attrText) return attrs
29
+ htmlAttrReg.lastIndex = 0
30
+ let match
31
+ while ((match = htmlAttrReg.exec(attrText)) !== null) {
32
+ const name = match[1]
33
+ const val = match[2] ?? match[3] ?? match[4] ?? ''
34
+ attrs.push([name, val])
35
+ }
36
+ return attrs
37
+ }
38
+
39
+ const mergeAttrSets = (target, source) => {
40
+ if (!source || source.length === 0) return
41
+ const index = new Map()
42
+ for (let i = 0; i < target.length; i++) index.set(target[i][0], i)
43
+ for (const [name, val] of source) {
44
+ const idx = index.get(name)
45
+ if (name === 'class') {
46
+ if (idx === undefined) {
47
+ target.push([name, val])
48
+ index.set(name, target.length - 1)
49
+ } else if (val) {
50
+ const existing = target[idx][1]
51
+ target[idx][1] = existing ? existing + ' ' + val : val
52
+ }
53
+ continue
54
+ }
55
+ if (name === 'style') {
56
+ if (idx === undefined) {
57
+ target.push([name, val])
58
+ index.set(name, target.length - 1)
59
+ } else {
60
+ target[idx][1] = appendStyleValue(target[idx][1], val)
61
+ }
62
+ continue
63
+ }
64
+ if (idx === undefined) {
65
+ target.push([name, val])
66
+ index.set(name, target.length - 1)
67
+ }
68
+ }
69
+ }
13
70
 
14
71
  const getEmphasizeLines = (attrVal) => {
15
72
  const lines = []
16
- let s, e
17
- attrVal.split(',').forEach(range => {
18
- if (range.indexOf('-') > -1) {
19
- [s, e] = range.split('-').map(n => parseInt(n.trim(), 10))
20
- lines.push([s, e])
73
+ for (const range of attrVal.split(',')) {
74
+ const part = range.trim()
75
+ if (!part) continue
76
+ const dash = part.indexOf('-')
77
+ if (dash > -1) {
78
+ const left = part.slice(0, dash).trim()
79
+ const right = part.slice(dash + 1).trim()
80
+ const s = left ? parseInt(left, 10) : null
81
+ const e = right ? parseInt(right, 10) : null
82
+ if (s !== null && (!Number.isFinite(s) || s <= 0)) continue
83
+ if (e !== null && (!Number.isFinite(e) || e <= 0)) continue
84
+ if (s === null && e === null) {
85
+ lines.push([null, null])
86
+ } else {
87
+ lines.push([s, e])
88
+ }
21
89
  } else {
22
- s = parseInt(range.trim(), 10)
90
+ const s = parseInt(part, 10)
91
+ if (!Number.isFinite(s) || s <= 0) continue
23
92
  lines.push([s, s])
24
93
  }
25
- })
94
+ }
26
95
  return lines
27
96
  }
28
97
 
29
98
  const splitFenceBlockToLines = (content, emphasizeLines, needLineNumber, needEmphasis, needEndSpan, threshold, lineEndSpanClass, br) => {
30
99
  const lines = content.split(br)
31
100
  const len = lines.length
32
- const endSpanTag = `<span class="${lineEndSpanClass}"></span>`
101
+ const endSpanTag = needEndSpan ? `<span class="${lineEndSpanClass}"></span>` : ''
102
+ const maxLine = len - (lines[len - 1] === '' ? 1 : 0)
33
103
  let emIdx = 0
34
- let [emStart, emEnd] = emphasizeLines[0] || []
104
+ let emStart
105
+ let emEnd
106
+ let doEmphasis = false
107
+ if (needEmphasis && maxLine > 0) {
108
+ const normalized = []
109
+ for (const range of emphasizeLines) {
110
+ let [s, e] = range
111
+ if (s == null) s = 1
112
+ if (e == null) e = maxLine
113
+ if (!Number.isFinite(s) || !Number.isFinite(e) || s <= 0 || e <= 0) continue
114
+ if (s > e) {
115
+ const tmp = s
116
+ s = e
117
+ e = tmp
118
+ }
119
+ if (s > maxLine || e < 1) continue
120
+ if (e > maxLine) e = maxLine
121
+ normalized.push([s, e])
122
+ }
123
+ if (normalized.length > 0) {
124
+ doEmphasis = true
125
+ emphasizeLines = normalized
126
+ ;[emStart, emEnd] = emphasizeLines[0]
127
+ }
128
+ }
35
129
  for (let n = 0; n < len; n++) {
36
130
  let line = lines[n]
37
131
 
38
132
  if (needEndSpan) {
39
- let lineLen = 0
40
- for (let i = 0, L = line.length; i < L; i++) {
41
- lineLen += line.charCodeAt(i) > 255 ? 2 : 1
133
+ let lineLen = line.length
134
+ if (lineLen < threshold) {
135
+ lineLen = 0
136
+ for (let i = 0, L = line.length; i < L; i++) {
137
+ lineLen += line.charCodeAt(i) > 255 ? 2 : 1
138
+ if (lineLen >= threshold) break
139
+ }
42
140
  }
43
141
  if (lineLen >= threshold) {
44
142
  if (line.slice(-closeTagLen) === closeTag) {
@@ -50,26 +148,29 @@ const splitFenceBlockToLines = (content, emphasizeLines, needLineNumber, needEmp
50
148
  }
51
149
 
52
150
  if (needLineNumber && n !== len - 1) {
53
- const tagStack = []
54
- tagReg.lastIndex = 0
55
- let match
56
- while ((match = tagReg.exec(line)) !== null) {
57
- const [fullMatch, tagName] = match
58
- if (fullMatch.startsWith('</')) {
59
- if (tagStack[tagStack.length-1] === tagName) tagStack.pop()
60
- } else if (!fullMatch.endsWith('/>')) {
61
- tagStack.push(tagName)
151
+ if (line.indexOf('<') !== -1) {
152
+ const tagStack = []
153
+ tagReg.lastIndex = 0
154
+ let match
155
+ while ((match = tagReg.exec(line)) !== null) {
156
+ const [fullMatch, tagName] = match
157
+ const tagNameLower = tagName.toLowerCase()
158
+ if (fullMatch.startsWith('</')) {
159
+ if (tagStack[tagStack.length-1] === tagNameLower) tagStack.pop()
160
+ } else if (!fullMatch.endsWith('/>') && !voidTags.has(tagNameLower)) {
161
+ tagStack.push(tagNameLower)
162
+ }
163
+ }
164
+ for (let i = tagStack.length-1; i >= 0; i--) {
165
+ const tagName = tagStack[i]
166
+ line += `</${tagName}>`
167
+ lines[n+1] = `<${tagName}>` + (lines[n+1]||'')
62
168
  }
63
- }
64
- for (let i = tagStack.length-1; i >= 0; i--) {
65
- const tagName = tagStack[i]
66
- line += `</${tagName}>`
67
- lines[n+1] = `<${tagName}>` + (lines[n+1]||'')
68
169
  }
69
170
  line = preLineTag + line + closeTag
70
171
  }
71
172
 
72
- if (needEmphasis) {
173
+ if (doEmphasis) {
73
174
  if (emStart === n + 1) line = emphOpenTag + line
74
175
  if (emEnd === n) {
75
176
  line = closeTag + line
@@ -123,7 +224,8 @@ const orderTokenAttrs = (token, opt) => {
123
224
  const getFenceHtml = (tokens, idx, md, opt, slf) => {
124
225
  const token = tokens[idx]
125
226
  let content = token.content
126
- const match = token.info.trim().match(infoReg)
227
+ const info = token.info.trim()
228
+ const match = info.match(infoReg)
127
229
  let lang = match ? match[1] : ''
128
230
 
129
231
  if (match && match[2]) {
@@ -132,36 +234,116 @@ const getFenceHtml = (tokens, idx, md, opt, slf) => {
132
234
  let langClass = ''
133
235
  if (lang && lang !== 'samp') {
134
236
  langClass = opt.langPrefix + lang
135
- token.attrSet('class', langClass + (token.attrGet('class') ? ' ' + token.attrGet('class') : ''))
237
+ const existingClass = token.attrGet('class')
238
+ token.attrSet('class', existingClass ? langClass + ' ' + existingClass : langClass)
136
239
  }
137
240
 
138
241
  let startNumber = -1
139
242
  let emphasizeLines = []
243
+ let wrapEnabled = false
244
+ let preWrapValue
140
245
 
141
246
  if (token.attrs) {
142
- for (let attr of token.attrs) {
143
- if (attr[0] === 'class') {
144
- const hasClassLang = attr[1].match(opt._langReg)
145
- if (hasClassLang) lang = hasClassLang[1]
146
- }
147
- if (startReg.test(attr[0])) {
148
- startNumber = +attr[1]
149
- if (attr[0] !== 'data-pre-start') {
150
- token.attrSet('data-pre-start', attr[1])
151
- token.attrs = token.attrs.filter(attr => !startFilterReg.test(attr[0]))
247
+ const newAttrs = []
248
+ let dataPreStartIndex = -1
249
+ let dataPreEmphasisIndex = -1
250
+ let styleIndex = -1
251
+ let startValue
252
+ let emphasisValue
253
+ let styleValue
254
+ let sawStartAttr = false
255
+ let sawEmphasisAttr = false
256
+ const appendOrder = []
257
+
258
+ for (const attr of token.attrs) {
259
+ const name = attr[0]
260
+ const val = attr[1]
261
+
262
+ switch (name) {
263
+ case 'class': {
264
+ if (val.indexOf(opt.langPrefix) !== -1) {
265
+ const hasClassLang = opt._langReg.exec(val)
266
+ if (hasClassLang) lang = hasClassLang[1]
267
+ }
268
+ newAttrs.push(attr)
269
+ break
152
270
  }
271
+ case 'style':
272
+ styleIndex = newAttrs.length
273
+ styleValue = val
274
+ newAttrs.push(attr)
275
+ break
276
+ case 'data-pre-start':
277
+ startNumber = +val
278
+ startValue = val
279
+ dataPreStartIndex = newAttrs.length
280
+ newAttrs.push(attr)
281
+ break
282
+ case 'start':
283
+ case 'pre-start':
284
+ startNumber = +val
285
+ startValue = val
286
+ if (!sawStartAttr) {
287
+ appendOrder.push('start')
288
+ sawStartAttr = true
289
+ }
290
+ break
291
+ case 'data-pre-emphasis':
292
+ dataPreEmphasisIndex = newAttrs.length
293
+ newAttrs.push(attr)
294
+ break
295
+ case 'em-lines':
296
+ case 'emphasize-lines':
297
+ emphasizeLines = getEmphasizeLines(val)
298
+ emphasisValue = val
299
+ if (!sawEmphasisAttr) {
300
+ appendOrder.push('emphasis')
301
+ sawEmphasisAttr = true
302
+ }
303
+ break
304
+ case 'data-pre-wrap':
305
+ preWrapValue = val
306
+ if (val === '' || val === 'true') wrapEnabled = true
307
+ break
308
+ case 'wrap':
309
+ case 'pre-wrap':
310
+ if (val === '' || val === 'true') {
311
+ wrapEnabled = true
312
+ }
313
+ break
314
+ default:
315
+ newAttrs.push(attr)
153
316
  }
154
- if (emphasisReg.test(attr[0])) {
155
- emphasizeLines = getEmphasizeLines(attr[1])
156
- token.attrSet('data-pre-emphasis', attr[1])
157
- token.attrs = token.attrs.filter(attr => !emphasisReg.test(attr[0]))
317
+ }
318
+
319
+ if (startValue !== undefined && dataPreStartIndex >= 0) {
320
+ newAttrs[dataPreStartIndex][1] = startValue
321
+ }
322
+ if (emphasisValue !== undefined && dataPreEmphasisIndex >= 0) {
323
+ newAttrs[dataPreEmphasisIndex][1] = emphasisValue
324
+ }
325
+ for (const kind of appendOrder) {
326
+ if (kind === 'start') {
327
+ if (dataPreStartIndex === -1 && startValue !== undefined) {
328
+ newAttrs.push(['data-pre-start', startValue])
329
+ }
330
+ } else if (kind === 'emphasis') {
331
+ if (dataPreEmphasisIndex === -1 && emphasisValue !== undefined) {
332
+ newAttrs.push(['data-pre-emphasis', emphasisValue])
333
+ }
158
334
  }
159
335
  }
336
+ if (startNumber !== -1) {
337
+ styleValue = appendStyleValue(styleValue, 'counter-set:pre-line-number ' + startNumber + ';')
338
+ }
339
+ if (styleIndex >= 0) {
340
+ if (styleValue !== undefined) newAttrs[styleIndex][1] = styleValue
341
+ } else if (styleValue) {
342
+ newAttrs.push(['style', styleValue])
343
+ }
344
+ if (wrapEnabled) preWrapValue = 'true'
345
+ token.attrs = newAttrs
160
346
  }
161
- if (startNumber !== -1) {
162
- token.attrJoin('style', 'counter-set:pre-line-number ' + startNumber + ';')
163
- }
164
- orderTokenAttrs(token, opt)
165
347
 
166
348
  if (opt.setHighlight && md.options.highlight) {
167
349
  if (lang && lang !== 'samp' ) {
@@ -173,17 +355,52 @@ const getFenceHtml = (tokens, idx, md, opt, slf) => {
173
355
  content = md.utils.escapeHtml(token.content)
174
356
  }
175
357
 
358
+ let preAttrsFromHighlight
359
+ if (content.indexOf('<pre') !== -1) {
360
+ const preMatch = content.match(preCodeWrapperReg)
361
+ if (preMatch) {
362
+ preAttrsFromHighlight = parseHtmlAttrs(preMatch[1])
363
+ const codeAttrsFromHighlight = parseHtmlAttrs(preMatch[2])
364
+ content = preMatch[3]
365
+ if (codeAttrsFromHighlight.length) {
366
+ if (!token.attrs) token.attrs = []
367
+ mergeAttrSets(token.attrs, codeAttrsFromHighlight)
368
+ }
369
+ }
370
+ }
371
+ orderTokenAttrs(token, opt)
372
+
373
+ let preAttrs = preAttrsFromHighlight ? preAttrsFromHighlight.slice() : []
374
+ if (preWrapValue !== undefined) {
375
+ const idx = preAttrs.findIndex(attr => attr[0] === 'data-pre-wrap')
376
+ if (idx === -1) {
377
+ preAttrs.push(['data-pre-wrap', preWrapValue])
378
+ } else {
379
+ preAttrs[idx][1] = preWrapValue
380
+ }
381
+ }
382
+ if (wrapEnabled && opt.setPreWrapStyle !== false) {
383
+ const idx = preAttrs.findIndex(attr => attr[0] === 'style')
384
+ if (idx === -1) {
385
+ preAttrs.push(['style', preWrapStyle])
386
+ } else {
387
+ preAttrs[idx][1] = appendStyleValue(preAttrs[idx][1], preWrapStyle)
388
+ }
389
+ }
390
+ if (preAttrs.length) orderTokenAttrs({ attrs: preAttrs }, opt)
391
+ const preAttrsText = preAttrs.length ? slf.renderAttrs({ attrs: preAttrs }) : ''
392
+
176
393
  const needLineNumber = opt.setLineNumber && startNumber >= 0
177
394
  const needEmphasis = opt.setEmphasizeLines && emphasizeLines.length > 0
178
395
  const needEndSpan = opt.setLineEndSpan > 0
179
396
  if (needLineNumber || needEmphasis || needEndSpan) {
180
- const brMatch = content.match(/\r?\n/)
181
- const br = brMatch ? brMatch[0] : '\n'
397
+ const nlIndex = content.indexOf('\n')
398
+ const br = nlIndex > 0 && content[nlIndex - 1] === '\r' ? '\r\n' : '\n'
182
399
  content = splitFenceBlockToLines(content, emphasizeLines, needLineNumber, needEmphasis, needEndSpan, opt.setLineEndSpan, opt.lineEndSpanClass, br)
183
400
  }
184
401
 
185
402
  const tag = opt._sampReg.test(lang) ? 'samp' : 'code'
186
- return `<pre><${tag}${slf.renderAttrs(token)}>${content}</${tag}></pre>\n`
403
+ return `<pre${preAttrsText}><${tag}${slf.renderAttrs(token)}>${content}</${tag}></pre>\n`
187
404
  }
188
405
 
189
406
  const mditRendererFence = (md, option) => {
@@ -194,6 +411,7 @@ const mditRendererFence = (md, option) => {
194
411
  setEmphasizeLines: true,
195
412
  setLineEndSpan: 0,
196
413
  lineEndSpanClass: 'pre-lineend-spacer',
414
+ setPreWrapStyle: true,
197
415
  sampLang: 'shell,console',
198
416
  langPrefix: md.options.langPrefix || 'language-',
199
417
  }
@@ -207,4 +425,4 @@ const mditRendererFence = (md, option) => {
207
425
  }
208
426
  }
209
427
 
210
- export default mditRendererFence
428
+ export default mditRendererFence
package/package.json CHANGED
@@ -1,8 +1,13 @@
1
1
  {
2
2
  "name": "@peaceroad/markdown-it-renderer-fence",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
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
+ "files": [
7
+ "index.js",
8
+ "LICENSE",
9
+ "README.md"
10
+ ],
6
11
  "type": "module",
7
12
  "scripts": {
8
13
  "test": "node test/test.js"
@@ -11,9 +16,10 @@
11
16
  "repository": "https://github.com/peaceroad/p7d-markdown-it-renderer-fence",
12
17
  "license": "MIT",
13
18
  "devDependencies": {
14
- "@peaceroad/markdown-it-figure-with-p-caption": "^0.10.1",
19
+ "@peaceroad/markdown-it-figure-with-p-caption": "^0.15.1",
20
+ "highlight.js": "^11.11.1",
15
21
  "markdown-it": "^14.1.0",
16
- "markdown-it-attrs": "^4.2.0",
17
- "highlight.js": "^11.10.0"
22
+ "markdown-it-attrs": "^4.3.1",
23
+ "shiki": "^3.21.0"
18
24
  }
19
25
  }
@@ -1,55 +0,0 @@
1
- [Markdown]
2
- ```
3
- 1234567890
4
- 2
5
- 1234567890
6
- 4
7
- 1234567890
8
- 6
9
- ```
10
- [HTML]
11
- <pre><code>1234567890<span class="pre-lineend-spacer"></span>
12
- 2
13
- 1234567890<span class="pre-lineend-spacer"></span>
14
- 4
15
- 1234567890<span class="pre-lineend-spacer"></span>
16
- 6
17
- </code></pre>
18
-
19
-
20
- [Markdown]
21
- ``` {em-lines="3"}
22
- 1234567890
23
- 2
24
- 1234567890
25
- 4
26
- 1234567890
27
- 6
28
- ```
29
- [HTML]
30
- <pre><code data-pre-emphasis="3">1234567890<span class="pre-lineend-spacer"></span>
31
- 2
32
- <span class="pre-lines-emphasis">1234567890<span class="pre-lineend-spacer"></span>
33
- </span>4
34
- 1234567890<span class="pre-lineend-spacer"></span>
35
- 6
36
- </code></pre>
37
-
38
-
39
- [Markdown]
40
- ``` {em-lines="3" start="4"}
41
- 1234567890
42
- 2
43
- 1234567890
44
- 4
45
- 1234567890
46
- 6
47
- ```
48
- [HTML]
49
- <pre><code data-pre-emphasis="3" data-pre-start="4" style="counter-set:pre-line-number 4;"><span class="pre-line">1234567890<span class="pre-lineend-spacer"></span></span>
50
- <span class="pre-line">2</span>
51
- <span class="pre-lines-emphasis"><span class="pre-line">1234567890<span class="pre-lineend-spacer"></span></span>
52
- </span><span class="pre-line">4</span>
53
- <span class="pre-line">1234567890<span class="pre-lineend-spacer"></span></span>
54
- <span class="pre-line">6</span>
55
- </code></pre>
@@ -1,93 +0,0 @@
1
- [Markdown]
2
- ``` {em-lines="3-5"}
3
- 1
4
- 2
5
- 3
6
- 4
7
- 5
8
- 6
9
- ```
10
- [HTML]
11
- <pre><code data-pre-emphasis="3-5">1
12
- 2
13
- <span class="pre-lines-emphasis">3
14
- 4
15
- 5
16
- </span>6
17
- </code></pre>
18
-
19
-
20
- [Markdown]
21
- ``` {em-lines="1"}
22
- 1
23
- 2
24
- 3
25
- 4
26
- 5
27
- 6
28
- ```
29
- [HTML]
30
- <pre><code data-pre-emphasis="1"><span class="pre-lines-emphasis">1
31
- </span>2
32
- 3
33
- 4
34
- 5
35
- 6
36
- </code></pre>
37
-
38
-
39
- [Markdown]
40
- ``` {em-lines="1-3,5-6"}
41
- 1
42
- 2
43
- 3
44
- 4
45
- 5
46
- 6
47
- ```
48
- [HTML]
49
- <pre><code data-pre-emphasis="1-3,5-6"><span class="pre-lines-emphasis">1
50
- 2
51
- 3
52
- </span>4
53
- <span class="pre-lines-emphasis">5
54
- 6
55
- </span></code></pre>
56
-
57
-
58
- [Markdown]
59
- ``` {em-lines="3-5" start="1"}
60
- 1
61
- 2
62
- 3
63
- 4
64
- 5
65
- 6
66
- ```
67
- [HTML]
68
- <pre><code data-pre-emphasis="3-5" data-pre-start="1" style="counter-set:pre-line-number 1;"><span class="pre-line">1</span>
69
- <span class="pre-line">2</span>
70
- <span class="pre-lines-emphasis"><span class="pre-line">3</span>
71
- <span class="pre-line">4</span>
72
- <span class="pre-line">5</span>
73
- </span><span class="pre-line">6</span>
74
- </code></pre>
75
-
76
-
77
- [Markdown]
78
- ``` {em-lines="2,4-5"}
79
- 1
80
- 2
81
- 3
82
- 4
83
- 5
84
- 6
85
- ```
86
- [HTML]
87
- <pre><code data-pre-emphasis="2,4-5">1
88
- <span class="pre-lines-emphasis">2
89
- </span>3
90
- <span class="pre-lines-emphasis">4
91
- 5
92
- </span>6
93
- </code></pre>
@@ -1,175 +0,0 @@
1
- [Markdown]
2
- ```js
3
- import mdit from 'markdonw-it'
4
- ```
5
- [HTML]
6
- <pre><code class="language-js"><span class="hljs-keyword">import</span> mdit <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;markdonw-it&#x27;</span>
7
- </code></pre>
8
-
9
-
10
- [Markdown]
11
- ```html
12
- <p>I draw <span class="style">cats</span>.</p>
13
- ```
14
- [HTML]
15
- <pre><code class="language-html"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>I draw <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;style&quot;</span>&gt;</span>cats<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
16
- </code></pre>
17
-
18
-
19
- [Markdown]
20
- ```js
21
- import mdit from 'markdonw-it'
22
- const md = mdit()
23
- md.render('Nyaan')
24
- ```
25
- [HTML]
26
- <pre><code class="language-js"><span class="hljs-keyword">import</span> mdit <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;markdonw-it&#x27;</span>
27
- <span class="hljs-keyword">const</span> md = <span class="hljs-title function_">mdit</span>()
28
- md.<span class="hljs-title function_">render</span>(<span class="hljs-string">&#x27;Nyaan&#x27;</span>)
29
- </code></pre>
30
-
31
-
32
- [Markdown]
33
- ```js {.style}
34
- import mdit from 'markdonw-it'
35
- const md = mdit()
36
- md.render('Nyaan')
37
- ```
38
- [HTML]
39
- <pre><code class="language-js style"><span class="hljs-keyword">import</span> mdit <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;markdonw-it&#x27;</span>
40
- <span class="hljs-keyword">const</span> md = <span class="hljs-title function_">mdit</span>()
41
- md.<span class="hljs-title function_">render</span>(<span class="hljs-string">&#x27;Nyaan&#x27;</span>)
42
- </code></pre>
43
-
44
-
45
- [Markdown]
46
- ```html {start="2"}
47
- <p>I draw <span class="style">cats</span>.</p>
48
- ```
49
- [HTML]
50
- <pre><code class="language-html" data-pre-start="2" style="counter-set:pre-line-number 2;"><span class="pre-line"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>I draw <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;style&quot;</span>&gt;</span>cats<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
51
- </code></pre>
52
-
53
-
54
- [Markdown]
55
- ```js {start="1"}
56
- import mdit from 'markdonw-it'
57
- ```
58
- [HTML]
59
- <pre><code class="language-js" data-pre-start="1" style="counter-set:pre-line-number 1;"><span class="pre-line"><span class="hljs-keyword">import</span> mdit <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;markdonw-it&#x27;</span></span>
60
- </code></pre>
61
-
62
-
63
- [Markdown]
64
- ```js {.style start="1"}
65
- import mdit from 'markdonw-it'
66
- const md = mdit()
67
- md.render('Nyaan')
68
- ```
69
- [HTML]
70
- <pre><code class="language-js style" data-pre-start="1" style="counter-set:pre-line-number 1;"><span class="pre-line"><span class="hljs-keyword">import</span> mdit <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;markdonw-it&#x27;</span></span>
71
- <span class="pre-line"><span class="hljs-keyword">const</span> md = <span class="hljs-title function_">mdit</span>()</span>
72
- <span class="pre-line">md.<span class="hljs-title function_">render</span>(<span class="hljs-string">&#x27;Nyaan&#x27;</span>)</span>
73
- </code></pre>
74
-
75
-
76
- [Markdown]
77
- ```shell
78
- $ pwd
79
- /home/User
80
- ```
81
- [HTML]
82
- <pre><samp class="language-shell"><span class="hljs-meta prompt_">$ </span><span class="language-bash"><span class="hljs-built_in">pwd</span></span>
83
- /home/User
84
- </samp></pre>
85
-
86
-
87
- [Markdown]
88
- ```console
89
- $ pwd
90
- /home/User
91
- ```
92
- [HTML]
93
- <pre><samp class="language-console"><span class="hljs-meta prompt_">$ </span><span class="language-bash"><span class="hljs-built_in">pwd</span></span>
94
- /home/User
95
- </samp></pre>
96
-
97
-
98
- [Markdown]
99
- ```samp
100
- $ pwd
101
- /home/User
102
- ```
103
- [HTML]
104
- <pre><samp>$ pwd
105
- /home/User
106
- </samp></pre>
107
-
108
- [Markdown]
109
- ``` {}
110
- console.log('A test.')
111
- ```
112
- [HTML]
113
- <pre><code>console.log('A test.')
114
- </code></pre>
115
-
116
- [Markdown]
117
- ```js
118
- console.log('A test.')
119
- ```
120
- [HTML]
121
- <pre><code class="language-js"><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;A test.&#x27;</span>)
122
- </code></pre>
123
-
124
- [Markdown]
125
- ```js {}
126
- console.log('A test.')
127
- ```
128
- [HTML]
129
- <pre><code class="language-js"><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;A test.&#x27;</span>)
130
- </code></pre>
131
-
132
- [Markdown]
133
- ```js {}
134
- console.log('A test.')
135
- ```
136
- [HTML]
137
- <pre><code class="language-js"><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;A test.&#x27;</span>)
138
- </code></pre>
139
-
140
-
141
- [Markdown]
142
- ~~~ {}
143
- console.log('A test.')
144
- ~~~
145
- [HTML]
146
- <pre><code>console.log('A test.')
147
- </code></pre>
148
-
149
-
150
- [Markdown]
151
- ~~~js {}
152
- console.log('A test.')
153
- ~~~
154
- [HTML]
155
- <pre><code class="language-js"><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;A test.&#x27;</span>)
156
- </code></pre>
157
-
158
-
159
- [Markdown]
160
- ```{.language-js}
161
- console.log('A test.')
162
- ```
163
- [HTML]
164
- <pre><code class="language-js"><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;A test.&#x27;</span>)
165
- </code></pre>
166
-
167
- [Markdown]
168
- ```conf
169
- [Service]
170
- Environment="OLLAMA_HOST=0.0.0.0"
171
- ```
172
- [HTML]
173
- <pre><code class="language-conf">[Service]
174
- Environment="OLLAMA_HOST=0.0.0.0"
175
- </code></pre>
package/test/examples.txt DELETED
@@ -1,130 +0,0 @@
1
- [Markdown]
2
- ```js
3
- import mdit from 'markdonw-it'
4
- mdit().render('A cat.')
5
- ```
6
- [HTML]
7
- <pre><code class="language-js">import mdit from 'markdonw-it'
8
- mdit().render('A cat.')
9
- </code></pre>
10
-
11
-
12
- [Markdown]
13
- ```samp
14
- $ pwd
15
- /home/User
16
- ```
17
- [HTML]
18
- <pre><samp>$ pwd
19
- /home/User
20
- </samp></pre>
21
-
22
-
23
- [Markdown]
24
- ```shell
25
- $ pwd
26
- /home/User
27
- ```
28
- [HTML]
29
- <pre><samp class="language-shell">$ pwd
30
- /home/User
31
- </samp></pre>
32
-
33
-
34
- [Markdown]
35
- ```console
36
- $ pwd
37
- /home/User
38
- ```
39
- [HTML]
40
- <pre><samp class="language-console">$ pwd
41
- /home/User
42
- </samp></pre>
43
-
44
-
45
- [Markdown]
46
- ```
47
- console.log('A test.')
48
- ```
49
- [HTML]
50
- <pre><code>console.log('A test.')
51
- </code></pre>
52
-
53
-
54
- [Markdown]
55
- ``` {}
56
- console.log('A test.')
57
- ```
58
- [HTML]
59
- <pre><code>console.log('A test.')
60
- </code></pre>
61
-
62
- [Markdown]
63
- ```js {}
64
- console.log('A test.')
65
- ```
66
- [HTML]
67
- <pre><code class="language-js">console.log('A test.')
68
- </code></pre>
69
-
70
-
71
- [Markdown]
72
- ```js {}
73
- console.log('A test.')
74
- ```
75
- [HTML]
76
- <pre><code class="language-js">console.log('A test.')
77
- </code></pre>
78
-
79
- [Markdown]
80
- ```js {.style #id}
81
- console.log('A test.')
82
- ```
83
- [HTML]
84
- <pre><code class="language-js style" id="id">console.log('A test.')
85
- </code></pre>
86
-
87
- [Markdown]
88
- ```js {.style}
89
- console.log('A test.')
90
- ```
91
- [HTML]
92
- <pre><code class="language-js style">console.log('A test.')
93
- </code></pre>
94
-
95
-
96
- [Markdown]
97
- ~~~ {}
98
- console.log('A test.')
99
- ~~~
100
- [HTML]
101
- <pre><code>console.log('A test.')
102
- </code></pre>
103
-
104
-
105
- [Markdown]
106
- ~~~js {}
107
- console.log('A test.')
108
- ~~~
109
- [HTML]
110
- <pre><code class="language-js">console.log('A test.')
111
- </code></pre>
112
-
113
-
114
- [Markdown]
115
- ```{.language-js}
116
- console.log('A test.')
117
- ```
118
- [HTML]
119
- <pre><code class="language-js">console.log('A test.')
120
- </code></pre>
121
-
122
-
123
- [Markdown]
124
- ``` js {start="3" aria-label="LABEL"}
125
- console.log('A test.')
126
- ```
127
- [HTML]
128
- <pre><code class="language-js" data-pre-start="3" style="counter-set:pre-line-number 3;" aria-label="LABEL"><span class="pre-line">console.log('A test.')</span>
129
- </code></pre>
130
-
package/test/test.js DELETED
@@ -1,123 +0,0 @@
1
- import assert from 'assert'
2
- import fs from 'fs'
3
- import path from 'path'
4
- import mdit from 'markdown-it'
5
-
6
- import mditFigureWithPCaption from '@peaceroad/markdown-it-figure-with-p-caption'
7
- import mditRendererFence from '../index.js'
8
- import mditAttrs from 'markdown-it-attrs'
9
- import highlightjs from 'highlight.js'
10
-
11
-
12
- let opt = {}
13
-
14
- const md = mdit({ html: true }).use(mditRendererFence).use(mditAttrs)
15
- const mdHighlightJs = mdit({
16
- html: true,
17
- langPrefix: 'language-',
18
- typographer: false,
19
- highlight: (str, lang) => {
20
- if (lang && highlightjs.getLanguage(lang)) {
21
- try {
22
- return highlightjs.highlight(str, { language: lang }).value
23
- } catch (__) {}
24
- }
25
- return str
26
- }
27
- }).use(mditRendererFence, opt).use(mditAttrs)
28
- const mdLinesEmphasis = mdit({ html: true }).use(mditRendererFence).use(mditAttrs)
29
- const mdLIneEndSpan = mdit({ html: true }).use(mditRendererFence, {setLineEndSpan: 8}).use(mditAttrs)
30
-
31
- let __dirname = path.dirname(new URL(import.meta.url).pathname)
32
- const isWindows = (process.platform === 'win32')
33
- if (isWindows) {
34
- __dirname = __dirname.replace(/^\/+/, '').replace(/\//g, '\\')
35
- }
36
-
37
- const testData = {
38
- noOption: __dirname + path.sep + 'examples.txt',
39
- highlightjs: __dirname + path.sep + 'examples-highlightjs.txt',
40
- linesEmphasis: __dirname + path.sep + 'example-lines-emphasis.txt',
41
- lineEndSpan: __dirname + path.sep + 'example-line-end-span.txt',
42
- }
43
-
44
- const getTestData = (pat) => {
45
- let ms = [];
46
- if(!fs.existsSync(pat)) {
47
- console.log('No exist: ' + pat)
48
- return ms
49
- }
50
- const exampleCont = fs.readFileSync(pat, 'utf-8').trim();
51
-
52
- let ms0 = exampleCont.split(/\n*\[Markdown\]\n/);
53
- let n = 1;
54
- while(n < ms0.length) {
55
- let mhs = ms0[n].split(/\n+\[HTML[^\]]*?\]\n/);
56
- let i = 1;
57
- while (i < 2) {
58
- if (mhs[i] === undefined) {
59
- mhs[i] = '';
60
- } else {
61
- mhs[i] = mhs[i].replace(/$/,'\n');
62
- }
63
- i++;
64
- }
65
- ms[n] = {
66
- "markdown": mhs[0],
67
- "html": mhs[1],
68
- };
69
- n++;
70
- }
71
- return ms
72
- }
73
-
74
- const runTest = (process, pat, pass, testId) => {
75
- console.log('===========================================================')
76
- console.log(pat)
77
- let ms = getTestData(pat)
78
- if (ms.length === 0) return
79
- let n = 1;
80
- let end = ms.length - 1
81
- if(testId) {
82
- if (testId[0]) n = testId[0]
83
- if (testId[1]) {
84
- if (ms.length >= testId[1]) {
85
- end = testId[1]
86
- }
87
- }
88
- }
89
- //console.log(n, end)
90
-
91
- while(n <= end) {
92
- if (!ms[n]
93
- //|| n != 14
94
- ) {
95
- n++
96
- continue
97
- }
98
-
99
- const m = ms[n].markdown;
100
- const h = process.render(m)
101
- console.log('Test: ' + n + ' >>>');
102
- try {
103
- assert.strictEqual(h, ms[n].html);
104
- } catch(e) {
105
- pass = false
106
- //console.log('Test: ' + n + ' >>>');
107
- //console.log(opt);
108
- console.log(ms[n].markdown);
109
- console.log('incorrect:');
110
- console.log('H: ' + h +'C: ' + ms[n].html);
111
- }
112
- n++;
113
- }
114
- return pass
115
- }
116
-
117
- let pass = true
118
- pass = runTest(md, testData.noOption, pass)
119
- pass = runTest(mdHighlightJs, testData.highlightjs, pass)
120
- pass = runTest(mdLinesEmphasis, testData.linesEmphasis, pass)
121
- pass = runTest(mdLIneEndSpan, testData.lineEndSpan, pass)
122
-
123
- if (pass) console.log('Passed all test.')