@peaceroad/markdown-it-renderer-fence 0.1.0 → 0.1.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/index.js +77 -56
- package/package.json +1 -1
- package/test/examples-highlightjs.txt +58 -0
- package/test/examples.txt +87 -0
- package/test/test.js +3 -3
package/index.js
CHANGED
|
@@ -1,56 +1,16 @@
|
|
|
1
|
-
const fenceStartTag = (
|
|
2
|
-
let
|
|
3
|
-
let hasClass = false
|
|
4
|
-
if (token.attrs) {
|
|
5
|
-
//console.log('start: ' +token.attrs)
|
|
6
|
-
for (let attr of token.attrs) {
|
|
7
|
-
if (attr[0] === 'id') {
|
|
8
|
-
idAttr.push(attr)
|
|
9
|
-
} else if (attr[0] === 'class') {
|
|
10
|
-
hasClass = true
|
|
11
|
-
classAttr.push([attr[0], opt.langPrefix + token.info + ' ' + attr[1]])
|
|
12
|
-
} else if (attr[0].startsWith('data-')) {
|
|
13
|
-
dataAttrs.push(attr)
|
|
14
|
-
} else if (attr[0] === 'style') {
|
|
15
|
-
styleAttr.push(attr)
|
|
16
|
-
} else {
|
|
17
|
-
otherAttrs.push(attr)
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
if (!hasClass) classAttr.push(['class', opt.langPrefix + token.info])
|
|
22
|
-
let orderedAttrs = [...idAttr, ...classAttr, ...dataAttrs, ...styleAttr, ...otherAttrs]
|
|
1
|
+
const fenceStartTag = (tagName, sAttr) => {
|
|
2
|
+
let orderedAttrs = [...sAttr.id, ...sAttr.clas, ...sAttr.data, ...sAttr.style, ...sAttr.other]
|
|
23
3
|
//console.log(orderedAttrs)
|
|
24
4
|
let tag = '<' + tagName
|
|
25
5
|
for (let attr of orderedAttrs) {
|
|
26
|
-
tag += ' ' + attr[0] + '="' + attr[1] + '"'
|
|
6
|
+
if (attr[0]) tag += ' ' + attr[0] + '="' + attr[1] + '"'
|
|
27
7
|
}
|
|
28
8
|
return tag + '>'
|
|
29
|
-
}
|
|
9
|
+
}
|
|
30
10
|
|
|
31
11
|
const splitFenceBlockToLines = (token, content) => {
|
|
32
12
|
const br = content.match(/\r?\n/)
|
|
33
13
|
const lines = content.split(/r?\n/)
|
|
34
|
-
let hasCodeLineStart = false
|
|
35
|
-
let styleIndex = -1
|
|
36
|
-
let dataIndex = -1
|
|
37
|
-
let setNumber = -1
|
|
38
|
-
if (token.attrs) {
|
|
39
|
-
token.attrs.forEach((attr, i) => {
|
|
40
|
-
if (attr[i][0] === 'style') styleIndex = i
|
|
41
|
-
hasCodeLineStart = (/^(?:(?:data-)?pre-)?start$/.test(attr[0]))
|
|
42
|
-
if (hasCodeLineStart) dataIndex = i
|
|
43
|
-
})
|
|
44
|
-
}
|
|
45
|
-
if (!hasCodeLineStart && setNumber === -1) return content
|
|
46
|
-
token.attrs[dataIndex][0] = 'data-pre-start'
|
|
47
|
-
setNumber = token.attrs[dataIndex][1]
|
|
48
|
-
|
|
49
|
-
if (styleIndex === -1) {
|
|
50
|
-
token.attrs.push(['style', 'counter-set:pre-line-number ' + setNumber + ';'])
|
|
51
|
-
} else {
|
|
52
|
-
token.attrs[styleIndex][1] = token.attrs[styleIndex][1].replace(/;?$/, '; counter-set:pre-line-number ' + setNumber + ';')
|
|
53
|
-
}
|
|
54
14
|
lines.map((line, n) => {
|
|
55
15
|
const lastElementTag = line.match(/<(\w+)( +[^>]*?)>[^>]*?(<\/\1>)?[^>]*?$/)
|
|
56
16
|
if (lastElementTag && !lastElementTag[3]) {
|
|
@@ -66,6 +26,25 @@ const splitFenceBlockToLines = (token, content) => {
|
|
|
66
26
|
return lines.join(br)
|
|
67
27
|
}
|
|
68
28
|
|
|
29
|
+
const setInfoAttr = (infoAttr) => {
|
|
30
|
+
let arr = []
|
|
31
|
+
let attrSets = infoAttr.trim().split(/ +/)
|
|
32
|
+
for (let attrSet of attrSets) {
|
|
33
|
+
const str = attrSet.match(/^(?:([.#])(.+)|(.+?)(?:=("')?(.*?)\1?)?)$/)
|
|
34
|
+
if (str) {
|
|
35
|
+
console.log(str)
|
|
36
|
+
if (str[1] === '.') str[1] = 'class'
|
|
37
|
+
if (str[1] === '#') str[1] = 'id'
|
|
38
|
+
if (str[3]) {
|
|
39
|
+
str[1] = str[3]
|
|
40
|
+
str[2] = str[5] ? str[5].replace(/^['"]/, '').replace(/['"]$/, '') : ''
|
|
41
|
+
}
|
|
42
|
+
arr.push([str[1], str[2]])
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return arr
|
|
46
|
+
}
|
|
47
|
+
|
|
69
48
|
const getFenceHtml = (tokens, idx, env, slf, md, options) => {
|
|
70
49
|
const opt = {
|
|
71
50
|
setHighlight: true,
|
|
@@ -78,31 +57,73 @@ const getFenceHtml = (tokens, idx, env, slf, md, options) => {
|
|
|
78
57
|
const token = tokens[idx]
|
|
79
58
|
//console.log(token)
|
|
80
59
|
let content = token.content
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
60
|
+
const infoAttr = token.info.trim().match(/{(.*)}$/)
|
|
61
|
+
if(infoAttr) {
|
|
62
|
+
token.attrs = token.attrs ? [...token.attrs, ...setInfoAttr(infoAttr[1])] : setInfoAttr(infoAttr[1])
|
|
63
|
+
}
|
|
64
|
+
//console.log(token.attrs)
|
|
65
|
+
|
|
66
|
+
let lang = token.info.trim().replace(/ *({.*)?$/, '')
|
|
67
|
+
const langClass = lang && token.info !== 'samp' ? opt.langPrefix + lang : ''
|
|
68
|
+
let sAttr = {id: [], clas: [], data: [], style: [], other: []}
|
|
69
|
+
let hasPreLineStart = false
|
|
70
|
+
let preLineStart = -1
|
|
71
|
+
if (token.attrs) {
|
|
72
|
+
//console.log('start: ' +token.attrs)
|
|
73
|
+
for (let attr of token.attrs) {
|
|
74
|
+
if (attr[0] === 'id') {
|
|
75
|
+
sAttr.id.push(attr)
|
|
76
|
+
} else if (attr[0] === 'class') {
|
|
77
|
+
const sAttrClass = langClass ? langClass + ' ' + attr[1] : attr[1]
|
|
78
|
+
const hasLang = attr[1].match(new RegExp('(?:^| )' + opt.langPrefix + '(.*)(?: |$)'))
|
|
79
|
+
if (hasLang) lang = hasLang[1]
|
|
80
|
+
sAttr.clas.push([attr[0], sAttrClass])
|
|
81
|
+
} else if (attr[0].startsWith('data-') || /^(?:pre-)?start$/.test(attr[0])) {
|
|
82
|
+
if (/^(?:(?:data-)?pre-)?start$/.test(attr[0])) {
|
|
83
|
+
hasPreLineStart = true
|
|
84
|
+
preLineStart = attr[1]
|
|
85
|
+
attr[0] = 'data-pre-start'
|
|
86
|
+
}
|
|
87
|
+
sAttr.data.push(attr)
|
|
88
|
+
} else if (attr[0] === 'style') {
|
|
89
|
+
sAttr.style.push(attr)
|
|
90
|
+
} else {
|
|
91
|
+
sAttr.other.push(attr)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (sAttr.clas.length === 0 && langClass !== '') sAttr.clas.push(['class', langClass])
|
|
96
|
+
if (hasPreLineStart && preLineStart !== -1) {
|
|
97
|
+
if (sAttr.style.length === 0) {
|
|
98
|
+
sAttr.style.push(['style', 'counter-set:pre-line-number ' + preLineStart + ';'])
|
|
99
|
+
} else {
|
|
100
|
+
sAttr.style[0][1] = sAttr.style[0][1].replace(/;?$/, '; counter-set:pre-line-number ' + preLineStart + ';')
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//console.log(JSON.stringify(sAttr))
|
|
104
|
+
|
|
105
|
+
if (opt.setHighlight && md.options.highlight) {
|
|
106
|
+
if (lang && lang !== 'samp' ) {
|
|
107
|
+
content = md.options.highlight(token.content, lang)
|
|
84
108
|
} else {
|
|
85
109
|
content = md.utils.escapeHtml(token.content)
|
|
86
110
|
}
|
|
87
111
|
} else {
|
|
88
112
|
content = md.utils.escapeHtml(token.content)
|
|
89
113
|
}
|
|
90
|
-
if (opt.setLineNumber) {
|
|
114
|
+
if (opt.setLineNumber && hasPreLineStart) {
|
|
91
115
|
content = splitFenceBlockToLines(token, content)
|
|
92
116
|
}
|
|
93
117
|
|
|
94
118
|
let fenceHtml = '<pre>'
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
fenceHtml += fenceStartTag(token, 'samp', opt);
|
|
119
|
+
let isSamp = /^(?:samp|shell|console)$/.test(lang)
|
|
120
|
+
if (isSamp) {
|
|
121
|
+
fenceHtml += fenceStartTag('samp', sAttr)
|
|
99
122
|
} else {
|
|
100
|
-
fenceHtml += fenceStartTag(
|
|
123
|
+
fenceHtml += fenceStartTag('code', sAttr)
|
|
101
124
|
}
|
|
102
125
|
fenceHtml += content
|
|
103
|
-
if (
|
|
104
|
-
fenceHtml += '</samp>'
|
|
105
|
-
} else if (token.info === 'shell' || token.info === 'console') {
|
|
126
|
+
if (isSamp) {
|
|
106
127
|
fenceHtml += '</samp>'
|
|
107
128
|
} else {
|
|
108
129
|
fenceHtml += '</code>'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peaceroad/markdown-it-renderer-fence",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.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
6
|
"type": "module",
|
|
@@ -105,3 +105,61 @@ $ pwd
|
|
|
105
105
|
/home/User
|
|
106
106
|
</samp></pre>
|
|
107
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">'A test.'</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">'A test.'</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">'A test.'</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">'A test.'</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">'A test.'</span>)
|
|
165
|
+
</code></pre>
|
package/test/examples.txt
CHANGED
|
@@ -41,3 +41,90 @@ $ pwd
|
|
|
41
41
|
/home/User
|
|
42
42
|
</samp></pre>
|
|
43
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
CHANGED
|
@@ -5,13 +5,13 @@ import mdit from 'markdown-it'
|
|
|
5
5
|
|
|
6
6
|
import mditFigureWithPCaption from '@peaceroad/markdown-it-figure-with-p-caption'
|
|
7
7
|
import mditRendererFence from '../index.js'
|
|
8
|
-
import
|
|
8
|
+
import mditAttrs from 'markdown-it-attrs'
|
|
9
9
|
import highlightjs from 'highlight.js'
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
let opt = {}
|
|
13
13
|
|
|
14
|
-
const md = mdit({ html: true }).use(mditRendererFence).use(
|
|
14
|
+
const md = mdit({ html: true }).use(mditRendererFence).use(mditAttrs)
|
|
15
15
|
const mdHighlightJs = mdit({
|
|
16
16
|
html: true,
|
|
17
17
|
langPrefix: 'language-',
|
|
@@ -24,7 +24,7 @@ const mdHighlightJs = mdit({
|
|
|
24
24
|
}
|
|
25
25
|
return ''
|
|
26
26
|
}
|
|
27
|
-
}).use(mditRendererFence, opt).use(
|
|
27
|
+
}).use(mditRendererFence, opt).use(mditAttrs)
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
let __dirname = path.dirname(new URL(import.meta.url).pathname)
|