@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 CHANGED
@@ -1,56 +1,16 @@
1
- const fenceStartTag = (token, tagName, opt) => {
2
- let idAttr = [], classAttr = [], dataAttrs = [], styleAttr = [], otherAttrs = []
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
- if (md.options.highlight) {
82
- if (token.info !== 'samp' && opt.setHighlight) {
83
- content = md.options.highlight(token.content, token.info)
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
- if (token.info === 'samp') {
96
- fenceHtml += '<samp>'
97
- } else if (token.info === 'shell' || token.info === 'console') {
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(token, 'code', opt);
123
+ fenceHtml += fenceStartTag('code', sAttr)
101
124
  }
102
125
  fenceHtml += content
103
- if (token.info === 'samp') {
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.0",
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">&#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>
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 attrs from 'markdown-it-attrs'
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(attrs)
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(attrs)
27
+ }).use(mditRendererFence, opt).use(mditAttrs)
28
28
 
29
29
 
30
30
  let __dirname = path.dirname(new URL(import.meta.url).pathname)