markdown-it-admon-collapsible 1.9.1 → 1.9.3

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,232 +1,231 @@
1
- /*
2
- const ADMONITION_TAGS = [
3
- 'note',
4
- 'summary', 'abstract', 'tldr',
5
- 'info', 'todo',
6
- 'tip', 'hint',
7
- 'success', 'check', 'done',
8
- 'question', 'help', 'faq',
9
- 'warning', 'attention', 'caution',
10
- 'failure', 'fail', 'missing',
11
- 'danger', 'error', 'bug',
12
- 'example', 'snippet',
13
- 'quote', 'cite'
14
- ]
15
- */
16
-
17
- const capitalize = ([first, ...rest], lowerRest = false) =>
18
- first.toUpperCase() + rest.join('')
19
-
20
- function getTag (params) {
21
- const [tag = '', ..._title] = params.trim().split(' ')
22
-
23
- /* c8 ignore next 3 */
24
- if (!tag) {
25
- return {}
26
- }
27
-
28
- const joined = _title.join(' ');
29
- let title;
30
- if (!joined) {
31
- title = capitalize(tag);
32
- } else if (joined === '""') {
33
- title = '';
34
- } else if ((joined.startsWith('"') && joined.endsWith('"')) || (joined.startsWith("'") && joined.endsWith("'"))) {
35
- title = joined.slice(1, -1);
36
- } else {
37
- title = joined;
38
- }
39
- return { tag: tag.toLowerCase(), title };
40
- }
41
-
42
- function validate (params) {
43
- const [tag = ''] = params.trim().split(' ', 1)
44
- return !!tag
45
- }
46
-
47
-
48
- function renderDefault(tokens, idx, _options, env, slf) {
49
- return slf.renderToken(tokens, idx, _options, env, slf);
50
- }
51
-
52
- function renderCollapsibleOpen(tokens, idx) {
53
- const token = tokens[idx];
54
- const classes = token.attrs ? token.attrs.find(a => a[0] === 'class')[1] : '';
55
- return `<div class="${classes}">\n`;
56
- }
57
-
58
- function renderCollapsibleTitleOpen(tokens, idx) {
59
- const expanded = tokens[idx - 1]?.meta?.expanded;
60
- // Add toggle button
61
- return `<p class="admonition-title"><button class="collapsible-toggle" tabindex="0">${expanded ? '&#x2212;' : '&#x2b;'}</button>`;
62
- }
63
-
64
- function renderCollapsibleTitleClose() {
65
- return '</p>\n';
66
- }
67
-
68
- function renderCollapsibleContentOpen(tokens, idx) {
69
- return '<div class="collapsible-content">\n';
70
- }
71
-
72
- function renderCollapsibleContentClose() {
73
- return '</div>\n';
74
- }
75
-
76
-
77
- const minMarkers = 3;
78
- const markerTypes = [
79
- { str: '!', type: 'admonition' },
80
- { str: '?', type: 'collapsible' }
81
- ];
82
-
83
-
84
- function admonition(state, startLine, endLine, silent) {
85
- let pos, nextLine, token;
86
- const start = state.bMarks[startLine] + state.tShift[startLine];
87
- let max = state.eMarks[startLine];
88
-
89
- // Determine marker type
90
- let markerType = null;
91
- for (const type of markerTypes) {
92
- if (state.src.substr(start, type.str.length) === type.str.repeat(type.str.length)) {
93
- markerType = type;
94
- break;
95
- }
96
- }
97
- if (!markerType) return false;
98
-
99
- const markerStr = markerType.str;
100
- const markerLen = markerStr.length;
101
-
102
- // Check out the rest of the marker string
103
- for (pos = start + 1; pos <= max; pos++) {
104
- if (markerStr[(pos - start) % markerLen] !== state.src[pos]) {
105
- break;
106
- }
107
- }
108
-
109
- const markerCount = Math.floor((pos - start) / markerLen);
110
- if (markerCount < minMarkers) return false;
111
- const markerPos = pos - ((pos - start) % markerLen);
112
- let params = state.src.slice(markerPos, max);
113
- let markup = state.src.slice(start, markerPos);
114
-
115
- // Collapsible: check for plus sign
116
- let isCollapsible = markerType.type === 'collapsible';
117
- let expanded = false;
118
- if (isCollapsible && params.trim().startsWith('+')) {
119
- expanded = true;
120
- params = params.trim().slice(1).trim();
121
- markup += '+';
122
- }
123
-
124
- if (!validate(params)) return false;
125
- if (silent) return true;
126
-
127
- const oldParent = state.parentType;
128
- const oldLineMax = state.lineMax;
129
- const oldIndent = state.blkIndent;
130
-
131
- let blkStart = pos;
132
- for (; blkStart < max; blkStart += 1) {
133
- if (state.src[blkStart] !== ' ') break;
134
- }
135
- state.parentType = 'admonition';
136
- state.blkIndent += blkStart - start;
137
-
138
- let wasEmpty = false;
139
- nextLine = startLine;
140
- for (;;) {
141
- nextLine++;
142
- if (nextLine >= endLine) break;
143
- pos = state.bMarks[nextLine] + state.tShift[nextLine];
144
- max = state.eMarks[nextLine];
145
- const isEmpty = state.sCount[nextLine] < state.blkIndent;
146
- if (isEmpty && wasEmpty) break;
147
- wasEmpty = isEmpty;
148
- if (pos < max && state.sCount[nextLine] < state.blkIndent) break;
149
- }
150
- state.lineMax = nextLine;
151
-
152
- const { tag, title } = getTag(params);
153
-
154
- // Use different token for collapsible
155
- const openType = isCollapsible ? 'collapsible_open' : 'admonition_open';
156
- const closeType = isCollapsible ? 'collapsible_close' : 'admonition_close';
157
-
158
- token = state.push(openType, 'div', 1);
159
- token.markup = markup;
160
- token.block = true;
161
- token.attrs = [['class', `admonition ${tag}${isCollapsible ? ' collapsible' : ''}${expanded ? ' expanded' : ''}`]];
162
- token.meta = { tag, expanded };
163
- token.content = title;
164
- token.info = params;
165
- token.map = [startLine, nextLine];
166
-
167
- if (title) {
168
- const titleMarkup = markup + ' ' + tag;
169
- token = state.push(isCollapsible ? 'collapsible_title_open' : 'admonition_title_open', 'p', 1);
170
- token.markup = titleMarkup;
171
- token.attrs = [['class', 'admonition-title']];
172
- token.map = [startLine, startLine + 1];
173
-
174
- token = state.push('inline', '', 0);
175
- token.content = title;
176
- token.map = [startLine, startLine + 1];
177
- token.children = [];
178
-
179
- token = state.push(isCollapsible ? 'collapsible_title_close' : 'admonition_title_close', 'p', -1);
180
- token.markup = titleMarkup;
181
- }
182
-
183
- state.md.block.tokenize(state, startLine + 1, nextLine);
184
-
185
- token = state.push(closeType, 'div', -1);
186
- token.markup = state.src.slice(start, pos);
187
- token.block = true;
188
-
189
- state.parentType = oldParent;
190
- state.lineMax = oldLineMax;
191
- state.blkIndent = oldIndent;
192
- state.line = nextLine;
193
-
194
- return true;
195
- }
196
-
197
- module.exports = function admonitionPlugin(md, options = {}) {
198
- const render = options.render || renderDefault;
199
-
200
- md.renderer.rules.admonition_open = render;
201
- md.renderer.rules.admonition_close = render;
202
- md.renderer.rules.admonition_title_open = render;
203
- md.renderer.rules.admonition_title_close = render;
204
-
205
- // Collapsible rendering
206
- md.renderer.rules.collapsible_open = renderCollapsibleOpen;
207
- md.renderer.rules.collapsible_close = (tokens, idx) => '</div>';
208
- md.renderer.rules.collapsible_close = (tokens, idx) => '</div>\n';
209
- md.renderer.rules.collapsible_title_open = renderCollapsibleTitleOpen;
210
- md.renderer.rules.collapsible_title_close = renderCollapsibleTitleClose;
211
-
212
- // Wrap content in collapsible-content div
213
- const origBlockTokenize = md.block.tokenize;
214
- md.block.tokenize = function(state, startLine, endLine) {
215
- if (state.parentType === 'admonition' && state.tokens.length > 0) {
216
- const lastToken = state.tokens[state.tokens.length - 1];
217
- if (lastToken.type === 'collapsible_title_close') {
218
- state.tokens.push({ type: 'collapsible_content_open' });
219
- origBlockTokenize.call(this, state, startLine, endLine);
220
- state.tokens.push({ type: 'collapsible_content_close' });
221
- return;
222
- }
223
- }
224
- origBlockTokenize.call(this, state, startLine, endLine);
225
- };
226
- md.renderer.rules.collapsible_content_open = renderCollapsibleContentOpen;
227
- md.renderer.rules.collapsible_content_close = renderCollapsibleContentClose;
228
-
229
- md.block.ruler.before('fence', 'admonition', admonition, {
230
- alt: ['paragraph', 'reference', 'blockquote', 'list']
231
- });
232
- }
1
+ /*
2
+ const ADMONITION_TAGS = [
3
+ 'note',
4
+ 'summary', 'abstract', 'tldr',
5
+ 'info', 'todo',
6
+ 'tip', 'hint',
7
+ 'success', 'check', 'done',
8
+ 'question', 'help', 'faq',
9
+ 'warning', 'attention', 'caution',
10
+ 'failure', 'fail', 'missing',
11
+ 'danger', 'error', 'bug',
12
+ 'example', 'snippet',
13
+ 'quote', 'cite'
14
+ ]
15
+ */
16
+
17
+ const capitalize = ([first, ...rest], lowerRest = false) =>
18
+ first.toUpperCase() + rest.join('')
19
+
20
+ function getTag (params) {
21
+ const [tag = '', ..._title] = params.trim().split(' ')
22
+
23
+ /* c8 ignore next 3 */
24
+ if (!tag) {
25
+ return {}
26
+ }
27
+
28
+ const joined = _title.join(' ');
29
+ let title;
30
+ if (!joined) {
31
+ title = capitalize(tag);
32
+ } else if (joined === '""') {
33
+ title = '';
34
+ } else if ((joined.startsWith('"') && joined.endsWith('"')) || (joined.startsWith("'") && joined.endsWith("'"))) {
35
+ title = joined.slice(1, -1);
36
+ } else {
37
+ title = joined;
38
+ }
39
+ return { tag: tag.toLowerCase(), title };
40
+ }
41
+
42
+ function validate (params) {
43
+ const [tag = ''] = params.trim().split(' ', 1)
44
+ return !!tag
45
+ }
46
+
47
+
48
+ function renderDefault(tokens, idx, _options, env, slf) {
49
+ return slf.renderToken(tokens, idx, _options, env, slf);
50
+ }
51
+
52
+ function renderCollapsibleOpen(tokens, idx) {
53
+ const token = tokens[idx];
54
+ const classes = token.attrs ? token.attrs.find(a => a[0] === 'class')[1] : '';
55
+ return `<div class="${classes}">\n`;
56
+ }
57
+
58
+ function renderCollapsibleTitleOpen(tokens, idx) {
59
+ const expanded = tokens[idx - 1]?.meta?.expanded;
60
+ // Add toggle button
61
+ return `<div class="admonition-title"><button class="collapsible-toggle" tabindex="0">${expanded ? '&#x2212;' : '&#x2b;'}</button>`;
62
+ }
63
+
64
+ function renderCollapsibleTitleClose() {
65
+ return '</div>\n';
66
+ }
67
+
68
+ function renderCollapsibleContentOpen(tokens, idx) {
69
+ return '';
70
+ }
71
+
72
+ function renderCollapsibleContentClose() {
73
+ return '';
74
+ }
75
+
76
+
77
+ const minMarkers = 3;
78
+ const markerTypes = [
79
+ { str: '!', type: 'admonition' },
80
+ { str: '?', type: 'collapsible' }
81
+ ];
82
+
83
+
84
+ function admonition(state, startLine, endLine, silent) {
85
+ let pos, nextLine, token;
86
+ const start = state.bMarks[startLine] + state.tShift[startLine];
87
+ let max = state.eMarks[startLine];
88
+
89
+ // Determine marker type
90
+ let markerType = null;
91
+ for (const type of markerTypes) {
92
+ if (state.src.substr(start, type.str.length) === type.str.repeat(type.str.length)) {
93
+ markerType = type;
94
+ break;
95
+ }
96
+ }
97
+ if (!markerType) return false;
98
+
99
+ const markerStr = markerType.str;
100
+ const markerLen = markerStr.length;
101
+
102
+ // Check out the rest of the marker string
103
+ for (pos = start + 1; pos <= max; pos++) {
104
+ if (markerStr[(pos - start) % markerLen] !== state.src[pos]) {
105
+ break;
106
+ }
107
+ }
108
+
109
+ const markerCount = Math.floor((pos - start) / markerLen);
110
+ if (markerCount < minMarkers) return false;
111
+ const markerPos = pos - ((pos - start) % markerLen);
112
+ let params = state.src.slice(markerPos, max);
113
+ let markup = state.src.slice(start, markerPos);
114
+
115
+ // Collapsible: check for plus sign
116
+ let isCollapsible = markerType.type === 'collapsible';
117
+ let expanded = false;
118
+ if (isCollapsible && params.trim().startsWith('+')) {
119
+ expanded = true;
120
+ params = params.trim().slice(1).trim();
121
+ markup += '+';
122
+ }
123
+
124
+ if (!validate(params)) return false;
125
+ if (silent) return true;
126
+
127
+ const oldParent = state.parentType;
128
+ const oldLineMax = state.lineMax;
129
+ const oldIndent = state.blkIndent;
130
+
131
+ let blkStart = pos;
132
+ for (; blkStart < max; blkStart += 1) {
133
+ if (state.src[blkStart] !== ' ') break;
134
+ }
135
+ state.parentType = 'admonition';
136
+ state.blkIndent += blkStart - start;
137
+
138
+ let wasEmpty = false;
139
+ nextLine = startLine;
140
+ for (;;) {
141
+ nextLine++;
142
+ if (nextLine >= endLine) break;
143
+ pos = state.bMarks[nextLine] + state.tShift[nextLine];
144
+ max = state.eMarks[nextLine];
145
+ const isEmpty = state.sCount[nextLine] < state.blkIndent;
146
+ if (isEmpty && wasEmpty) break;
147
+ wasEmpty = isEmpty;
148
+ if (pos < max && state.sCount[nextLine] < state.blkIndent) break;
149
+ }
150
+ state.lineMax = nextLine;
151
+
152
+ const { tag, title } = getTag(params);
153
+
154
+ // Use different token for collapsible
155
+ const openType = isCollapsible ? 'collapsible_open' : 'admonition_open';
156
+ const closeType = isCollapsible ? 'collapsible_close' : 'admonition_close';
157
+
158
+ token = state.push(openType, 'div', 1);
159
+ token.markup = markup;
160
+ token.block = true;
161
+ token.attrs = [['class', `admonition ${tag}${isCollapsible ? ' collapsible' : ''}${expanded ? ' expanded' : ''}`]];
162
+ token.meta = { tag, expanded };
163
+ token.content = title;
164
+ token.info = params;
165
+ token.map = [startLine, nextLine];
166
+
167
+ if (title) {
168
+ const titleMarkup = markup + ' ' + tag;
169
+ token = state.push(isCollapsible ? 'collapsible_title_open' : 'admonition_title_open', 'div', 1);
170
+ token.markup = titleMarkup;
171
+ token.attrs = [['class', 'admonition-title']];
172
+ token.map = [startLine, startLine + 1];
173
+
174
+ token = state.push('inline', '', 0);
175
+ token.content = title;
176
+ token.map = [startLine, startLine + 1];
177
+ token.children = [];
178
+
179
+ token = state.push(isCollapsible ? 'collapsible_title_close' : 'admonition_title_close', 'div', -1);
180
+ token.markup = titleMarkup;
181
+ }
182
+
183
+ state.md.block.tokenize(state, startLine + 1, nextLine);
184
+
185
+ token = state.push(closeType, 'div', -1);
186
+ token.markup = state.src.slice(start, pos);
187
+ token.block = true;
188
+
189
+ state.parentType = oldParent;
190
+ state.lineMax = oldLineMax;
191
+ state.blkIndent = oldIndent;
192
+ state.line = nextLine;
193
+
194
+ return true;
195
+ }
196
+
197
+ module.exports = function admonitionPlugin(md, options = {}) {
198
+ const render = options.render || renderDefault;
199
+
200
+ md.renderer.rules.admonition_open = render;
201
+ md.renderer.rules.admonition_close = render;
202
+ md.renderer.rules.admonition_title_open = render;
203
+ md.renderer.rules.admonition_title_close = render;
204
+
205
+ // Collapsible rendering
206
+ md.renderer.rules.collapsible_open = renderCollapsibleOpen;
207
+ md.renderer.rules.collapsible_close = (tokens, idx) => '</div>\n';
208
+ md.renderer.rules.collapsible_title_open = renderCollapsibleTitleOpen;
209
+ md.renderer.rules.collapsible_title_close = renderCollapsibleTitleClose;
210
+
211
+ // Wrap content in collapsible-content div
212
+ const origBlockTokenize = md.block.tokenize;
213
+ md.block.tokenize = function(state, startLine, endLine) {
214
+ if (state.parentType === 'admonition' && state.tokens.length > 0) {
215
+ const lastToken = state.tokens[state.tokens.length - 1];
216
+ if (lastToken.type === 'collapsible_title_close') {
217
+ state.tokens.push({ type: 'collapsible_content_open' });
218
+ origBlockTokenize.call(this, state, startLine, endLine);
219
+ state.tokens.push({ type: 'collapsible_content_close' });
220
+ return;
221
+ }
222
+ }
223
+ origBlockTokenize.call(this, state, startLine, endLine);
224
+ };
225
+ md.renderer.rules.collapsible_content_open = renderCollapsibleContentOpen;
226
+ md.renderer.rules.collapsible_content_close = renderCollapsibleContentClose;
227
+
228
+ md.block.ruler.before('fence', 'admonition', admonition, {
229
+ alt: ['paragraph', 'reference', 'blockquote', 'list']
230
+ });
231
+ }
package/package.json CHANGED
@@ -1,58 +1,58 @@
1
- {
2
- "name": "markdown-it-admon-collapsible",
3
- "version": "1.9.1",
4
- "description": "Plugin to create admonitions for markdown-it markdown parser",
5
- "keywords": [
6
- "admonition",
7
- "markdown-it-plugin",
8
- "markdown-it",
9
- "markdown"
10
- ],
11
- "homepage": "https://github.com/tomasdahlqvist/markdown-it-admon-collapsible#readme",
12
- "bugs": {
13
- "url": "https://github.com/tomasdahlqvist/markdown-it-admon-collapsible/issues"
14
- },
15
- "repository": {
16
- "type": "git",
17
- "url": "git+https://github.com/tomasdahlqvist/markdown-it-admon-collapsible.git"
18
- },
19
- "license": "MIT",
20
- "author": "",
21
- "maintainers": [
22
- "tomasdahlqvist"
23
- ],
24
- "main": "index.js",
25
- "directories": {
26
- "doc": "docs",
27
- "example": "example",
28
- "test": "test"
29
- },
30
- "files": [
31
- "CHANGELOG.md",
32
- "docs/",
33
- "dist/",
34
- "index.js",
35
- "styles/"
36
- ],
37
- "scripts": {
38
- "clean": "git clean -fXd -e \\!node_modules -e \\!node_modules/**/*",
39
- "coverage": "npm run test && c8 report --reporter html",
40
- "lint": "eslint --fix .",
41
- "test": "c8 mocha",
42
- "build": "mkdir -p dist && node_modules/.bin/browserify ./ -s markdownitAdmonCollapsible > dist/markdown-it-admon-collapsible.js && terser dist/markdown-it-admon-collapsible.js -c -m > dist/markdown-it-admon-collapsible.min.js"
43
- },
44
- "devDependencies": {
45
- "browserify": "^17.0.0",
46
- "c8": "^10.1.3",
47
- "eslint": "^8.56.0",
48
- "eslint-config-standard": "^17.1.0",
49
- "eslint-plugin-import": "^2.29.1",
50
- "eslint-plugin-node": "^11.1.0",
51
- "eslint-plugin-promise": "^6.1.1",
52
- "markdown-it": "^14.0.0",
53
- "markdown-it-testgen": "~0.1.6",
54
- "mocha": "^11.7.5",
55
- "rimraf": "^6.1.2",
56
- "terser": "^5.26.0"
57
- }
58
- }
1
+ {
2
+ "name": "markdown-it-admon-collapsible",
3
+ "version": "1.9.3",
4
+ "description": "Plugin to create admonitions for markdown-it markdown parser",
5
+ "keywords": [
6
+ "admonition",
7
+ "markdown-it-plugin",
8
+ "markdown-it",
9
+ "markdown"
10
+ ],
11
+ "homepage": "https://github.com/tomasdahlqvist/markdown-it-admon-collapsible#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/tomasdahlqvist/markdown-it-admon-collapsible/issues"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/tomasdahlqvist/markdown-it-admon-collapsible.git"
18
+ },
19
+ "license": "MIT",
20
+ "author": "",
21
+ "maintainers": [
22
+ "tomasdahlqvist"
23
+ ],
24
+ "main": "index.js",
25
+ "directories": {
26
+ "doc": "docs",
27
+ "example": "example",
28
+ "test": "test"
29
+ },
30
+ "files": [
31
+ "CHANGELOG.md",
32
+ "docs/",
33
+ "dist/",
34
+ "index.js",
35
+ "styles/"
36
+ ],
37
+ "scripts": {
38
+ "clean": "git clean -fXd -e \\!node_modules -e \\!node_modules/**/*",
39
+ "coverage": "npm run test && c8 report --reporter html",
40
+ "lint": "eslint --fix .",
41
+ "test": "c8 mocha",
42
+ "build": "mkdir -p dist && node_modules/.bin/browserify ./ -s markdownitAdmonCollapsible > dist/markdown-it-admon-collapsible.js && terser dist/markdown-it-admon-collapsible.js -c -m > dist/markdown-it-admon-collapsible.min.js"
43
+ },
44
+ "devDependencies": {
45
+ "browserify": "^17.0.0",
46
+ "c8": "^10.1.3",
47
+ "eslint": "^8.56.0",
48
+ "eslint-config-standard": "^17.1.0",
49
+ "eslint-plugin-import": "^2.29.1",
50
+ "eslint-plugin-node": "^11.1.0",
51
+ "eslint-plugin-promise": "^6.1.1",
52
+ "markdown-it": "^14.0.0",
53
+ "markdown-it-testgen": "~0.1.6",
54
+ "mocha": "^11.7.5",
55
+ "rimraf": "^6.1.2",
56
+ "terser": "^5.26.0"
57
+ }
58
+ }