@peaceroad/markdown-it-renderer-fence 0.1.2 → 0.3.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 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
 
@@ -106,7 +106,7 @@ Add `em-lines` or `emphasize-lines` attribute by by adding attributes used markd
106
106
 
107
107
  ~~~html
108
108
  [HTML]
109
- <pre><code>1
109
+ <pre><code data-pre-emphasis="2,4-5">1
110
110
  <span class="pre-lines-emphasis">2
111
111
  </span>3
112
112
  <span class="pre-lines-emphasis">4
@@ -114,3 +114,35 @@ Add `em-lines` or `emphasize-lines` attribute by by adding attributes used markd
114
114
  </span>6
115
115
  </code></pre>
116
116
  ~~~
117
+
118
+ ## Enable pre-wrap for code blocks
119
+
120
+ Add `wrap` or `pre-wrap` attribute (optionally `="true"`) by adding attributes used markdown-it-attrs.
121
+
122
+ ~~~md
123
+ ```js {wrap}
124
+ const longLine = 'This line is long but wraps.'
125
+ ```
126
+ ~~~
127
+
128
+ ~~~html
129
+ <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.'
130
+ </code></pre>
131
+ ~~~
132
+
133
+ When `setPreWrapStyle` is set to false, only `data-pre-wrap="true"` is added and the inline style is omitted.
134
+
135
+
136
+ ## Options
137
+
138
+ The following options can be specified when initializing the plugin:
139
+
140
+ - attrsOrder: default ['class','id','data-*','style'] — order of attributes in output; wildcards supported.
141
+ - setHighlight: default true — enable calling highlight function (e.g., highlight.js).
142
+ - setLineNumber: default true — wrap lines in spans for line numbers.
143
+ - setEmphasizeLines: default true — enable emphasis based on emphasize-lines attribute.
144
+ - setLineEndSpan: default 0 — character count threshold to append end-of-line span (0 to disable).
145
+ - lineEndSpanClass: default 'pre-lineend-spacer' — CSS class for end-of-line span.
146
+ - setPreWrapStyle: default true — include inline pre-wrap styles on `<pre>` when wrap is enabled.
147
+ - sampLang: default 'shell,console' — comma-separated list of languages (in addition to 'samp') that will be rendered using `<samp>`.
148
+ - langPrefix: default md.options.langPrefix || 'language-' — prefix for language class on code blocks.
package/index.js CHANGED
@@ -1,68 +1,108 @@
1
- //import highlightjs from 'highlight.js'
2
-
3
- const fenceStartTag = (tagName, sAttr) => {
4
- let orderedAttrs = [...sAttr.id, ...sAttr.clas, ...sAttr.data, ...sAttr.style, ...sAttr.other]
5
- //console.log(orderedAttrs)
6
- let tag = '<' + tagName
7
- for (let attr of orderedAttrs) {
8
- if (attr[0]) tag += ' ' + attr[0] + '="' + attr[1] + '"'
9
- }
10
- return tag + '>'
1
+ const infoReg = /^([^{\s]*)(?:\s*\{(.*)\})?$/
2
+
3
+ const attrReg = /^(?:([.#])(.+)|(.+?)(?:=(["'])?(.*?)\1)?)$/
4
+ const interAttrsSpaceReg = / +/
5
+ const tagReg = /<\/?([A-Za-z][A-Za-z0-9-]*)(?:\s+[^>]*?)?\/?\s*>/g
6
+ const preLineTag = '<span class="pre-line">'
7
+ const emphOpenTag = '<span class="pre-lines-emphasis">'
8
+ const closeTag = '</span>'
9
+ const closeTagLen = closeTag.length
10
+ const preWrapStyle = 'white-space: pre-wrap; overflow-wrap: anywhere;'
11
+
12
+ const appendStyleValue = (style, addition) => {
13
+ if (!addition) return style
14
+ let next = addition.trim()
15
+ if (!next) return style
16
+ if (!next.endsWith(';')) next += ';'
17
+ if (!style) return next
18
+ const base = style.trimEnd()
19
+ const separator = base.endsWith(';') ? ' ' : '; '
20
+ return base + separator + next
11
21
  }
12
22
 
13
- const parseEmphasizeLines = (attrValue) => {
23
+ const getEmphasizeLines = (attrVal) => {
14
24
  const lines = []
15
25
  let s, e
16
- attrValue.split(',').forEach(range => {
17
- if (range.includes('-')) {
18
- [s, e] = range.split('-').map(n => parseInt(n.trim(), 10));
19
- lines.push([s, e]);
26
+ attrVal.split(',').forEach(range => {
27
+ if (range.indexOf('-') > -1) {
28
+ [s, e] = range.split('-').map(n => parseInt(n.trim(), 10))
29
+ lines.push([s, e])
20
30
  } else {
21
31
  s = parseInt(range.trim(), 10)
22
32
  lines.push([s, s])
23
33
  }
24
- });
25
- return lines;
34
+ })
35
+ return lines
26
36
  }
27
37
 
28
- const splitFenceBlockToLines = (content, emphasizeLines, opt, hasPreLineStart) => {
29
- const br = content.match(/\r?\n/)
30
- const lines = content.split(/\r?\n/)
31
- lines.map((line, n) => {
32
- if (opt.setLineNumber && hasPreLineStart) {
33
- const lastElementTag = line.match(/<(\w+)( +[^>]*?)>[^>]*?(<\/\1>)?[^>]*?$/)
34
- if (lastElementTag && !lastElementTag[3]) {
35
- line += '</span>'
36
- if (n < lines.length - 2) {
37
- lines[n + 1] = `<${lastElementTag[1]}${lastElementTag[2]}>` + lines[n + 1]
38
+ const splitFenceBlockToLines = (content, emphasizeLines, needLineNumber, needEmphasis, needEndSpan, threshold, lineEndSpanClass, br) => {
39
+ const lines = content.split(br)
40
+ const len = lines.length
41
+ const endSpanTag = needEndSpan ? `<span class="${lineEndSpanClass}"></span>` : ''
42
+ let emIdx = 0
43
+ let [emStart, emEnd] = emphasizeLines[0] || []
44
+ for (let n = 0; n < len; n++) {
45
+ let line = lines[n]
46
+
47
+ if (needEndSpan) {
48
+ let lineLen = line.length
49
+ if (lineLen < threshold) {
50
+ lineLen = 0
51
+ for (let i = 0, L = line.length; i < L; i++) {
52
+ lineLen += line.charCodeAt(i) > 255 ? 2 : 1
53
+ if (lineLen >= threshold) break
38
54
  }
39
55
  }
40
- if (n < lines.length - 1) {
41
- lines[n] = '<span class="pre-line">' + line + '</span>'
56
+ if (lineLen >= threshold) {
57
+ if (line.slice(-closeTagLen) === closeTag) {
58
+ line = line.slice(0, -closeTagLen) + endSpanTag + closeTag
59
+ } else {
60
+ line = line + endSpanTag
61
+ }
42
62
  }
43
63
  }
44
64
 
45
- if (opt.setEmphasizeLines && emphasizeLines.length > 0) {
46
- if (emphasizeLines[0][0] === n + 1) {
47
- lines[n] = `<span class="pre-lines-emphasis">${lines[n]}`
48
- }
49
- if (emphasizeLines[0][1] === n) {
50
- lines[n] = '</span>' + lines[n]
51
- emphasizeLines.shift()
65
+ if (needLineNumber && n !== len - 1) {
66
+ if (line.indexOf('<') !== -1) {
67
+ const tagStack = []
68
+ tagReg.lastIndex = 0
69
+ let match
70
+ while ((match = tagReg.exec(line)) !== null) {
71
+ const [fullMatch, tagName] = match
72
+ if (fullMatch.startsWith('</')) {
73
+ if (tagStack[tagStack.length-1] === tagName) tagStack.pop()
74
+ } else if (!fullMatch.endsWith('/>')) {
75
+ tagStack.push(tagName)
76
+ }
77
+ }
78
+ for (let i = tagStack.length-1; i >= 0; i--) {
79
+ const tagName = tagStack[i]
80
+ line += `</${tagName}>`
81
+ lines[n+1] = `<${tagName}>` + (lines[n+1]||'')
82
+ }
52
83
  }
84
+ line = preLineTag + line + closeTag
53
85
  }
54
86
 
55
- })
87
+ if (needEmphasis) {
88
+ if (emStart === n + 1) line = emphOpenTag + line
89
+ if (emEnd === n) {
90
+ line = closeTag + line
91
+ emIdx++
92
+ [emStart, emEnd] = emphasizeLines[emIdx] || []
93
+ }
94
+ }
95
+ lines[n] = line
96
+ }
56
97
  return lines.join(br)
57
98
  }
58
99
 
59
- const setInfoAttr = (infoAttr) => {
100
+ const getInfoAttr = (infoAttr) => {
101
+ let attrSets = infoAttr.trim().split(interAttrsSpaceReg)
60
102
  let arr = []
61
- let attrSets = infoAttr.trim().split(/ +/)
62
103
  for (let attrSet of attrSets) {
63
- const str = attrSet.match(/^(?:([.#])(.+)|(.+?)(?:=("')?(.*?)\1?)?)$/)
104
+ const str = attrReg.exec(attrSet)
64
105
  if (str) {
65
- //console.log(str)
66
106
  if (str[1] === '.') str[1] = 'class'
67
107
  if (str[1] === '#') str[1] = 'id'
68
108
  if (str[3]) {
@@ -75,103 +115,202 @@ const setInfoAttr = (infoAttr) => {
75
115
  return arr
76
116
  }
77
117
 
78
- const getFenceHtml = (tokens, idx, env, slf, md, options) => {
79
- const opt = {
80
- setHighlight: true,
81
- setLineNumber: true,
82
- setEmphasizeLines: true,
83
- langPrefix: 'language-',
84
- highlight: null,
85
- }
86
- if (options) Object.assign(opt, options)
118
+ const orderTokenAttrs = (token, opt) => {
119
+ if (!token.attrs) return
120
+ const order = opt.attrsOrder || []
121
+ token.attrs.sort((a, b) => {
122
+ const idx = (name) => {
123
+ for (let i = 0; i < order.length; i++) {
124
+ const key = order[i]
125
+ if (key.endsWith('*')) {
126
+ const prefix = key.slice(0, -1)
127
+ if (name.startsWith(prefix)) return i
128
+ } else if (name === key) {
129
+ return i
130
+ }
131
+ }
132
+ return order.length
133
+ }
134
+ return idx(a[0]) - idx(b[0])
135
+ })
136
+ }
87
137
 
138
+ const getFenceHtml = (tokens, idx, md, opt, slf) => {
88
139
  const token = tokens[idx]
89
140
  let content = token.content
90
- const infoAttr = token.info.trim().match(/{(.*)}$/)
91
- if(infoAttr) {
92
- token.attrs = token.attrs ? [...token.attrs, ...setInfoAttr(infoAttr[1])] : setInfoAttr(infoAttr[1])
141
+ const info = token.info.trim()
142
+ const match = info.match(infoReg)
143
+ let lang = match ? match[1] : ''
144
+
145
+ if (match && match[2]) {
146
+ getInfoAttr(match[2]).forEach(([name, val]) => token.attrJoin(name, val))
147
+ }
148
+ let langClass = ''
149
+ if (lang && lang !== 'samp') {
150
+ langClass = opt.langPrefix + lang
151
+ const existingClass = token.attrGet('class')
152
+ token.attrSet('class', existingClass ? langClass + ' ' + existingClass : langClass)
93
153
  }
94
154
 
95
- let lang = token.info.trim().replace(/ *({.*)?$/, '')
96
- const langClass = lang && token.info !== 'samp' ? opt.langPrefix + lang : ''
97
- let sAttr = {id: [], clas: [], data: [], style: [], other: []}
98
- let hasPreLineStart = false
99
- let preLineStart = -1
155
+ let startNumber = -1
100
156
  let emphasizeLines = []
157
+ let wrapEnabled = false
158
+ let preWrapValue
159
+
101
160
  if (token.attrs) {
102
- //console.log('start: ' +token.attrs)
103
- for (let attr of token.attrs) {
104
- if (attr[0] === 'id') {
105
- sAttr.id.push(attr)
106
- } else if (attr[0] === 'class') {
107
- const sAttrClass = langClass ? langClass + ' ' + attr[1] : attr[1]
108
- const hasLang = attr[1].match(new RegExp('(?:^| )' + opt.langPrefix + '(.*)(?: |$)'))
109
- if (hasLang) lang = hasLang[1]
110
- sAttr.clas.push([attr[0], sAttrClass])
111
- } else if (attr[0].startsWith('data-') || /^(?:pre-)?start$/.test(attr[0])) {
112
- if (/^(?:(?:data-)?pre-)?start$/.test(attr[0])) {
113
- hasPreLineStart = true
114
- preLineStart = attr[1]
115
- attr[0] = 'data-pre-start'
161
+ const newAttrs = []
162
+ let dataPreStartIndex = -1
163
+ let dataPreEmphasisIndex = -1
164
+ let styleIndex = -1
165
+ let startValue
166
+ let emphasisValue
167
+ let styleValue
168
+ let sawStartAttr = false
169
+ let sawEmphasisAttr = false
170
+ const appendOrder = []
171
+
172
+ for (const attr of token.attrs) {
173
+ const name = attr[0]
174
+ const val = attr[1]
175
+
176
+ switch (name) {
177
+ case 'class': {
178
+ if (val.indexOf(opt.langPrefix) !== -1) {
179
+ const hasClassLang = opt._langReg.exec(val)
180
+ if (hasClassLang) lang = hasClassLang[1]
181
+ }
182
+ newAttrs.push(attr)
183
+ break
116
184
  }
117
- sAttr.data.push(attr)
118
- } else if (/^em(?:phasize)?-lines$/.test(attr[0])) {
119
- emphasizeLines = parseEmphasizeLines(attr[1])
120
- } else if (attr[0] === 'style') {
121
- sAttr.style.push(attr)
122
- } else {
123
- sAttr.other.push(attr)
185
+ case 'style':
186
+ styleIndex = newAttrs.length
187
+ styleValue = val
188
+ newAttrs.push(attr)
189
+ break
190
+ case 'data-pre-start':
191
+ startNumber = +val
192
+ startValue = val
193
+ dataPreStartIndex = newAttrs.length
194
+ newAttrs.push(attr)
195
+ break
196
+ case 'start':
197
+ case 'pre-start':
198
+ startNumber = +val
199
+ startValue = val
200
+ if (!sawStartAttr) {
201
+ appendOrder.push('start')
202
+ sawStartAttr = true
203
+ }
204
+ break
205
+ case 'data-pre-emphasis':
206
+ dataPreEmphasisIndex = newAttrs.length
207
+ newAttrs.push(attr)
208
+ break
209
+ case 'em-lines':
210
+ case 'emphasize-lines':
211
+ emphasizeLines = getEmphasizeLines(val)
212
+ emphasisValue = val
213
+ if (!sawEmphasisAttr) {
214
+ appendOrder.push('emphasis')
215
+ sawEmphasisAttr = true
216
+ }
217
+ break
218
+ case 'data-pre-wrap':
219
+ preWrapValue = val
220
+ if (val === '' || val === 'true') wrapEnabled = true
221
+ break
222
+ case 'wrap':
223
+ case 'pre-wrap':
224
+ if (val === '' || val === 'true') {
225
+ wrapEnabled = true
226
+ }
227
+ break
228
+ default:
229
+ newAttrs.push(attr)
124
230
  }
125
231
  }
232
+
233
+ if (startValue !== undefined && dataPreStartIndex >= 0) {
234
+ newAttrs[dataPreStartIndex][1] = startValue
235
+ }
236
+ if (emphasisValue !== undefined && dataPreEmphasisIndex >= 0) {
237
+ newAttrs[dataPreEmphasisIndex][1] = emphasisValue
238
+ }
239
+ for (const kind of appendOrder) {
240
+ if (kind === 'start') {
241
+ if (dataPreStartIndex === -1 && startValue !== undefined) {
242
+ newAttrs.push(['data-pre-start', startValue])
243
+ }
244
+ } else if (kind === 'emphasis') {
245
+ if (dataPreEmphasisIndex === -1 && emphasisValue !== undefined) {
246
+ newAttrs.push(['data-pre-emphasis', emphasisValue])
247
+ }
248
+ }
249
+ }
250
+ if (startNumber !== -1) {
251
+ styleValue = appendStyleValue(styleValue, 'counter-set:pre-line-number ' + startNumber + ';')
252
+ }
253
+ if (styleIndex >= 0) {
254
+ if (styleValue !== undefined) newAttrs[styleIndex][1] = styleValue
255
+ } else if (styleValue) {
256
+ newAttrs.push(['style', styleValue])
257
+ }
258
+ if (wrapEnabled) preWrapValue = 'true'
259
+ token.attrs = newAttrs
126
260
  }
127
- if (sAttr.clas.length === 0 && langClass !== '') sAttr.clas.push(['class', langClass])
128
- if (hasPreLineStart && preLineStart !== -1) {
129
- if (sAttr.style.length === 0) {
130
- sAttr.style.push(['style', 'counter-set:pre-line-number ' + preLineStart + ';'])
131
- } else {
132
- sAttr.style[0][1] = sAttr.style[0][1].replace(/;?$/, '; counter-set:pre-line-number ' + preLineStart + ';')
261
+ orderTokenAttrs(token, opt)
262
+ let preAttrs = ''
263
+ if (preWrapValue !== undefined) {
264
+ const escapeHtml = md.utils.escapeHtml
265
+ preAttrs = ' data-pre-wrap="' + escapeHtml(preWrapValue) + '"'
266
+ if (wrapEnabled && opt.setPreWrapStyle !== false) {
267
+ preAttrs += ' style="' + escapeHtml(preWrapStyle) + '"'
133
268
  }
134
269
  }
135
- //console.log(JSON.stringify(sAttr))
270
+
136
271
  if (opt.setHighlight && md.options.highlight) {
137
272
  if (lang && lang !== 'samp' ) {
138
273
  content = md.options.highlight(content, lang)
139
- /*
140
- try {
141
- content = highlightjs.highlight(token.content, {language: lang}).value
142
- } catch (__) {}
143
- */
144
274
  } else {
145
275
  content = md.utils.escapeHtml(token.content)
146
276
  }
147
277
  } else {
148
278
  content = md.utils.escapeHtml(token.content)
149
279
  }
150
- if (opt.setLineNumber || opt.setEmphasizeLines) {
151
- content = splitFenceBlockToLines(content, emphasizeLines, opt, hasPreLineStart)
152
- }
153
280
 
154
- let fenceHtml = '<pre>'
155
- let isSamp = /^(?:samp|shell|console)$/.test(lang)
156
- if (isSamp) {
157
- fenceHtml += fenceStartTag('samp', sAttr)
158
- } else {
159
- fenceHtml += fenceStartTag('code', sAttr)
281
+ const needLineNumber = opt.setLineNumber && startNumber >= 0
282
+ const needEmphasis = opt.setEmphasizeLines && emphasizeLines.length > 0
283
+ const needEndSpan = opt.setLineEndSpan > 0
284
+ if (needLineNumber || needEmphasis || needEndSpan) {
285
+ const nlIndex = content.indexOf('\n')
286
+ const br = nlIndex > 0 && content[nlIndex - 1] === '\r' ? '\r\n' : '\n'
287
+ content = splitFenceBlockToLines(content, emphasizeLines, needLineNumber, needEmphasis, needEndSpan, opt.setLineEndSpan, opt.lineEndSpanClass, br)
160
288
  }
161
289
 
162
- fenceHtml += content
163
- if (isSamp) {
164
- fenceHtml += '</samp>'
165
- } else {
166
- fenceHtml += '</code>'
167
- }
168
- return fenceHtml + '</pre>\n'
290
+ const tag = opt._sampReg.test(lang) ? 'samp' : 'code'
291
+ return `<pre${preAttrs}><${tag}${slf.renderAttrs(token)}>${content}</${tag}></pre>\n`
169
292
  }
170
293
 
171
- const mditRendererFence = (md, options) => {
172
- md.renderer.rules['fence'] = (tokens, idx, env, slf) => {
173
- return getFenceHtml(tokens, idx, env, slf, md, options)
294
+ const mditRendererFence = (md, option) => {
295
+ const opt = {
296
+ attrsOrder: ['class', 'id', 'data-*', 'style'],
297
+ setHighlight: true,
298
+ setLineNumber: true,
299
+ setEmphasizeLines: true,
300
+ setLineEndSpan: 0,
301
+ lineEndSpanClass: 'pre-lineend-spacer',
302
+ setPreWrapStyle: true,
303
+ sampLang: 'shell,console',
304
+ langPrefix: md.options.langPrefix || 'language-',
305
+ }
306
+ if (option) Object.assign(opt, option)
307
+
308
+ opt._sampReg = new RegExp('^(?:samp|' + opt.sampLang.split(',').join('|') + ')$')
309
+ opt._langReg = new RegExp(opt.langPrefix + '([A-Za-z0-9-]+)')
310
+
311
+ md.renderer.rules['fence'] = (tokens, idx, options, env, slf) => {
312
+ return getFenceHtml(tokens, idx, md, opt, slf)
174
313
  }
175
314
  }
176
315
 
177
- export default mditRendererFence
316
+ export default mditRendererFence
package/package.json CHANGED
@@ -1,8 +1,13 @@
1
1
  {
2
2
  "name": "@peaceroad/markdown-it-renderer-fence",
3
- "version": "0.1.2",
3
+ "version": "0.3.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
+ "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,9 @@
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.14.2",
15
20
  "markdown-it": "^14.1.0",
16
- "markdown-it-attrs": "^4.2.0",
17
- "highlight.js": "^11.10.0"
21
+ "markdown-it-attrs": "^4.3.1",
22
+ "highlight.js": "^11.11.1"
18
23
  }
19
24
  }
@@ -1,98 +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>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><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><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-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>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>
94
-
95
-
96
-
97
-
98
-
@@ -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 id="id" class="language-js style">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,120 +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
-
30
- let __dirname = path.dirname(new URL(import.meta.url).pathname)
31
- const isWindows = (process.platform === 'win32')
32
- if (isWindows) {
33
- __dirname = __dirname.replace(/^\/+/, '').replace(/\//g, '\\')
34
- }
35
-
36
- const testData = {
37
- noOption: __dirname + path.sep + 'examples.txt',
38
- highlightjs: __dirname + path.sep + 'examples-highlightjs.txt',
39
- linesEmphasis: __dirname + path.sep + 'example-lines-emphasis.txt',
40
- }
41
-
42
- const getTestData = (pat) => {
43
- let ms = [];
44
- if(!fs.existsSync(pat)) {
45
- console.log('No exist: ' + pat)
46
- return ms
47
- }
48
- const exampleCont = fs.readFileSync(pat, 'utf-8').trim();
49
-
50
- let ms0 = exampleCont.split(/\n*\[Markdown\]\n/);
51
- let n = 1;
52
- while(n < ms0.length) {
53
- let mhs = ms0[n].split(/\n+\[HTML[^\]]*?\]\n/);
54
- let i = 1;
55
- while (i < 2) {
56
- if (mhs[i] === undefined) {
57
- mhs[i] = '';
58
- } else {
59
- mhs[i] = mhs[i].replace(/$/,'\n');
60
- }
61
- i++;
62
- }
63
- ms[n] = {
64
- "markdown": mhs[0],
65
- "html": mhs[1],
66
- };
67
- n++;
68
- }
69
- return ms
70
- }
71
-
72
- const runTest = (process, pat, pass, testId) => {
73
- console.log('===========================================================')
74
- console.log(pat)
75
- let ms = getTestData(pat)
76
- if (ms.length === 0) return
77
- let n = 1;
78
- let end = ms.length - 1
79
- if(testId) {
80
- if (testId[0]) n = testId[0]
81
- if (testId[1]) {
82
- if (ms.length >= testId[1]) {
83
- end = testId[1]
84
- }
85
- }
86
- }
87
- //console.log(n, end)
88
-
89
- while(n <= end) {
90
- if (!ms[n]
91
- //|| n != 2
92
- ) {
93
- n++
94
- continue
95
- }
96
-
97
- const m = ms[n].markdown;
98
- const h = process.render(m)
99
- console.log('Test: ' + n + ' >>>');
100
- try {
101
- assert.strictEqual(h, ms[n].html);
102
- } catch(e) {
103
- pass = false
104
- //console.log('Test: ' + n + ' >>>');
105
- //console.log(opt);
106
- console.log(ms[n].markdown);
107
- console.log('incorrect:');
108
- console.log('H: ' + h +'C: ' + ms[n].html);
109
- }
110
- n++;
111
- }
112
- return pass
113
- }
114
-
115
- let pass = true
116
- pass = runTest(md, testData.noOption, pass)
117
- pass = runTest(mdHighlightJs, testData.highlightjs, pass)
118
- pass = runTest(mdLinesEmphasis, testData.linesEmphasis, pass)
119
-
120
- if (pass) console.log('Passed all test.')