@subiz/widget-v4 4.1.28 → 4.1.29

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.
Files changed (101) hide show
  1. package/compiled_src/chatbox/GenericTemplateAttachments.js +5 -1
  2. package/compiled_src/chatbox/ProductAttachments.js +7 -2
  3. package/compiled_src/util/campaign.js +6 -2
  4. package/compiled_src/util/common.js +667 -4
  5. package/compiled_src/util/order.js +4 -2
  6. package/compiled_src/util/pubsub.js +6 -3
  7. package/package.json +1 -1
  8. package/src/chatbox/GenericTemplateAttachments.js +5 -5
  9. package/src/chatbox/ProductAttachments.js +7 -6
  10. package/src/util/common.js +198 -3
  11. package/dist/132.js +0 -6639
  12. package/dist/178.js +0 -406
  13. package/dist/18754d60df1.132.js +0 -1
  14. package/dist/18754d60df1.178.js +0 -1
  15. package/dist/18754d60df1.213.js +0 -1
  16. package/dist/18754d60df1.335.js +0 -1
  17. package/dist/18754d60df1.362.js +0 -1
  18. package/dist/18754d60df1.441.js +0 -1
  19. package/dist/18754d60df1.605.js +0 -1
  20. package/dist/18754d60df1.678.js +0 -1
  21. package/dist/18754d60df1.782.js +0 -1
  22. package/dist/18754d60df1.app.js +0 -1
  23. package/dist/18754d60df1.index.html +0 -33
  24. package/dist/18754d60df1.library.html +0 -33
  25. package/dist/18754d60df1.library.js +0 -1
  26. package/dist/18754d60df1.preview.html +0 -759
  27. package/dist/18754d60df1.preview.js +0 -1
  28. package/dist/18754d60df1.screenshoot.js +0 -1
  29. package/dist/18754d60df1.webview.js +0 -1
  30. package/dist/213.js +0 -2780
  31. package/dist/335.js +0 -372
  32. package/dist/362.js +0 -107
  33. package/dist/441.js +0 -2919
  34. package/dist/605.js +0 -305
  35. package/dist/678.js +0 -107
  36. package/dist/782.js +0 -107
  37. package/dist/HASH +0 -1
  38. package/dist/assets/img/Facebook.64607ec.png +0 -0
  39. package/dist/assets/img/Zalo.6845707.png +0 -0
  40. package/dist/assets/img/award1a.1a58e10.png +0 -0
  41. package/dist/assets/img/award3a.3b74423.png +0 -0
  42. package/dist/assets/img/award4a.ed6ccd4.png +0 -0
  43. package/dist/assets/img/award5.39eb7ae.png +0 -0
  44. package/dist/assets/img/bubble_default.7d5e4ab.svg +0 -20
  45. package/dist/assets/img/caret.998eb8f.svg +0 -1
  46. package/dist/assets/img/convos_empty.2353007.svg +0 -72
  47. package/dist/assets/img/default.06e6ee0.jpg +0 -0
  48. package/dist/assets/img/default_avatar.5b74dc1.png +0 -0
  49. package/dist/assets/img/done_gray.d7e8203.svg +0 -4
  50. package/dist/assets/img/done_green.b817fd4.svg +0 -4
  51. package/dist/assets/img/emoji/messenger/sub_23.529_58.824.d5faf14.png +0 -0
  52. package/dist/assets/img/emoji/messenger/sub_23.529_60.784.1420241.png +0 -0
  53. package/dist/assets/img/emoji/messenger/sub_25.490_0.000.1e6b2c0.png +0 -0
  54. package/dist/assets/img/emoji/messenger/sub_25.490_45.098.3dfbc08.png +0 -0
  55. package/dist/assets/img/emoji/messenger/sub_25.490_5.882.4b49e94.png +0 -0
  56. package/dist/assets/img/emoji/messenger/sub_27.451_72.549.7114f58.png +0 -0
  57. package/dist/assets/img/emoji/messenger/sub_27.451_84.314.231e2b7.png +0 -0
  58. package/dist/assets/img/emoji/messenger/sub_27.451_96.078.ddbb008.png +0 -0
  59. package/dist/assets/img/emoji/messenger/sub_29.412_5.882.61f3359.png +0 -0
  60. package/dist/assets/img/emoji/messenger/sub_58.824_100.000.6df72bc.png +0 -0
  61. package/dist/assets/img/emoji/messenger/sub_58.824_45.098.3d7a7ad.png +0 -0
  62. package/dist/assets/img/emoji/messenger/sub_58.824_47.059.0f4d6e2.png +0 -0
  63. package/dist/assets/img/emoji/messenger/sub_58.824_54.902.65724c1.png +0 -0
  64. package/dist/assets/img/emoji/messenger/sub_58.824_64.706.9da3cba.png +0 -0
  65. package/dist/assets/img/emoji/messenger/sub_58.824_72.549.edca5cf.png +0 -0
  66. package/dist/assets/img/emoji/messenger/sub_58.824_78.431.f910f2a.png +0 -0
  67. package/dist/assets/img/emoji/messenger/sub_58.824_88.235.def4e71.png +0 -0
  68. package/dist/assets/img/emoji/messenger/sub_60.784_11.765.49c03d0.png +0 -0
  69. package/dist/assets/img/emoji/messenger/sub_60.784_27.451.46b54e5.png +0 -0
  70. package/dist/assets/img/emoji/messenger/sub_60.784_29.412.e36d284.png +0 -0
  71. package/dist/assets/img/emoji/messenger/sub_60.784_3.922.bb191b0.png +0 -0
  72. package/dist/assets/img/emoji/messenger/sub_60.784_35.294.af7b927.png +0 -0
  73. package/dist/assets/img/emoji/messenger/sub_60.784_7.843.98f2a99.png +0 -0
  74. package/dist/assets/img/empty.29bed2d.svg +0 -23
  75. package/dist/assets/img/empty_1.0b98af0.svg +0 -11
  76. package/dist/assets/img/examplte_logo.f86535f.svg +0 -1
  77. package/dist/assets/img/external-link.90577cc.svg +0 -1
  78. package/dist/assets/img/fb_inverse_circle.36c2cfc.png +0 -0
  79. package/dist/assets/img/ghn.070f8e3.svg +0 -17
  80. package/dist/assets/img/ghtk.326eac1.svg +0 -18
  81. package/dist/assets/img/image_default.be0698b.png +0 -0
  82. package/dist/assets/img/info.ebce7ea.svg +0 -1
  83. package/dist/assets/img/loader.37000a7.svg +0 -1
  84. package/dist/assets/img/loading_static.a27f0ac.svg +0 -10
  85. package/dist/assets/img/main-service1.d536cc2.png +0 -0
  86. package/dist/assets/img/main-service2.9b99549.png +0 -0
  87. package/dist/assets/img/not_found_search.2ddb8d1.png +0 -0
  88. package/dist/assets/img/package.8d37d0f.svg +0 -5
  89. package/dist/assets/img/package_fade.763c001.svg +0 -1
  90. package/dist/assets/img/rating--average.1ea492c.svg +0 -12
  91. package/dist/assets/img/rating--great.e3d712e.svg +0 -16
  92. package/dist/assets/img/rating--poor.2938a25.svg +0 -12
  93. package/dist/assets/img/search.f9705ff.svg +0 -1
  94. package/dist/assets/img/send.6db52a9.svg +0 -3
  95. package/dist/assets/img/shop.f7dc7d8.svg +0 -1
  96. package/dist/assets/img/shop_faded.df7845a.svg +0 -1
  97. package/dist/assets/img/subiz-mono.877e9f5.svg +0 -3
  98. package/dist/assets/img/x.26fdfa3.svg +0 -5
  99. package/dist/malicious-app.js +0 -13
  100. package/dist/screenshoot.html +0 -7
  101. package/dist/screenshoot.js +0 -5677
package/dist/441.js DELETED
@@ -1,2919 +0,0 @@
1
- "use strict";
2
- (self["webpackChunk_subiz_widget_v4"] = self["webpackChunk_subiz_widget_v4"] || []).push([[441],{
3
-
4
- /***/ 7441:
5
- /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
6
-
7
- __webpack_require__.r(__webpack_exports__);
8
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
9
- /* harmony export */ "Hooks": () => (/* binding */ Hooks),
10
- /* harmony export */ "Lexer": () => (/* binding */ Lexer),
11
- /* harmony export */ "Parser": () => (/* binding */ Parser),
12
- /* harmony export */ "Renderer": () => (/* binding */ Renderer),
13
- /* harmony export */ "Slugger": () => (/* binding */ Slugger),
14
- /* harmony export */ "TextRenderer": () => (/* binding */ TextRenderer),
15
- /* harmony export */ "Tokenizer": () => (/* binding */ Tokenizer),
16
- /* harmony export */ "defaults": () => (/* binding */ defaults),
17
- /* harmony export */ "getDefaults": () => (/* binding */ getDefaults),
18
- /* harmony export */ "lexer": () => (/* binding */ lexer),
19
- /* harmony export */ "marked": () => (/* binding */ marked),
20
- /* harmony export */ "options": () => (/* binding */ options),
21
- /* harmony export */ "parse": () => (/* binding */ parse),
22
- /* harmony export */ "parseInline": () => (/* binding */ parseInline),
23
- /* harmony export */ "parser": () => (/* binding */ parser),
24
- /* harmony export */ "setOptions": () => (/* binding */ setOptions),
25
- /* harmony export */ "use": () => (/* binding */ use),
26
- /* harmony export */ "walkTokens": () => (/* binding */ walkTokens)
27
- /* harmony export */ });
28
- /**
29
- * marked v4.3.0 - a markdown parser
30
- * Copyright (c) 2011-2023, Christopher Jeffrey. (MIT Licensed)
31
- * https://github.com/markedjs/marked
32
- */
33
-
34
- /**
35
- * DO NOT EDIT THIS FILE
36
- * The code in this file is generated from files in ./src/
37
- */
38
-
39
- function getDefaults() {
40
- return {
41
- async: false,
42
- baseUrl: null,
43
- breaks: false,
44
- extensions: null,
45
- gfm: true,
46
- headerIds: true,
47
- headerPrefix: '',
48
- highlight: null,
49
- hooks: null,
50
- langPrefix: 'language-',
51
- mangle: true,
52
- pedantic: false,
53
- renderer: null,
54
- sanitize: false,
55
- sanitizer: null,
56
- silent: false,
57
- smartypants: false,
58
- tokenizer: null,
59
- walkTokens: null,
60
- xhtml: false
61
- };
62
- }
63
-
64
- let defaults = getDefaults();
65
-
66
- function changeDefaults(newDefaults) {
67
- defaults = newDefaults;
68
- }
69
-
70
- /**
71
- * Helpers
72
- */
73
- const escapeTest = /[&<>"']/;
74
- const escapeReplace = new RegExp(escapeTest.source, 'g');
75
- const escapeTestNoEncode = /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/;
76
- const escapeReplaceNoEncode = new RegExp(escapeTestNoEncode.source, 'g');
77
- const escapeReplacements = {
78
- '&': '&amp;',
79
- '<': '&lt;',
80
- '>': '&gt;',
81
- '"': '&quot;',
82
- "'": '&#39;'
83
- };
84
- const getEscapeReplacement = (ch) => escapeReplacements[ch];
85
- function escape(html, encode) {
86
- if (encode) {
87
- if (escapeTest.test(html)) {
88
- return html.replace(escapeReplace, getEscapeReplacement);
89
- }
90
- } else {
91
- if (escapeTestNoEncode.test(html)) {
92
- return html.replace(escapeReplaceNoEncode, getEscapeReplacement);
93
- }
94
- }
95
-
96
- return html;
97
- }
98
-
99
- const unescapeTest = /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig;
100
-
101
- /**
102
- * @param {string} html
103
- */
104
- function unescape(html) {
105
- // explicitly match decimal, hex, and named HTML entities
106
- return html.replace(unescapeTest, (_, n) => {
107
- n = n.toLowerCase();
108
- if (n === 'colon') return ':';
109
- if (n.charAt(0) === '#') {
110
- return n.charAt(1) === 'x'
111
- ? String.fromCharCode(parseInt(n.substring(2), 16))
112
- : String.fromCharCode(+n.substring(1));
113
- }
114
- return '';
115
- });
116
- }
117
-
118
- const caret = /(^|[^\[])\^/g;
119
-
120
- /**
121
- * @param {string | RegExp} regex
122
- * @param {string} opt
123
- */
124
- function edit(regex, opt) {
125
- regex = typeof regex === 'string' ? regex : regex.source;
126
- opt = opt || '';
127
- const obj = {
128
- replace: (name, val) => {
129
- val = val.source || val;
130
- val = val.replace(caret, '$1');
131
- regex = regex.replace(name, val);
132
- return obj;
133
- },
134
- getRegex: () => {
135
- return new RegExp(regex, opt);
136
- }
137
- };
138
- return obj;
139
- }
140
-
141
- const nonWordAndColonTest = /[^\w:]/g;
142
- const originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;
143
-
144
- /**
145
- * @param {boolean} sanitize
146
- * @param {string} base
147
- * @param {string} href
148
- */
149
- function cleanUrl(sanitize, base, href) {
150
- if (sanitize) {
151
- let prot;
152
- try {
153
- prot = decodeURIComponent(unescape(href))
154
- .replace(nonWordAndColonTest, '')
155
- .toLowerCase();
156
- } catch (e) {
157
- return null;
158
- }
159
- if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) {
160
- return null;
161
- }
162
- }
163
- if (base && !originIndependentUrl.test(href)) {
164
- href = resolveUrl(base, href);
165
- }
166
- try {
167
- href = encodeURI(href).replace(/%25/g, '%');
168
- } catch (e) {
169
- return null;
170
- }
171
- return href;
172
- }
173
-
174
- const baseUrls = {};
175
- const justDomain = /^[^:]+:\/*[^/]*$/;
176
- const protocol = /^([^:]+:)[\s\S]*$/;
177
- const domain = /^([^:]+:\/*[^/]*)[\s\S]*$/;
178
-
179
- /**
180
- * @param {string} base
181
- * @param {string} href
182
- */
183
- function resolveUrl(base, href) {
184
- if (!baseUrls[' ' + base]) {
185
- // we can ignore everything in base after the last slash of its path component,
186
- // but we might need to add _that_
187
- // https://tools.ietf.org/html/rfc3986#section-3
188
- if (justDomain.test(base)) {
189
- baseUrls[' ' + base] = base + '/';
190
- } else {
191
- baseUrls[' ' + base] = rtrim(base, '/', true);
192
- }
193
- }
194
- base = baseUrls[' ' + base];
195
- const relativeBase = base.indexOf(':') === -1;
196
-
197
- if (href.substring(0, 2) === '//') {
198
- if (relativeBase) {
199
- return href;
200
- }
201
- return base.replace(protocol, '$1') + href;
202
- } else if (href.charAt(0) === '/') {
203
- if (relativeBase) {
204
- return href;
205
- }
206
- return base.replace(domain, '$1') + href;
207
- } else {
208
- return base + href;
209
- }
210
- }
211
-
212
- const noopTest = { exec: function noopTest() {} };
213
-
214
- function splitCells(tableRow, count) {
215
- // ensure that every cell-delimiting pipe has a space
216
- // before it to distinguish it from an escaped pipe
217
- const row = tableRow.replace(/\|/g, (match, offset, str) => {
218
- let escaped = false,
219
- curr = offset;
220
- while (--curr >= 0 && str[curr] === '\\') escaped = !escaped;
221
- if (escaped) {
222
- // odd number of slashes means | is escaped
223
- // so we leave it alone
224
- return '|';
225
- } else {
226
- // add space before unescaped |
227
- return ' |';
228
- }
229
- }),
230
- cells = row.split(/ \|/);
231
- let i = 0;
232
-
233
- // First/last cell in a row cannot be empty if it has no leading/trailing pipe
234
- if (!cells[0].trim()) { cells.shift(); }
235
- if (cells.length > 0 && !cells[cells.length - 1].trim()) { cells.pop(); }
236
-
237
- if (cells.length > count) {
238
- cells.splice(count);
239
- } else {
240
- while (cells.length < count) cells.push('');
241
- }
242
-
243
- for (; i < cells.length; i++) {
244
- // leading or trailing whitespace is ignored per the gfm spec
245
- cells[i] = cells[i].trim().replace(/\\\|/g, '|');
246
- }
247
- return cells;
248
- }
249
-
250
- /**
251
- * Remove trailing 'c's. Equivalent to str.replace(/c*$/, '').
252
- * /c*$/ is vulnerable to REDOS.
253
- *
254
- * @param {string} str
255
- * @param {string} c
256
- * @param {boolean} invert Remove suffix of non-c chars instead. Default falsey.
257
- */
258
- function rtrim(str, c, invert) {
259
- const l = str.length;
260
- if (l === 0) {
261
- return '';
262
- }
263
-
264
- // Length of suffix matching the invert condition.
265
- let suffLen = 0;
266
-
267
- // Step left until we fail to match the invert condition.
268
- while (suffLen < l) {
269
- const currChar = str.charAt(l - suffLen - 1);
270
- if (currChar === c && !invert) {
271
- suffLen++;
272
- } else if (currChar !== c && invert) {
273
- suffLen++;
274
- } else {
275
- break;
276
- }
277
- }
278
-
279
- return str.slice(0, l - suffLen);
280
- }
281
-
282
- function findClosingBracket(str, b) {
283
- if (str.indexOf(b[1]) === -1) {
284
- return -1;
285
- }
286
- const l = str.length;
287
- let level = 0,
288
- i = 0;
289
- for (; i < l; i++) {
290
- if (str[i] === '\\') {
291
- i++;
292
- } else if (str[i] === b[0]) {
293
- level++;
294
- } else if (str[i] === b[1]) {
295
- level--;
296
- if (level < 0) {
297
- return i;
298
- }
299
- }
300
- }
301
- return -1;
302
- }
303
-
304
- function checkSanitizeDeprecation(opt) {
305
- if (opt && opt.sanitize && !opt.silent) {
306
- console.warn('marked(): sanitize and sanitizer parameters are deprecated since version 0.7.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/#/USING_ADVANCED.md#options');
307
- }
308
- }
309
-
310
- // copied from https://stackoverflow.com/a/5450113/806777
311
- /**
312
- * @param {string} pattern
313
- * @param {number} count
314
- */
315
- function repeatString(pattern, count) {
316
- if (count < 1) {
317
- return '';
318
- }
319
- let result = '';
320
- while (count > 1) {
321
- if (count & 1) {
322
- result += pattern;
323
- }
324
- count >>= 1;
325
- pattern += pattern;
326
- }
327
- return result + pattern;
328
- }
329
-
330
- function outputLink(cap, link, raw, lexer) {
331
- const href = link.href;
332
- const title = link.title ? escape(link.title) : null;
333
- const text = cap[1].replace(/\\([\[\]])/g, '$1');
334
-
335
- if (cap[0].charAt(0) !== '!') {
336
- lexer.state.inLink = true;
337
- const token = {
338
- type: 'link',
339
- raw,
340
- href,
341
- title,
342
- text,
343
- tokens: lexer.inlineTokens(text)
344
- };
345
- lexer.state.inLink = false;
346
- return token;
347
- }
348
- return {
349
- type: 'image',
350
- raw,
351
- href,
352
- title,
353
- text: escape(text)
354
- };
355
- }
356
-
357
- function indentCodeCompensation(raw, text) {
358
- const matchIndentToCode = raw.match(/^(\s+)(?:```)/);
359
-
360
- if (matchIndentToCode === null) {
361
- return text;
362
- }
363
-
364
- const indentToCode = matchIndentToCode[1];
365
-
366
- return text
367
- .split('\n')
368
- .map(node => {
369
- const matchIndentInNode = node.match(/^\s+/);
370
- if (matchIndentInNode === null) {
371
- return node;
372
- }
373
-
374
- const [indentInNode] = matchIndentInNode;
375
-
376
- if (indentInNode.length >= indentToCode.length) {
377
- return node.slice(indentToCode.length);
378
- }
379
-
380
- return node;
381
- })
382
- .join('\n');
383
- }
384
-
385
- /**
386
- * Tokenizer
387
- */
388
- class Tokenizer {
389
- constructor(options) {
390
- this.options = options || defaults;
391
- }
392
-
393
- space(src) {
394
- const cap = this.rules.block.newline.exec(src);
395
- if (cap && cap[0].length > 0) {
396
- return {
397
- type: 'space',
398
- raw: cap[0]
399
- };
400
- }
401
- }
402
-
403
- code(src) {
404
- const cap = this.rules.block.code.exec(src);
405
- if (cap) {
406
- const text = cap[0].replace(/^ {1,4}/gm, '');
407
- return {
408
- type: 'code',
409
- raw: cap[0],
410
- codeBlockStyle: 'indented',
411
- text: !this.options.pedantic
412
- ? rtrim(text, '\n')
413
- : text
414
- };
415
- }
416
- }
417
-
418
- fences(src) {
419
- const cap = this.rules.block.fences.exec(src);
420
- if (cap) {
421
- const raw = cap[0];
422
- const text = indentCodeCompensation(raw, cap[3] || '');
423
-
424
- return {
425
- type: 'code',
426
- raw,
427
- lang: cap[2] ? cap[2].trim().replace(this.rules.inline._escapes, '$1') : cap[2],
428
- text
429
- };
430
- }
431
- }
432
-
433
- heading(src) {
434
- const cap = this.rules.block.heading.exec(src);
435
- if (cap) {
436
- let text = cap[2].trim();
437
-
438
- // remove trailing #s
439
- if (/#$/.test(text)) {
440
- const trimmed = rtrim(text, '#');
441
- if (this.options.pedantic) {
442
- text = trimmed.trim();
443
- } else if (!trimmed || / $/.test(trimmed)) {
444
- // CommonMark requires space before trailing #s
445
- text = trimmed.trim();
446
- }
447
- }
448
-
449
- return {
450
- type: 'heading',
451
- raw: cap[0],
452
- depth: cap[1].length,
453
- text,
454
- tokens: this.lexer.inline(text)
455
- };
456
- }
457
- }
458
-
459
- hr(src) {
460
- const cap = this.rules.block.hr.exec(src);
461
- if (cap) {
462
- return {
463
- type: 'hr',
464
- raw: cap[0]
465
- };
466
- }
467
- }
468
-
469
- blockquote(src) {
470
- const cap = this.rules.block.blockquote.exec(src);
471
- if (cap) {
472
- const text = cap[0].replace(/^ *>[ \t]?/gm, '');
473
- const top = this.lexer.state.top;
474
- this.lexer.state.top = true;
475
- const tokens = this.lexer.blockTokens(text);
476
- this.lexer.state.top = top;
477
- return {
478
- type: 'blockquote',
479
- raw: cap[0],
480
- tokens,
481
- text
482
- };
483
- }
484
- }
485
-
486
- list(src) {
487
- let cap = this.rules.block.list.exec(src);
488
- if (cap) {
489
- let raw, istask, ischecked, indent, i, blankLine, endsWithBlankLine,
490
- line, nextLine, rawLine, itemContents, endEarly;
491
-
492
- let bull = cap[1].trim();
493
- const isordered = bull.length > 1;
494
-
495
- const list = {
496
- type: 'list',
497
- raw: '',
498
- ordered: isordered,
499
- start: isordered ? +bull.slice(0, -1) : '',
500
- loose: false,
501
- items: []
502
- };
503
-
504
- bull = isordered ? `\\d{1,9}\\${bull.slice(-1)}` : `\\${bull}`;
505
-
506
- if (this.options.pedantic) {
507
- bull = isordered ? bull : '[*+-]';
508
- }
509
-
510
- // Get next list item
511
- const itemRegex = new RegExp(`^( {0,3}${bull})((?:[\t ][^\\n]*)?(?:\\n|$))`);
512
-
513
- // Check if current bullet point can start a new List Item
514
- while (src) {
515
- endEarly = false;
516
- if (!(cap = itemRegex.exec(src))) {
517
- break;
518
- }
519
-
520
- if (this.rules.block.hr.test(src)) { // End list if bullet was actually HR (possibly move into itemRegex?)
521
- break;
522
- }
523
-
524
- raw = cap[0];
525
- src = src.substring(raw.length);
526
-
527
- line = cap[2].split('\n', 1)[0].replace(/^\t+/, (t) => ' '.repeat(3 * t.length));
528
- nextLine = src.split('\n', 1)[0];
529
-
530
- if (this.options.pedantic) {
531
- indent = 2;
532
- itemContents = line.trimLeft();
533
- } else {
534
- indent = cap[2].search(/[^ ]/); // Find first non-space char
535
- indent = indent > 4 ? 1 : indent; // Treat indented code blocks (> 4 spaces) as having only 1 indent
536
- itemContents = line.slice(indent);
537
- indent += cap[1].length;
538
- }
539
-
540
- blankLine = false;
541
-
542
- if (!line && /^ *$/.test(nextLine)) { // Items begin with at most one blank line
543
- raw += nextLine + '\n';
544
- src = src.substring(nextLine.length + 1);
545
- endEarly = true;
546
- }
547
-
548
- if (!endEarly) {
549
- const nextBulletRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ \t][^\\n]*)?(?:\\n|$))`);
550
- const hrRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`);
551
- const fencesBeginRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:\`\`\`|~~~)`);
552
- const headingBeginRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`);
553
-
554
- // Check if following lines should be included in List Item
555
- while (src) {
556
- rawLine = src.split('\n', 1)[0];
557
- nextLine = rawLine;
558
-
559
- // Re-align to follow commonmark nesting rules
560
- if (this.options.pedantic) {
561
- nextLine = nextLine.replace(/^ {1,4}(?=( {4})*[^ ])/g, ' ');
562
- }
563
-
564
- // End list item if found code fences
565
- if (fencesBeginRegex.test(nextLine)) {
566
- break;
567
- }
568
-
569
- // End list item if found start of new heading
570
- if (headingBeginRegex.test(nextLine)) {
571
- break;
572
- }
573
-
574
- // End list item if found start of new bullet
575
- if (nextBulletRegex.test(nextLine)) {
576
- break;
577
- }
578
-
579
- // Horizontal rule found
580
- if (hrRegex.test(src)) {
581
- break;
582
- }
583
-
584
- if (nextLine.search(/[^ ]/) >= indent || !nextLine.trim()) { // Dedent if possible
585
- itemContents += '\n' + nextLine.slice(indent);
586
- } else {
587
- // not enough indentation
588
- if (blankLine) {
589
- break;
590
- }
591
-
592
- // paragraph continuation unless last line was a different block level element
593
- if (line.search(/[^ ]/) >= 4) { // indented code block
594
- break;
595
- }
596
- if (fencesBeginRegex.test(line)) {
597
- break;
598
- }
599
- if (headingBeginRegex.test(line)) {
600
- break;
601
- }
602
- if (hrRegex.test(line)) {
603
- break;
604
- }
605
-
606
- itemContents += '\n' + nextLine;
607
- }
608
-
609
- if (!blankLine && !nextLine.trim()) { // Check if current line is blank
610
- blankLine = true;
611
- }
612
-
613
- raw += rawLine + '\n';
614
- src = src.substring(rawLine.length + 1);
615
- line = nextLine.slice(indent);
616
- }
617
- }
618
-
619
- if (!list.loose) {
620
- // If the previous item ended with a blank line, the list is loose
621
- if (endsWithBlankLine) {
622
- list.loose = true;
623
- } else if (/\n *\n *$/.test(raw)) {
624
- endsWithBlankLine = true;
625
- }
626
- }
627
-
628
- // Check for task list items
629
- if (this.options.gfm) {
630
- istask = /^\[[ xX]\] /.exec(itemContents);
631
- if (istask) {
632
- ischecked = istask[0] !== '[ ] ';
633
- itemContents = itemContents.replace(/^\[[ xX]\] +/, '');
634
- }
635
- }
636
-
637
- list.items.push({
638
- type: 'list_item',
639
- raw,
640
- task: !!istask,
641
- checked: ischecked,
642
- loose: false,
643
- text: itemContents
644
- });
645
-
646
- list.raw += raw;
647
- }
648
-
649
- // Do not consume newlines at end of final item. Alternatively, make itemRegex *start* with any newlines to simplify/speed up endsWithBlankLine logic
650
- list.items[list.items.length - 1].raw = raw.trimRight();
651
- list.items[list.items.length - 1].text = itemContents.trimRight();
652
- list.raw = list.raw.trimRight();
653
-
654
- const l = list.items.length;
655
-
656
- // Item child tokens handled here at end because we needed to have the final item to trim it first
657
- for (i = 0; i < l; i++) {
658
- this.lexer.state.top = false;
659
- list.items[i].tokens = this.lexer.blockTokens(list.items[i].text, []);
660
-
661
- if (!list.loose) {
662
- // Check if list should be loose
663
- const spacers = list.items[i].tokens.filter(t => t.type === 'space');
664
- const hasMultipleLineBreaks = spacers.length > 0 && spacers.some(t => /\n.*\n/.test(t.raw));
665
-
666
- list.loose = hasMultipleLineBreaks;
667
- }
668
- }
669
-
670
- // Set all items to loose if list is loose
671
- if (list.loose) {
672
- for (i = 0; i < l; i++) {
673
- list.items[i].loose = true;
674
- }
675
- }
676
-
677
- return list;
678
- }
679
- }
680
-
681
- html(src) {
682
- const cap = this.rules.block.html.exec(src);
683
- if (cap) {
684
- const token = {
685
- type: 'html',
686
- raw: cap[0],
687
- pre: !this.options.sanitizer
688
- && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
689
- text: cap[0]
690
- };
691
- if (this.options.sanitize) {
692
- const text = this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0]);
693
- token.type = 'paragraph';
694
- token.text = text;
695
- token.tokens = this.lexer.inline(text);
696
- }
697
- return token;
698
- }
699
- }
700
-
701
- def(src) {
702
- const cap = this.rules.block.def.exec(src);
703
- if (cap) {
704
- const tag = cap[1].toLowerCase().replace(/\s+/g, ' ');
705
- const href = cap[2] ? cap[2].replace(/^<(.*)>$/, '$1').replace(this.rules.inline._escapes, '$1') : '';
706
- const title = cap[3] ? cap[3].substring(1, cap[3].length - 1).replace(this.rules.inline._escapes, '$1') : cap[3];
707
- return {
708
- type: 'def',
709
- tag,
710
- raw: cap[0],
711
- href,
712
- title
713
- };
714
- }
715
- }
716
-
717
- table(src) {
718
- const cap = this.rules.block.table.exec(src);
719
- if (cap) {
720
- const item = {
721
- type: 'table',
722
- header: splitCells(cap[1]).map(c => { return { text: c }; }),
723
- align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
724
- rows: cap[3] && cap[3].trim() ? cap[3].replace(/\n[ \t]*$/, '').split('\n') : []
725
- };
726
-
727
- if (item.header.length === item.align.length) {
728
- item.raw = cap[0];
729
-
730
- let l = item.align.length;
731
- let i, j, k, row;
732
- for (i = 0; i < l; i++) {
733
- if (/^ *-+: *$/.test(item.align[i])) {
734
- item.align[i] = 'right';
735
- } else if (/^ *:-+: *$/.test(item.align[i])) {
736
- item.align[i] = 'center';
737
- } else if (/^ *:-+ *$/.test(item.align[i])) {
738
- item.align[i] = 'left';
739
- } else {
740
- item.align[i] = null;
741
- }
742
- }
743
-
744
- l = item.rows.length;
745
- for (i = 0; i < l; i++) {
746
- item.rows[i] = splitCells(item.rows[i], item.header.length).map(c => { return { text: c }; });
747
- }
748
-
749
- // parse child tokens inside headers and cells
750
-
751
- // header child tokens
752
- l = item.header.length;
753
- for (j = 0; j < l; j++) {
754
- item.header[j].tokens = this.lexer.inline(item.header[j].text);
755
- }
756
-
757
- // cell child tokens
758
- l = item.rows.length;
759
- for (j = 0; j < l; j++) {
760
- row = item.rows[j];
761
- for (k = 0; k < row.length; k++) {
762
- row[k].tokens = this.lexer.inline(row[k].text);
763
- }
764
- }
765
-
766
- return item;
767
- }
768
- }
769
- }
770
-
771
- lheading(src) {
772
- const cap = this.rules.block.lheading.exec(src);
773
- if (cap) {
774
- return {
775
- type: 'heading',
776
- raw: cap[0],
777
- depth: cap[2].charAt(0) === '=' ? 1 : 2,
778
- text: cap[1],
779
- tokens: this.lexer.inline(cap[1])
780
- };
781
- }
782
- }
783
-
784
- paragraph(src) {
785
- const cap = this.rules.block.paragraph.exec(src);
786
- if (cap) {
787
- const text = cap[1].charAt(cap[1].length - 1) === '\n'
788
- ? cap[1].slice(0, -1)
789
- : cap[1];
790
- return {
791
- type: 'paragraph',
792
- raw: cap[0],
793
- text,
794
- tokens: this.lexer.inline(text)
795
- };
796
- }
797
- }
798
-
799
- text(src) {
800
- const cap = this.rules.block.text.exec(src);
801
- if (cap) {
802
- return {
803
- type: 'text',
804
- raw: cap[0],
805
- text: cap[0],
806
- tokens: this.lexer.inline(cap[0])
807
- };
808
- }
809
- }
810
-
811
- escape(src) {
812
- const cap = this.rules.inline.escape.exec(src);
813
- if (cap) {
814
- return {
815
- type: 'escape',
816
- raw: cap[0],
817
- text: escape(cap[1])
818
- };
819
- }
820
- }
821
-
822
- tag(src) {
823
- const cap = this.rules.inline.tag.exec(src);
824
- if (cap) {
825
- if (!this.lexer.state.inLink && /^<a /i.test(cap[0])) {
826
- this.lexer.state.inLink = true;
827
- } else if (this.lexer.state.inLink && /^<\/a>/i.test(cap[0])) {
828
- this.lexer.state.inLink = false;
829
- }
830
- if (!this.lexer.state.inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
831
- this.lexer.state.inRawBlock = true;
832
- } else if (this.lexer.state.inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
833
- this.lexer.state.inRawBlock = false;
834
- }
835
-
836
- return {
837
- type: this.options.sanitize
838
- ? 'text'
839
- : 'html',
840
- raw: cap[0],
841
- inLink: this.lexer.state.inLink,
842
- inRawBlock: this.lexer.state.inRawBlock,
843
- text: this.options.sanitize
844
- ? (this.options.sanitizer
845
- ? this.options.sanitizer(cap[0])
846
- : escape(cap[0]))
847
- : cap[0]
848
- };
849
- }
850
- }
851
-
852
- link(src) {
853
- const cap = this.rules.inline.link.exec(src);
854
- if (cap) {
855
- const trimmedUrl = cap[2].trim();
856
- if (!this.options.pedantic && /^</.test(trimmedUrl)) {
857
- // commonmark requires matching angle brackets
858
- if (!(/>$/.test(trimmedUrl))) {
859
- return;
860
- }
861
-
862
- // ending angle bracket cannot be escaped
863
- const rtrimSlash = rtrim(trimmedUrl.slice(0, -1), '\\');
864
- if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) {
865
- return;
866
- }
867
- } else {
868
- // find closing parenthesis
869
- const lastParenIndex = findClosingBracket(cap[2], '()');
870
- if (lastParenIndex > -1) {
871
- const start = cap[0].indexOf('!') === 0 ? 5 : 4;
872
- const linkLen = start + cap[1].length + lastParenIndex;
873
- cap[2] = cap[2].substring(0, lastParenIndex);
874
- cap[0] = cap[0].substring(0, linkLen).trim();
875
- cap[3] = '';
876
- }
877
- }
878
- let href = cap[2];
879
- let title = '';
880
- if (this.options.pedantic) {
881
- // split pedantic href and title
882
- const link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href);
883
-
884
- if (link) {
885
- href = link[1];
886
- title = link[3];
887
- }
888
- } else {
889
- title = cap[3] ? cap[3].slice(1, -1) : '';
890
- }
891
-
892
- href = href.trim();
893
- if (/^</.test(href)) {
894
- if (this.options.pedantic && !(/>$/.test(trimmedUrl))) {
895
- // pedantic allows starting angle bracket without ending angle bracket
896
- href = href.slice(1);
897
- } else {
898
- href = href.slice(1, -1);
899
- }
900
- }
901
- return outputLink(cap, {
902
- href: href ? href.replace(this.rules.inline._escapes, '$1') : href,
903
- title: title ? title.replace(this.rules.inline._escapes, '$1') : title
904
- }, cap[0], this.lexer);
905
- }
906
- }
907
-
908
- reflink(src, links) {
909
- let cap;
910
- if ((cap = this.rules.inline.reflink.exec(src))
911
- || (cap = this.rules.inline.nolink.exec(src))) {
912
- let link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
913
- link = links[link.toLowerCase()];
914
- if (!link) {
915
- const text = cap[0].charAt(0);
916
- return {
917
- type: 'text',
918
- raw: text,
919
- text
920
- };
921
- }
922
- return outputLink(cap, link, cap[0], this.lexer);
923
- }
924
- }
925
-
926
- emStrong(src, maskedSrc, prevChar = '') {
927
- let match = this.rules.inline.emStrong.lDelim.exec(src);
928
- if (!match) return;
929
-
930
- // _ can't be between two alphanumerics. \p{L}\p{N} includes non-english alphabet/numbers as well
931
- if (match[3] && prevChar.match(/[\p{L}\p{N}]/u)) return;
932
-
933
- const nextChar = match[1] || match[2] || '';
934
-
935
- if (!nextChar || (nextChar && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar)))) {
936
- const lLength = match[0].length - 1;
937
- let rDelim, rLength, delimTotal = lLength, midDelimTotal = 0;
938
-
939
- const endReg = match[0][0] === '*' ? this.rules.inline.emStrong.rDelimAst : this.rules.inline.emStrong.rDelimUnd;
940
- endReg.lastIndex = 0;
941
-
942
- // Clip maskedSrc to same section of string as src (move to lexer?)
943
- maskedSrc = maskedSrc.slice(-1 * src.length + lLength);
944
-
945
- while ((match = endReg.exec(maskedSrc)) != null) {
946
- rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6];
947
-
948
- if (!rDelim) continue; // skip single * in __abc*abc__
949
-
950
- rLength = rDelim.length;
951
-
952
- if (match[3] || match[4]) { // found another Left Delim
953
- delimTotal += rLength;
954
- continue;
955
- } else if (match[5] || match[6]) { // either Left or Right Delim
956
- if (lLength % 3 && !((lLength + rLength) % 3)) {
957
- midDelimTotal += rLength;
958
- continue; // CommonMark Emphasis Rules 9-10
959
- }
960
- }
961
-
962
- delimTotal -= rLength;
963
-
964
- if (delimTotal > 0) continue; // Haven't found enough closing delimiters
965
-
966
- // Remove extra characters. *a*** -> *a*
967
- rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal);
968
-
969
- const raw = src.slice(0, lLength + match.index + (match[0].length - rDelim.length) + rLength);
970
-
971
- // Create `em` if smallest delimiter has odd char count. *a***
972
- if (Math.min(lLength, rLength) % 2) {
973
- const text = raw.slice(1, -1);
974
- return {
975
- type: 'em',
976
- raw,
977
- text,
978
- tokens: this.lexer.inlineTokens(text)
979
- };
980
- }
981
-
982
- // Create 'strong' if smallest delimiter has even char count. **a***
983
- const text = raw.slice(2, -2);
984
- return {
985
- type: 'strong',
986
- raw,
987
- text,
988
- tokens: this.lexer.inlineTokens(text)
989
- };
990
- }
991
- }
992
- }
993
-
994
- codespan(src) {
995
- const cap = this.rules.inline.code.exec(src);
996
- if (cap) {
997
- let text = cap[2].replace(/\n/g, ' ');
998
- const hasNonSpaceChars = /[^ ]/.test(text);
999
- const hasSpaceCharsOnBothEnds = /^ /.test(text) && / $/.test(text);
1000
- if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {
1001
- text = text.substring(1, text.length - 1);
1002
- }
1003
- text = escape(text, true);
1004
- return {
1005
- type: 'codespan',
1006
- raw: cap[0],
1007
- text
1008
- };
1009
- }
1010
- }
1011
-
1012
- br(src) {
1013
- const cap = this.rules.inline.br.exec(src);
1014
- if (cap) {
1015
- return {
1016
- type: 'br',
1017
- raw: cap[0]
1018
- };
1019
- }
1020
- }
1021
-
1022
- del(src) {
1023
- const cap = this.rules.inline.del.exec(src);
1024
- if (cap) {
1025
- return {
1026
- type: 'del',
1027
- raw: cap[0],
1028
- text: cap[2],
1029
- tokens: this.lexer.inlineTokens(cap[2])
1030
- };
1031
- }
1032
- }
1033
-
1034
- autolink(src, mangle) {
1035
- const cap = this.rules.inline.autolink.exec(src);
1036
- if (cap) {
1037
- let text, href;
1038
- if (cap[2] === '@') {
1039
- text = escape(this.options.mangle ? mangle(cap[1]) : cap[1]);
1040
- href = 'mailto:' + text;
1041
- } else {
1042
- text = escape(cap[1]);
1043
- href = text;
1044
- }
1045
-
1046
- return {
1047
- type: 'link',
1048
- raw: cap[0],
1049
- text,
1050
- href,
1051
- tokens: [
1052
- {
1053
- type: 'text',
1054
- raw: text,
1055
- text
1056
- }
1057
- ]
1058
- };
1059
- }
1060
- }
1061
-
1062
- url(src, mangle) {
1063
- let cap;
1064
- if (cap = this.rules.inline.url.exec(src)) {
1065
- let text, href;
1066
- if (cap[2] === '@') {
1067
- text = escape(this.options.mangle ? mangle(cap[0]) : cap[0]);
1068
- href = 'mailto:' + text;
1069
- } else {
1070
- // do extended autolink path validation
1071
- let prevCapZero;
1072
- do {
1073
- prevCapZero = cap[0];
1074
- cap[0] = this.rules.inline._backpedal.exec(cap[0])[0];
1075
- } while (prevCapZero !== cap[0]);
1076
- text = escape(cap[0]);
1077
- if (cap[1] === 'www.') {
1078
- href = 'http://' + cap[0];
1079
- } else {
1080
- href = cap[0];
1081
- }
1082
- }
1083
- return {
1084
- type: 'link',
1085
- raw: cap[0],
1086
- text,
1087
- href,
1088
- tokens: [
1089
- {
1090
- type: 'text',
1091
- raw: text,
1092
- text
1093
- }
1094
- ]
1095
- };
1096
- }
1097
- }
1098
-
1099
- inlineText(src, smartypants) {
1100
- const cap = this.rules.inline.text.exec(src);
1101
- if (cap) {
1102
- let text;
1103
- if (this.lexer.state.inRawBlock) {
1104
- text = this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0])) : cap[0];
1105
- } else {
1106
- text = escape(this.options.smartypants ? smartypants(cap[0]) : cap[0]);
1107
- }
1108
- return {
1109
- type: 'text',
1110
- raw: cap[0],
1111
- text
1112
- };
1113
- }
1114
- }
1115
- }
1116
-
1117
- /**
1118
- * Block-Level Grammar
1119
- */
1120
- const block = {
1121
- newline: /^(?: *(?:\n|$))+/,
1122
- code: /^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,
1123
- fences: /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,
1124
- hr: /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,
1125
- heading: /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,
1126
- blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,
1127
- list: /^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/,
1128
- html: '^ {0,3}(?:' // optional indentation
1129
- + '<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)' // (1)
1130
- + '|comment[^\\n]*(\\n+|$)' // (2)
1131
- + '|<\\?[\\s\\S]*?(?:\\?>\\n*|$)' // (3)
1132
- + '|<![A-Z][\\s\\S]*?(?:>\\n*|$)' // (4)
1133
- + '|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)' // (5)
1134
- + '|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (6)
1135
- + '|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (7) open tag
1136
- + '|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (7) closing tag
1137
- + ')',
1138
- def: /^ {0,3}\[(label)\]: *(?:\n *)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n *)?| *\n *)(title))? *(?:\n+|$)/,
1139
- table: noopTest,
1140
- lheading: /^((?:.|\n(?!\n))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,
1141
- // regex template, placeholders will be replaced according to different paragraph
1142
- // interruption rules of commonmark and the original markdown spec:
1143
- _paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,
1144
- text: /^[^\n]+/
1145
- };
1146
-
1147
- block._label = /(?!\s*\])(?:\\.|[^\[\]\\])+/;
1148
- block._title = /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/;
1149
- block.def = edit(block.def)
1150
- .replace('label', block._label)
1151
- .replace('title', block._title)
1152
- .getRegex();
1153
-
1154
- block.bullet = /(?:[*+-]|\d{1,9}[.)])/;
1155
- block.listItemStart = edit(/^( *)(bull) */)
1156
- .replace('bull', block.bullet)
1157
- .getRegex();
1158
-
1159
- block.list = edit(block.list)
1160
- .replace(/bull/g, block.bullet)
1161
- .replace('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))')
1162
- .replace('def', '\\n+(?=' + block.def.source + ')')
1163
- .getRegex();
1164
-
1165
- block._tag = 'address|article|aside|base|basefont|blockquote|body|caption'
1166
- + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption'
1167
- + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe'
1168
- + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option'
1169
- + '|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr'
1170
- + '|track|ul';
1171
- block._comment = /<!--(?!-?>)[\s\S]*?(?:-->|$)/;
1172
- block.html = edit(block.html, 'i')
1173
- .replace('comment', block._comment)
1174
- .replace('tag', block._tag)
1175
- .replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/)
1176
- .getRegex();
1177
-
1178
- block.paragraph = edit(block._paragraph)
1179
- .replace('hr', block.hr)
1180
- .replace('heading', ' {0,3}#{1,6} ')
1181
- .replace('|lheading', '') // setex headings don't interrupt commonmark paragraphs
1182
- .replace('|table', '')
1183
- .replace('blockquote', ' {0,3}>')
1184
- .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n')
1185
- .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
1186
- .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)')
1187
- .replace('tag', block._tag) // pars can be interrupted by type (6) html blocks
1188
- .getRegex();
1189
-
1190
- block.blockquote = edit(block.blockquote)
1191
- .replace('paragraph', block.paragraph)
1192
- .getRegex();
1193
-
1194
- /**
1195
- * Normal Block Grammar
1196
- */
1197
-
1198
- block.normal = { ...block };
1199
-
1200
- /**
1201
- * GFM Block Grammar
1202
- */
1203
-
1204
- block.gfm = {
1205
- ...block.normal,
1206
- table: '^ *([^\\n ].*\\|.*)\\n' // Header
1207
- + ' {0,3}(?:\\| *)?(:?-+:? *(?:\\| *:?-+:? *)*)(?:\\| *)?' // Align
1208
- + '(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)' // Cells
1209
- };
1210
-
1211
- block.gfm.table = edit(block.gfm.table)
1212
- .replace('hr', block.hr)
1213
- .replace('heading', ' {0,3}#{1,6} ')
1214
- .replace('blockquote', ' {0,3}>')
1215
- .replace('code', ' {4}[^\\n]')
1216
- .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n')
1217
- .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
1218
- .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)')
1219
- .replace('tag', block._tag) // tables can be interrupted by type (6) html blocks
1220
- .getRegex();
1221
-
1222
- block.gfm.paragraph = edit(block._paragraph)
1223
- .replace('hr', block.hr)
1224
- .replace('heading', ' {0,3}#{1,6} ')
1225
- .replace('|lheading', '') // setex headings don't interrupt commonmark paragraphs
1226
- .replace('table', block.gfm.table) // interrupt paragraphs with table
1227
- .replace('blockquote', ' {0,3}>')
1228
- .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n')
1229
- .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
1230
- .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)')
1231
- .replace('tag', block._tag) // pars can be interrupted by type (6) html blocks
1232
- .getRegex();
1233
- /**
1234
- * Pedantic grammar (original John Gruber's loose markdown specification)
1235
- */
1236
-
1237
- block.pedantic = {
1238
- ...block.normal,
1239
- html: edit(
1240
- '^ *(?:comment *(?:\\n|\\s*$)'
1241
- + '|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)' // closed tag
1242
- + '|<tag(?:"[^"]*"|\'[^\']*\'|\\s[^\'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))')
1243
- .replace('comment', block._comment)
1244
- .replace(/tag/g, '(?!(?:'
1245
- + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub'
1246
- + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)'
1247
- + '\\b)\\w+(?!:|[^\\w\\s@]*@)\\b')
1248
- .getRegex(),
1249
- def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,
1250
- heading: /^(#{1,6})(.*)(?:\n+|$)/,
1251
- fences: noopTest, // fences not supported
1252
- lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,
1253
- paragraph: edit(block.normal._paragraph)
1254
- .replace('hr', block.hr)
1255
- .replace('heading', ' *#{1,6} *[^\n]')
1256
- .replace('lheading', block.lheading)
1257
- .replace('blockquote', ' {0,3}>')
1258
- .replace('|fences', '')
1259
- .replace('|list', '')
1260
- .replace('|html', '')
1261
- .getRegex()
1262
- };
1263
-
1264
- /**
1265
- * Inline-Level Grammar
1266
- */
1267
- const inline = {
1268
- escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,
1269
- autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/,
1270
- url: noopTest,
1271
- tag: '^comment'
1272
- + '|^</[a-zA-Z][\\w:-]*\\s*>' // self-closing tag
1273
- + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag
1274
- + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. <?php ?>
1275
- + '|^<![a-zA-Z]+\\s[\\s\\S]*?>' // declaration, e.g. <!DOCTYPE html>
1276
- + '|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>', // CDATA section
1277
- link: /^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,
1278
- reflink: /^!?\[(label)\]\[(ref)\]/,
1279
- nolink: /^!?\[(ref)\](?:\[\])?/,
1280
- reflinkSearch: 'reflink|nolink(?!\\()',
1281
- emStrong: {
1282
- lDelim: /^(?:\*+(?:([punct_])|[^\s*]))|^_+(?:([punct*])|([^\s_]))/,
1283
- // (1) and (2) can only be a Right Delimiter. (3) and (4) can only be Left. (5) and (6) can be either Left or Right.
1284
- // () Skip orphan inside strong () Consume to delim (1) #*** (2) a***#, a*** (3) #***a, ***a (4) ***# (5) #***# (6) a***a
1285
- rDelimAst: /^(?:[^_*\\]|\\.)*?\_\_(?:[^_*\\]|\\.)*?\*(?:[^_*\\]|\\.)*?(?=\_\_)|(?:[^*\\]|\\.)+(?=[^*])|[punct_](\*+)(?=[\s]|$)|(?:[^punct*_\s\\]|\\.)(\*+)(?=[punct_\s]|$)|[punct_\s](\*+)(?=[^punct*_\s])|[\s](\*+)(?=[punct_])|[punct_](\*+)(?=[punct_])|(?:[^punct*_\s\\]|\\.)(\*+)(?=[^punct*_\s])/,
1286
- rDelimUnd: /^(?:[^_*\\]|\\.)*?\*\*(?:[^_*\\]|\\.)*?\_(?:[^_*\\]|\\.)*?(?=\*\*)|(?:[^_\\]|\\.)+(?=[^_])|[punct*](\_+)(?=[\s]|$)|(?:[^punct*_\s\\]|\\.)(\_+)(?=[punct*\s]|$)|[punct*\s](\_+)(?=[^punct*_\s])|[\s](\_+)(?=[punct*])|[punct*](\_+)(?=[punct*])/ // ^- Not allowed for _
1287
- },
1288
- code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,
1289
- br: /^( {2,}|\\)\n(?!\s*$)/,
1290
- del: noopTest,
1291
- text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,
1292
- punctuation: /^([\spunctuation])/
1293
- };
1294
-
1295
- // list of punctuation marks from CommonMark spec
1296
- // without * and _ to handle the different emphasis markers * and _
1297
- inline._punctuation = '!"#$%&\'()+\\-.,/:;<=>?@\\[\\]`^{|}~';
1298
- inline.punctuation = edit(inline.punctuation).replace(/punctuation/g, inline._punctuation).getRegex();
1299
-
1300
- // sequences em should skip over [title](link), `code`, <html>
1301
- inline.blockSkip = /\[[^\]]*?\]\([^\)]*?\)|`[^`]*?`|<[^>]*?>/g;
1302
- // lookbehind is not available on Safari as of version 16
1303
- // inline.escapedEmSt = /(?<=(?:^|[^\\)(?:\\[^])*)\\[*_]/g;
1304
- inline.escapedEmSt = /(?:^|[^\\])(?:\\\\)*\\[*_]/g;
1305
-
1306
- inline._comment = edit(block._comment).replace('(?:-->|$)', '-->').getRegex();
1307
-
1308
- inline.emStrong.lDelim = edit(inline.emStrong.lDelim)
1309
- .replace(/punct/g, inline._punctuation)
1310
- .getRegex();
1311
-
1312
- inline.emStrong.rDelimAst = edit(inline.emStrong.rDelimAst, 'g')
1313
- .replace(/punct/g, inline._punctuation)
1314
- .getRegex();
1315
-
1316
- inline.emStrong.rDelimUnd = edit(inline.emStrong.rDelimUnd, 'g')
1317
- .replace(/punct/g, inline._punctuation)
1318
- .getRegex();
1319
-
1320
- inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;
1321
-
1322
- inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/;
1323
- inline._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/;
1324
- inline.autolink = edit(inline.autolink)
1325
- .replace('scheme', inline._scheme)
1326
- .replace('email', inline._email)
1327
- .getRegex();
1328
-
1329
- inline._attribute = /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/;
1330
-
1331
- inline.tag = edit(inline.tag)
1332
- .replace('comment', inline._comment)
1333
- .replace('attribute', inline._attribute)
1334
- .getRegex();
1335
-
1336
- inline._label = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
1337
- inline._href = /<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/;
1338
- inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/;
1339
-
1340
- inline.link = edit(inline.link)
1341
- .replace('label', inline._label)
1342
- .replace('href', inline._href)
1343
- .replace('title', inline._title)
1344
- .getRegex();
1345
-
1346
- inline.reflink = edit(inline.reflink)
1347
- .replace('label', inline._label)
1348
- .replace('ref', block._label)
1349
- .getRegex();
1350
-
1351
- inline.nolink = edit(inline.nolink)
1352
- .replace('ref', block._label)
1353
- .getRegex();
1354
-
1355
- inline.reflinkSearch = edit(inline.reflinkSearch, 'g')
1356
- .replace('reflink', inline.reflink)
1357
- .replace('nolink', inline.nolink)
1358
- .getRegex();
1359
-
1360
- /**
1361
- * Normal Inline Grammar
1362
- */
1363
-
1364
- inline.normal = { ...inline };
1365
-
1366
- /**
1367
- * Pedantic Inline Grammar
1368
- */
1369
-
1370
- inline.pedantic = {
1371
- ...inline.normal,
1372
- strong: {
1373
- start: /^__|\*\*/,
1374
- middle: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
1375
- endAst: /\*\*(?!\*)/g,
1376
- endUnd: /__(?!_)/g
1377
- },
1378
- em: {
1379
- start: /^_|\*/,
1380
- middle: /^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/,
1381
- endAst: /\*(?!\*)/g,
1382
- endUnd: /_(?!_)/g
1383
- },
1384
- link: edit(/^!?\[(label)\]\((.*?)\)/)
1385
- .replace('label', inline._label)
1386
- .getRegex(),
1387
- reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/)
1388
- .replace('label', inline._label)
1389
- .getRegex()
1390
- };
1391
-
1392
- /**
1393
- * GFM Inline Grammar
1394
- */
1395
-
1396
- inline.gfm = {
1397
- ...inline.normal,
1398
- escape: edit(inline.escape).replace('])', '~|])').getRegex(),
1399
- _extended_email: /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,
1400
- url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,
1401
- _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,
1402
- del: /^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/,
1403
- text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/
1404
- };
1405
-
1406
- inline.gfm.url = edit(inline.gfm.url, 'i')
1407
- .replace('email', inline.gfm._extended_email)
1408
- .getRegex();
1409
- /**
1410
- * GFM + Line Breaks Inline Grammar
1411
- */
1412
-
1413
- inline.breaks = {
1414
- ...inline.gfm,
1415
- br: edit(inline.br).replace('{2,}', '*').getRegex(),
1416
- text: edit(inline.gfm.text)
1417
- .replace('\\b_', '\\b_| {2,}\\n')
1418
- .replace(/\{2,\}/g, '*')
1419
- .getRegex()
1420
- };
1421
-
1422
- /**
1423
- * smartypants text replacement
1424
- * @param {string} text
1425
- */
1426
- function smartypants(text) {
1427
- return text
1428
- // em-dashes
1429
- .replace(/---/g, '\u2014')
1430
- // en-dashes
1431
- .replace(/--/g, '\u2013')
1432
- // opening singles
1433
- .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
1434
- // closing singles & apostrophes
1435
- .replace(/'/g, '\u2019')
1436
- // opening doubles
1437
- .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
1438
- // closing doubles
1439
- .replace(/"/g, '\u201d')
1440
- // ellipses
1441
- .replace(/\.{3}/g, '\u2026');
1442
- }
1443
-
1444
- /**
1445
- * mangle email addresses
1446
- * @param {string} text
1447
- */
1448
- function mangle(text) {
1449
- let out = '',
1450
- i,
1451
- ch;
1452
-
1453
- const l = text.length;
1454
- for (i = 0; i < l; i++) {
1455
- ch = text.charCodeAt(i);
1456
- if (Math.random() > 0.5) {
1457
- ch = 'x' + ch.toString(16);
1458
- }
1459
- out += '&#' + ch + ';';
1460
- }
1461
-
1462
- return out;
1463
- }
1464
-
1465
- /**
1466
- * Block Lexer
1467
- */
1468
- class Lexer {
1469
- constructor(options) {
1470
- this.tokens = [];
1471
- this.tokens.links = Object.create(null);
1472
- this.options = options || defaults;
1473
- this.options.tokenizer = this.options.tokenizer || new Tokenizer();
1474
- this.tokenizer = this.options.tokenizer;
1475
- this.tokenizer.options = this.options;
1476
- this.tokenizer.lexer = this;
1477
- this.inlineQueue = [];
1478
- this.state = {
1479
- inLink: false,
1480
- inRawBlock: false,
1481
- top: true
1482
- };
1483
-
1484
- const rules = {
1485
- block: block.normal,
1486
- inline: inline.normal
1487
- };
1488
-
1489
- if (this.options.pedantic) {
1490
- rules.block = block.pedantic;
1491
- rules.inline = inline.pedantic;
1492
- } else if (this.options.gfm) {
1493
- rules.block = block.gfm;
1494
- if (this.options.breaks) {
1495
- rules.inline = inline.breaks;
1496
- } else {
1497
- rules.inline = inline.gfm;
1498
- }
1499
- }
1500
- this.tokenizer.rules = rules;
1501
- }
1502
-
1503
- /**
1504
- * Expose Rules
1505
- */
1506
- static get rules() {
1507
- return {
1508
- block,
1509
- inline
1510
- };
1511
- }
1512
-
1513
- /**
1514
- * Static Lex Method
1515
- */
1516
- static lex(src, options) {
1517
- const lexer = new Lexer(options);
1518
- return lexer.lex(src);
1519
- }
1520
-
1521
- /**
1522
- * Static Lex Inline Method
1523
- */
1524
- static lexInline(src, options) {
1525
- const lexer = new Lexer(options);
1526
- return lexer.inlineTokens(src);
1527
- }
1528
-
1529
- /**
1530
- * Preprocessing
1531
- */
1532
- lex(src) {
1533
- src = src
1534
- .replace(/\r\n|\r/g, '\n');
1535
-
1536
- this.blockTokens(src, this.tokens);
1537
-
1538
- let next;
1539
- while (next = this.inlineQueue.shift()) {
1540
- this.inlineTokens(next.src, next.tokens);
1541
- }
1542
-
1543
- return this.tokens;
1544
- }
1545
-
1546
- /**
1547
- * Lexing
1548
- */
1549
- blockTokens(src, tokens = []) {
1550
- if (this.options.pedantic) {
1551
- src = src.replace(/\t/g, ' ').replace(/^ +$/gm, '');
1552
- } else {
1553
- src = src.replace(/^( *)(\t+)/gm, (_, leading, tabs) => {
1554
- return leading + ' '.repeat(tabs.length);
1555
- });
1556
- }
1557
-
1558
- let token, lastToken, cutSrc, lastParagraphClipped;
1559
-
1560
- while (src) {
1561
- if (this.options.extensions
1562
- && this.options.extensions.block
1563
- && this.options.extensions.block.some((extTokenizer) => {
1564
- if (token = extTokenizer.call({ lexer: this }, src, tokens)) {
1565
- src = src.substring(token.raw.length);
1566
- tokens.push(token);
1567
- return true;
1568
- }
1569
- return false;
1570
- })) {
1571
- continue;
1572
- }
1573
-
1574
- // newline
1575
- if (token = this.tokenizer.space(src)) {
1576
- src = src.substring(token.raw.length);
1577
- if (token.raw.length === 1 && tokens.length > 0) {
1578
- // if there's a single \n as a spacer, it's terminating the last line,
1579
- // so move it there so that we don't get unecessary paragraph tags
1580
- tokens[tokens.length - 1].raw += '\n';
1581
- } else {
1582
- tokens.push(token);
1583
- }
1584
- continue;
1585
- }
1586
-
1587
- // code
1588
- if (token = this.tokenizer.code(src)) {
1589
- src = src.substring(token.raw.length);
1590
- lastToken = tokens[tokens.length - 1];
1591
- // An indented code block cannot interrupt a paragraph.
1592
- if (lastToken && (lastToken.type === 'paragraph' || lastToken.type === 'text')) {
1593
- lastToken.raw += '\n' + token.raw;
1594
- lastToken.text += '\n' + token.text;
1595
- this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
1596
- } else {
1597
- tokens.push(token);
1598
- }
1599
- continue;
1600
- }
1601
-
1602
- // fences
1603
- if (token = this.tokenizer.fences(src)) {
1604
- src = src.substring(token.raw.length);
1605
- tokens.push(token);
1606
- continue;
1607
- }
1608
-
1609
- // heading
1610
- if (token = this.tokenizer.heading(src)) {
1611
- src = src.substring(token.raw.length);
1612
- tokens.push(token);
1613
- continue;
1614
- }
1615
-
1616
- // hr
1617
- if (token = this.tokenizer.hr(src)) {
1618
- src = src.substring(token.raw.length);
1619
- tokens.push(token);
1620
- continue;
1621
- }
1622
-
1623
- // blockquote
1624
- if (token = this.tokenizer.blockquote(src)) {
1625
- src = src.substring(token.raw.length);
1626
- tokens.push(token);
1627
- continue;
1628
- }
1629
-
1630
- // list
1631
- if (token = this.tokenizer.list(src)) {
1632
- src = src.substring(token.raw.length);
1633
- tokens.push(token);
1634
- continue;
1635
- }
1636
-
1637
- // html
1638
- if (token = this.tokenizer.html(src)) {
1639
- src = src.substring(token.raw.length);
1640
- tokens.push(token);
1641
- continue;
1642
- }
1643
-
1644
- // def
1645
- if (token = this.tokenizer.def(src)) {
1646
- src = src.substring(token.raw.length);
1647
- lastToken = tokens[tokens.length - 1];
1648
- if (lastToken && (lastToken.type === 'paragraph' || lastToken.type === 'text')) {
1649
- lastToken.raw += '\n' + token.raw;
1650
- lastToken.text += '\n' + token.raw;
1651
- this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
1652
- } else if (!this.tokens.links[token.tag]) {
1653
- this.tokens.links[token.tag] = {
1654
- href: token.href,
1655
- title: token.title
1656
- };
1657
- }
1658
- continue;
1659
- }
1660
-
1661
- // table (gfm)
1662
- if (token = this.tokenizer.table(src)) {
1663
- src = src.substring(token.raw.length);
1664
- tokens.push(token);
1665
- continue;
1666
- }
1667
-
1668
- // lheading
1669
- if (token = this.tokenizer.lheading(src)) {
1670
- src = src.substring(token.raw.length);
1671
- tokens.push(token);
1672
- continue;
1673
- }
1674
-
1675
- // top-level paragraph
1676
- // prevent paragraph consuming extensions by clipping 'src' to extension start
1677
- cutSrc = src;
1678
- if (this.options.extensions && this.options.extensions.startBlock) {
1679
- let startIndex = Infinity;
1680
- const tempSrc = src.slice(1);
1681
- let tempStart;
1682
- this.options.extensions.startBlock.forEach(function(getStartIndex) {
1683
- tempStart = getStartIndex.call({ lexer: this }, tempSrc);
1684
- if (typeof tempStart === 'number' && tempStart >= 0) { startIndex = Math.min(startIndex, tempStart); }
1685
- });
1686
- if (startIndex < Infinity && startIndex >= 0) {
1687
- cutSrc = src.substring(0, startIndex + 1);
1688
- }
1689
- }
1690
- if (this.state.top && (token = this.tokenizer.paragraph(cutSrc))) {
1691
- lastToken = tokens[tokens.length - 1];
1692
- if (lastParagraphClipped && lastToken.type === 'paragraph') {
1693
- lastToken.raw += '\n' + token.raw;
1694
- lastToken.text += '\n' + token.text;
1695
- this.inlineQueue.pop();
1696
- this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
1697
- } else {
1698
- tokens.push(token);
1699
- }
1700
- lastParagraphClipped = (cutSrc.length !== src.length);
1701
- src = src.substring(token.raw.length);
1702
- continue;
1703
- }
1704
-
1705
- // text
1706
- if (token = this.tokenizer.text(src)) {
1707
- src = src.substring(token.raw.length);
1708
- lastToken = tokens[tokens.length - 1];
1709
- if (lastToken && lastToken.type === 'text') {
1710
- lastToken.raw += '\n' + token.raw;
1711
- lastToken.text += '\n' + token.text;
1712
- this.inlineQueue.pop();
1713
- this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
1714
- } else {
1715
- tokens.push(token);
1716
- }
1717
- continue;
1718
- }
1719
-
1720
- if (src) {
1721
- const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
1722
- if (this.options.silent) {
1723
- console.error(errMsg);
1724
- break;
1725
- } else {
1726
- throw new Error(errMsg);
1727
- }
1728
- }
1729
- }
1730
-
1731
- this.state.top = true;
1732
- return tokens;
1733
- }
1734
-
1735
- inline(src, tokens = []) {
1736
- this.inlineQueue.push({ src, tokens });
1737
- return tokens;
1738
- }
1739
-
1740
- /**
1741
- * Lexing/Compiling
1742
- */
1743
- inlineTokens(src, tokens = []) {
1744
- let token, lastToken, cutSrc;
1745
-
1746
- // String with links masked to avoid interference with em and strong
1747
- let maskedSrc = src;
1748
- let match;
1749
- let keepPrevChar, prevChar;
1750
-
1751
- // Mask out reflinks
1752
- if (this.tokens.links) {
1753
- const links = Object.keys(this.tokens.links);
1754
- if (links.length > 0) {
1755
- while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {
1756
- if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) {
1757
- maskedSrc = maskedSrc.slice(0, match.index) + '[' + repeatString('a', match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);
1758
- }
1759
- }
1760
- }
1761
- }
1762
- // Mask out other blocks
1763
- while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {
1764
- maskedSrc = maskedSrc.slice(0, match.index) + '[' + repeatString('a', match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
1765
- }
1766
-
1767
- // Mask out escaped em & strong delimiters
1768
- while ((match = this.tokenizer.rules.inline.escapedEmSt.exec(maskedSrc)) != null) {
1769
- maskedSrc = maskedSrc.slice(0, match.index + match[0].length - 2) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.escapedEmSt.lastIndex);
1770
- this.tokenizer.rules.inline.escapedEmSt.lastIndex--;
1771
- }
1772
-
1773
- while (src) {
1774
- if (!keepPrevChar) {
1775
- prevChar = '';
1776
- }
1777
- keepPrevChar = false;
1778
-
1779
- // extensions
1780
- if (this.options.extensions
1781
- && this.options.extensions.inline
1782
- && this.options.extensions.inline.some((extTokenizer) => {
1783
- if (token = extTokenizer.call({ lexer: this }, src, tokens)) {
1784
- src = src.substring(token.raw.length);
1785
- tokens.push(token);
1786
- return true;
1787
- }
1788
- return false;
1789
- })) {
1790
- continue;
1791
- }
1792
-
1793
- // escape
1794
- if (token = this.tokenizer.escape(src)) {
1795
- src = src.substring(token.raw.length);
1796
- tokens.push(token);
1797
- continue;
1798
- }
1799
-
1800
- // tag
1801
- if (token = this.tokenizer.tag(src)) {
1802
- src = src.substring(token.raw.length);
1803
- lastToken = tokens[tokens.length - 1];
1804
- if (lastToken && token.type === 'text' && lastToken.type === 'text') {
1805
- lastToken.raw += token.raw;
1806
- lastToken.text += token.text;
1807
- } else {
1808
- tokens.push(token);
1809
- }
1810
- continue;
1811
- }
1812
-
1813
- // link
1814
- if (token = this.tokenizer.link(src)) {
1815
- src = src.substring(token.raw.length);
1816
- tokens.push(token);
1817
- continue;
1818
- }
1819
-
1820
- // reflink, nolink
1821
- if (token = this.tokenizer.reflink(src, this.tokens.links)) {
1822
- src = src.substring(token.raw.length);
1823
- lastToken = tokens[tokens.length - 1];
1824
- if (lastToken && token.type === 'text' && lastToken.type === 'text') {
1825
- lastToken.raw += token.raw;
1826
- lastToken.text += token.text;
1827
- } else {
1828
- tokens.push(token);
1829
- }
1830
- continue;
1831
- }
1832
-
1833
- // em & strong
1834
- if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) {
1835
- src = src.substring(token.raw.length);
1836
- tokens.push(token);
1837
- continue;
1838
- }
1839
-
1840
- // code
1841
- if (token = this.tokenizer.codespan(src)) {
1842
- src = src.substring(token.raw.length);
1843
- tokens.push(token);
1844
- continue;
1845
- }
1846
-
1847
- // br
1848
- if (token = this.tokenizer.br(src)) {
1849
- src = src.substring(token.raw.length);
1850
- tokens.push(token);
1851
- continue;
1852
- }
1853
-
1854
- // del (gfm)
1855
- if (token = this.tokenizer.del(src)) {
1856
- src = src.substring(token.raw.length);
1857
- tokens.push(token);
1858
- continue;
1859
- }
1860
-
1861
- // autolink
1862
- if (token = this.tokenizer.autolink(src, mangle)) {
1863
- src = src.substring(token.raw.length);
1864
- tokens.push(token);
1865
- continue;
1866
- }
1867
-
1868
- // url (gfm)
1869
- if (!this.state.inLink && (token = this.tokenizer.url(src, mangle))) {
1870
- src = src.substring(token.raw.length);
1871
- tokens.push(token);
1872
- continue;
1873
- }
1874
-
1875
- // text
1876
- // prevent inlineText consuming extensions by clipping 'src' to extension start
1877
- cutSrc = src;
1878
- if (this.options.extensions && this.options.extensions.startInline) {
1879
- let startIndex = Infinity;
1880
- const tempSrc = src.slice(1);
1881
- let tempStart;
1882
- this.options.extensions.startInline.forEach(function(getStartIndex) {
1883
- tempStart = getStartIndex.call({ lexer: this }, tempSrc);
1884
- if (typeof tempStart === 'number' && tempStart >= 0) { startIndex = Math.min(startIndex, tempStart); }
1885
- });
1886
- if (startIndex < Infinity && startIndex >= 0) {
1887
- cutSrc = src.substring(0, startIndex + 1);
1888
- }
1889
- }
1890
- if (token = this.tokenizer.inlineText(cutSrc, smartypants)) {
1891
- src = src.substring(token.raw.length);
1892
- if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started
1893
- prevChar = token.raw.slice(-1);
1894
- }
1895
- keepPrevChar = true;
1896
- lastToken = tokens[tokens.length - 1];
1897
- if (lastToken && lastToken.type === 'text') {
1898
- lastToken.raw += token.raw;
1899
- lastToken.text += token.text;
1900
- } else {
1901
- tokens.push(token);
1902
- }
1903
- continue;
1904
- }
1905
-
1906
- if (src) {
1907
- const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
1908
- if (this.options.silent) {
1909
- console.error(errMsg);
1910
- break;
1911
- } else {
1912
- throw new Error(errMsg);
1913
- }
1914
- }
1915
- }
1916
-
1917
- return tokens;
1918
- }
1919
- }
1920
-
1921
- /**
1922
- * Renderer
1923
- */
1924
- class Renderer {
1925
- constructor(options) {
1926
- this.options = options || defaults;
1927
- }
1928
-
1929
- code(code, infostring, escaped) {
1930
- const lang = (infostring || '').match(/\S*/)[0];
1931
- if (this.options.highlight) {
1932
- const out = this.options.highlight(code, lang);
1933
- if (out != null && out !== code) {
1934
- escaped = true;
1935
- code = out;
1936
- }
1937
- }
1938
-
1939
- code = code.replace(/\n$/, '') + '\n';
1940
-
1941
- if (!lang) {
1942
- return '<pre><code>'
1943
- + (escaped ? code : escape(code, true))
1944
- + '</code></pre>\n';
1945
- }
1946
-
1947
- return '<pre><code class="'
1948
- + this.options.langPrefix
1949
- + escape(lang)
1950
- + '">'
1951
- + (escaped ? code : escape(code, true))
1952
- + '</code></pre>\n';
1953
- }
1954
-
1955
- /**
1956
- * @param {string} quote
1957
- */
1958
- blockquote(quote) {
1959
- return `<blockquote>\n${quote}</blockquote>\n`;
1960
- }
1961
-
1962
- html(html) {
1963
- return html;
1964
- }
1965
-
1966
- /**
1967
- * @param {string} text
1968
- * @param {string} level
1969
- * @param {string} raw
1970
- * @param {any} slugger
1971
- */
1972
- heading(text, level, raw, slugger) {
1973
- if (this.options.headerIds) {
1974
- const id = this.options.headerPrefix + slugger.slug(raw);
1975
- return `<h${level} id="${id}">${text}</h${level}>\n`;
1976
- }
1977
-
1978
- // ignore IDs
1979
- return `<h${level}>${text}</h${level}>\n`;
1980
- }
1981
-
1982
- hr() {
1983
- return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
1984
- }
1985
-
1986
- list(body, ordered, start) {
1987
- const type = ordered ? 'ol' : 'ul',
1988
- startatt = (ordered && start !== 1) ? (' start="' + start + '"') : '';
1989
- return '<' + type + startatt + '>\n' + body + '</' + type + '>\n';
1990
- }
1991
-
1992
- /**
1993
- * @param {string} text
1994
- */
1995
- listitem(text) {
1996
- return `<li>${text}</li>\n`;
1997
- }
1998
-
1999
- checkbox(checked) {
2000
- return '<input '
2001
- + (checked ? 'checked="" ' : '')
2002
- + 'disabled="" type="checkbox"'
2003
- + (this.options.xhtml ? ' /' : '')
2004
- + '> ';
2005
- }
2006
-
2007
- /**
2008
- * @param {string} text
2009
- */
2010
- paragraph(text) {
2011
- return `<p>${text}</p>\n`;
2012
- }
2013
-
2014
- /**
2015
- * @param {string} header
2016
- * @param {string} body
2017
- */
2018
- table(header, body) {
2019
- if (body) body = `<tbody>${body}</tbody>`;
2020
-
2021
- return '<table>\n'
2022
- + '<thead>\n'
2023
- + header
2024
- + '</thead>\n'
2025
- + body
2026
- + '</table>\n';
2027
- }
2028
-
2029
- /**
2030
- * @param {string} content
2031
- */
2032
- tablerow(content) {
2033
- return `<tr>\n${content}</tr>\n`;
2034
- }
2035
-
2036
- tablecell(content, flags) {
2037
- const type = flags.header ? 'th' : 'td';
2038
- const tag = flags.align
2039
- ? `<${type} align="${flags.align}">`
2040
- : `<${type}>`;
2041
- return tag + content + `</${type}>\n`;
2042
- }
2043
-
2044
- /**
2045
- * span level renderer
2046
- * @param {string} text
2047
- */
2048
- strong(text) {
2049
- return `<strong>${text}</strong>`;
2050
- }
2051
-
2052
- /**
2053
- * @param {string} text
2054
- */
2055
- em(text) {
2056
- return `<em>${text}</em>`;
2057
- }
2058
-
2059
- /**
2060
- * @param {string} text
2061
- */
2062
- codespan(text) {
2063
- return `<code>${text}</code>`;
2064
- }
2065
-
2066
- br() {
2067
- return this.options.xhtml ? '<br/>' : '<br>';
2068
- }
2069
-
2070
- /**
2071
- * @param {string} text
2072
- */
2073
- del(text) {
2074
- return `<del>${text}</del>`;
2075
- }
2076
-
2077
- /**
2078
- * @param {string} href
2079
- * @param {string} title
2080
- * @param {string} text
2081
- */
2082
- link(href, title, text) {
2083
- href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
2084
- if (href === null) {
2085
- return text;
2086
- }
2087
- let out = '<a href="' + href + '"';
2088
- if (title) {
2089
- out += ' title="' + title + '"';
2090
- }
2091
- out += '>' + text + '</a>';
2092
- return out;
2093
- }
2094
-
2095
- /**
2096
- * @param {string} href
2097
- * @param {string} title
2098
- * @param {string} text
2099
- */
2100
- image(href, title, text) {
2101
- href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
2102
- if (href === null) {
2103
- return text;
2104
- }
2105
-
2106
- let out = `<img src="${href}" alt="${text}"`;
2107
- if (title) {
2108
- out += ` title="${title}"`;
2109
- }
2110
- out += this.options.xhtml ? '/>' : '>';
2111
- return out;
2112
- }
2113
-
2114
- text(text) {
2115
- return text;
2116
- }
2117
- }
2118
-
2119
- /**
2120
- * TextRenderer
2121
- * returns only the textual part of the token
2122
- */
2123
- class TextRenderer {
2124
- // no need for block level renderers
2125
- strong(text) {
2126
- return text;
2127
- }
2128
-
2129
- em(text) {
2130
- return text;
2131
- }
2132
-
2133
- codespan(text) {
2134
- return text;
2135
- }
2136
-
2137
- del(text) {
2138
- return text;
2139
- }
2140
-
2141
- html(text) {
2142
- return text;
2143
- }
2144
-
2145
- text(text) {
2146
- return text;
2147
- }
2148
-
2149
- link(href, title, text) {
2150
- return '' + text;
2151
- }
2152
-
2153
- image(href, title, text) {
2154
- return '' + text;
2155
- }
2156
-
2157
- br() {
2158
- return '';
2159
- }
2160
- }
2161
-
2162
- /**
2163
- * Slugger generates header id
2164
- */
2165
- class Slugger {
2166
- constructor() {
2167
- this.seen = {};
2168
- }
2169
-
2170
- /**
2171
- * @param {string} value
2172
- */
2173
- serialize(value) {
2174
- return value
2175
- .toLowerCase()
2176
- .trim()
2177
- // remove html tags
2178
- .replace(/<[!\/a-z].*?>/ig, '')
2179
- // remove unwanted chars
2180
- .replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '')
2181
- .replace(/\s/g, '-');
2182
- }
2183
-
2184
- /**
2185
- * Finds the next safe (unique) slug to use
2186
- * @param {string} originalSlug
2187
- * @param {boolean} isDryRun
2188
- */
2189
- getNextSafeSlug(originalSlug, isDryRun) {
2190
- let slug = originalSlug;
2191
- let occurenceAccumulator = 0;
2192
- if (this.seen.hasOwnProperty(slug)) {
2193
- occurenceAccumulator = this.seen[originalSlug];
2194
- do {
2195
- occurenceAccumulator++;
2196
- slug = originalSlug + '-' + occurenceAccumulator;
2197
- } while (this.seen.hasOwnProperty(slug));
2198
- }
2199
- if (!isDryRun) {
2200
- this.seen[originalSlug] = occurenceAccumulator;
2201
- this.seen[slug] = 0;
2202
- }
2203
- return slug;
2204
- }
2205
-
2206
- /**
2207
- * Convert string to unique id
2208
- * @param {object} [options]
2209
- * @param {boolean} [options.dryrun] Generates the next unique slug without
2210
- * updating the internal accumulator.
2211
- */
2212
- slug(value, options = {}) {
2213
- const slug = this.serialize(value);
2214
- return this.getNextSafeSlug(slug, options.dryrun);
2215
- }
2216
- }
2217
-
2218
- /**
2219
- * Parsing & Compiling
2220
- */
2221
- class Parser {
2222
- constructor(options) {
2223
- this.options = options || defaults;
2224
- this.options.renderer = this.options.renderer || new Renderer();
2225
- this.renderer = this.options.renderer;
2226
- this.renderer.options = this.options;
2227
- this.textRenderer = new TextRenderer();
2228
- this.slugger = new Slugger();
2229
- }
2230
-
2231
- /**
2232
- * Static Parse Method
2233
- */
2234
- static parse(tokens, options) {
2235
- const parser = new Parser(options);
2236
- return parser.parse(tokens);
2237
- }
2238
-
2239
- /**
2240
- * Static Parse Inline Method
2241
- */
2242
- static parseInline(tokens, options) {
2243
- const parser = new Parser(options);
2244
- return parser.parseInline(tokens);
2245
- }
2246
-
2247
- /**
2248
- * Parse Loop
2249
- */
2250
- parse(tokens, top = true) {
2251
- let out = '',
2252
- i,
2253
- j,
2254
- k,
2255
- l2,
2256
- l3,
2257
- row,
2258
- cell,
2259
- header,
2260
- body,
2261
- token,
2262
- ordered,
2263
- start,
2264
- loose,
2265
- itemBody,
2266
- item,
2267
- checked,
2268
- task,
2269
- checkbox,
2270
- ret;
2271
-
2272
- const l = tokens.length;
2273
- for (i = 0; i < l; i++) {
2274
- token = tokens[i];
2275
-
2276
- // Run any renderer extensions
2277
- if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {
2278
- ret = this.options.extensions.renderers[token.type].call({ parser: this }, token);
2279
- if (ret !== false || !['space', 'hr', 'heading', 'code', 'table', 'blockquote', 'list', 'html', 'paragraph', 'text'].includes(token.type)) {
2280
- out += ret || '';
2281
- continue;
2282
- }
2283
- }
2284
-
2285
- switch (token.type) {
2286
- case 'space': {
2287
- continue;
2288
- }
2289
- case 'hr': {
2290
- out += this.renderer.hr();
2291
- continue;
2292
- }
2293
- case 'heading': {
2294
- out += this.renderer.heading(
2295
- this.parseInline(token.tokens),
2296
- token.depth,
2297
- unescape(this.parseInline(token.tokens, this.textRenderer)),
2298
- this.slugger);
2299
- continue;
2300
- }
2301
- case 'code': {
2302
- out += this.renderer.code(token.text,
2303
- token.lang,
2304
- token.escaped);
2305
- continue;
2306
- }
2307
- case 'table': {
2308
- header = '';
2309
-
2310
- // header
2311
- cell = '';
2312
- l2 = token.header.length;
2313
- for (j = 0; j < l2; j++) {
2314
- cell += this.renderer.tablecell(
2315
- this.parseInline(token.header[j].tokens),
2316
- { header: true, align: token.align[j] }
2317
- );
2318
- }
2319
- header += this.renderer.tablerow(cell);
2320
-
2321
- body = '';
2322
- l2 = token.rows.length;
2323
- for (j = 0; j < l2; j++) {
2324
- row = token.rows[j];
2325
-
2326
- cell = '';
2327
- l3 = row.length;
2328
- for (k = 0; k < l3; k++) {
2329
- cell += this.renderer.tablecell(
2330
- this.parseInline(row[k].tokens),
2331
- { header: false, align: token.align[k] }
2332
- );
2333
- }
2334
-
2335
- body += this.renderer.tablerow(cell);
2336
- }
2337
- out += this.renderer.table(header, body);
2338
- continue;
2339
- }
2340
- case 'blockquote': {
2341
- body = this.parse(token.tokens);
2342
- out += this.renderer.blockquote(body);
2343
- continue;
2344
- }
2345
- case 'list': {
2346
- ordered = token.ordered;
2347
- start = token.start;
2348
- loose = token.loose;
2349
- l2 = token.items.length;
2350
-
2351
- body = '';
2352
- for (j = 0; j < l2; j++) {
2353
- item = token.items[j];
2354
- checked = item.checked;
2355
- task = item.task;
2356
-
2357
- itemBody = '';
2358
- if (item.task) {
2359
- checkbox = this.renderer.checkbox(checked);
2360
- if (loose) {
2361
- if (item.tokens.length > 0 && item.tokens[0].type === 'paragraph') {
2362
- item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
2363
- if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {
2364
- item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text;
2365
- }
2366
- } else {
2367
- item.tokens.unshift({
2368
- type: 'text',
2369
- text: checkbox
2370
- });
2371
- }
2372
- } else {
2373
- itemBody += checkbox;
2374
- }
2375
- }
2376
-
2377
- itemBody += this.parse(item.tokens, loose);
2378
- body += this.renderer.listitem(itemBody, task, checked);
2379
- }
2380
-
2381
- out += this.renderer.list(body, ordered, start);
2382
- continue;
2383
- }
2384
- case 'html': {
2385
- // TODO parse inline content if parameter markdown=1
2386
- out += this.renderer.html(token.text);
2387
- continue;
2388
- }
2389
- case 'paragraph': {
2390
- out += this.renderer.paragraph(this.parseInline(token.tokens));
2391
- continue;
2392
- }
2393
- case 'text': {
2394
- body = token.tokens ? this.parseInline(token.tokens) : token.text;
2395
- while (i + 1 < l && tokens[i + 1].type === 'text') {
2396
- token = tokens[++i];
2397
- body += '\n' + (token.tokens ? this.parseInline(token.tokens) : token.text);
2398
- }
2399
- out += top ? this.renderer.paragraph(body) : body;
2400
- continue;
2401
- }
2402
-
2403
- default: {
2404
- const errMsg = 'Token with "' + token.type + '" type was not found.';
2405
- if (this.options.silent) {
2406
- console.error(errMsg);
2407
- return;
2408
- } else {
2409
- throw new Error(errMsg);
2410
- }
2411
- }
2412
- }
2413
- }
2414
-
2415
- return out;
2416
- }
2417
-
2418
- /**
2419
- * Parse Inline Tokens
2420
- */
2421
- parseInline(tokens, renderer) {
2422
- renderer = renderer || this.renderer;
2423
- let out = '',
2424
- i,
2425
- token,
2426
- ret;
2427
-
2428
- const l = tokens.length;
2429
- for (i = 0; i < l; i++) {
2430
- token = tokens[i];
2431
-
2432
- // Run any renderer extensions
2433
- if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {
2434
- ret = this.options.extensions.renderers[token.type].call({ parser: this }, token);
2435
- if (ret !== false || !['escape', 'html', 'link', 'image', 'strong', 'em', 'codespan', 'br', 'del', 'text'].includes(token.type)) {
2436
- out += ret || '';
2437
- continue;
2438
- }
2439
- }
2440
-
2441
- switch (token.type) {
2442
- case 'escape': {
2443
- out += renderer.text(token.text);
2444
- break;
2445
- }
2446
- case 'html': {
2447
- out += renderer.html(token.text);
2448
- break;
2449
- }
2450
- case 'link': {
2451
- out += renderer.link(token.href, token.title, this.parseInline(token.tokens, renderer));
2452
- break;
2453
- }
2454
- case 'image': {
2455
- out += renderer.image(token.href, token.title, token.text);
2456
- break;
2457
- }
2458
- case 'strong': {
2459
- out += renderer.strong(this.parseInline(token.tokens, renderer));
2460
- break;
2461
- }
2462
- case 'em': {
2463
- out += renderer.em(this.parseInline(token.tokens, renderer));
2464
- break;
2465
- }
2466
- case 'codespan': {
2467
- out += renderer.codespan(token.text);
2468
- break;
2469
- }
2470
- case 'br': {
2471
- out += renderer.br();
2472
- break;
2473
- }
2474
- case 'del': {
2475
- out += renderer.del(this.parseInline(token.tokens, renderer));
2476
- break;
2477
- }
2478
- case 'text': {
2479
- out += renderer.text(token.text);
2480
- break;
2481
- }
2482
- default: {
2483
- const errMsg = 'Token with "' + token.type + '" type was not found.';
2484
- if (this.options.silent) {
2485
- console.error(errMsg);
2486
- return;
2487
- } else {
2488
- throw new Error(errMsg);
2489
- }
2490
- }
2491
- }
2492
- }
2493
- return out;
2494
- }
2495
- }
2496
-
2497
- class Hooks {
2498
- constructor(options) {
2499
- this.options = options || defaults;
2500
- }
2501
-
2502
- static passThroughHooks = new Set([
2503
- 'preprocess',
2504
- 'postprocess'
2505
- ]);
2506
-
2507
- /**
2508
- * Process markdown before marked
2509
- */
2510
- preprocess(markdown) {
2511
- return markdown;
2512
- }
2513
-
2514
- /**
2515
- * Process HTML after marked is finished
2516
- */
2517
- postprocess(html) {
2518
- return html;
2519
- }
2520
- }
2521
-
2522
- function onError(silent, async, callback) {
2523
- return (e) => {
2524
- e.message += '\nPlease report this to https://github.com/markedjs/marked.';
2525
-
2526
- if (silent) {
2527
- const msg = '<p>An error occurred:</p><pre>'
2528
- + escape(e.message + '', true)
2529
- + '</pre>';
2530
- if (async) {
2531
- return Promise.resolve(msg);
2532
- }
2533
- if (callback) {
2534
- callback(null, msg);
2535
- return;
2536
- }
2537
- return msg;
2538
- }
2539
-
2540
- if (async) {
2541
- return Promise.reject(e);
2542
- }
2543
- if (callback) {
2544
- callback(e);
2545
- return;
2546
- }
2547
- throw e;
2548
- };
2549
- }
2550
-
2551
- function parseMarkdown(lexer, parser) {
2552
- return (src, opt, callback) => {
2553
- if (typeof opt === 'function') {
2554
- callback = opt;
2555
- opt = null;
2556
- }
2557
-
2558
- const origOpt = { ...opt };
2559
- opt = { ...marked.defaults, ...origOpt };
2560
- const throwError = onError(opt.silent, opt.async, callback);
2561
-
2562
- // throw error in case of non string input
2563
- if (typeof src === 'undefined' || src === null) {
2564
- return throwError(new Error('marked(): input parameter is undefined or null'));
2565
- }
2566
- if (typeof src !== 'string') {
2567
- return throwError(new Error('marked(): input parameter is of type '
2568
- + Object.prototype.toString.call(src) + ', string expected'));
2569
- }
2570
-
2571
- checkSanitizeDeprecation(opt);
2572
-
2573
- if (opt.hooks) {
2574
- opt.hooks.options = opt;
2575
- }
2576
-
2577
- if (callback) {
2578
- const highlight = opt.highlight;
2579
- let tokens;
2580
-
2581
- try {
2582
- if (opt.hooks) {
2583
- src = opt.hooks.preprocess(src);
2584
- }
2585
- tokens = lexer(src, opt);
2586
- } catch (e) {
2587
- return throwError(e);
2588
- }
2589
-
2590
- const done = function(err) {
2591
- let out;
2592
-
2593
- if (!err) {
2594
- try {
2595
- if (opt.walkTokens) {
2596
- marked.walkTokens(tokens, opt.walkTokens);
2597
- }
2598
- out = parser(tokens, opt);
2599
- if (opt.hooks) {
2600
- out = opt.hooks.postprocess(out);
2601
- }
2602
- } catch (e) {
2603
- err = e;
2604
- }
2605
- }
2606
-
2607
- opt.highlight = highlight;
2608
-
2609
- return err
2610
- ? throwError(err)
2611
- : callback(null, out);
2612
- };
2613
-
2614
- if (!highlight || highlight.length < 3) {
2615
- return done();
2616
- }
2617
-
2618
- delete opt.highlight;
2619
-
2620
- if (!tokens.length) return done();
2621
-
2622
- let pending = 0;
2623
- marked.walkTokens(tokens, function(token) {
2624
- if (token.type === 'code') {
2625
- pending++;
2626
- setTimeout(() => {
2627
- highlight(token.text, token.lang, function(err, code) {
2628
- if (err) {
2629
- return done(err);
2630
- }
2631
- if (code != null && code !== token.text) {
2632
- token.text = code;
2633
- token.escaped = true;
2634
- }
2635
-
2636
- pending--;
2637
- if (pending === 0) {
2638
- done();
2639
- }
2640
- });
2641
- }, 0);
2642
- }
2643
- });
2644
-
2645
- if (pending === 0) {
2646
- done();
2647
- }
2648
-
2649
- return;
2650
- }
2651
-
2652
- if (opt.async) {
2653
- return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src)
2654
- .then(src => lexer(src, opt))
2655
- .then(tokens => opt.walkTokens ? Promise.all(marked.walkTokens(tokens, opt.walkTokens)).then(() => tokens) : tokens)
2656
- .then(tokens => parser(tokens, opt))
2657
- .then(html => opt.hooks ? opt.hooks.postprocess(html) : html)
2658
- .catch(throwError);
2659
- }
2660
-
2661
- try {
2662
- if (opt.hooks) {
2663
- src = opt.hooks.preprocess(src);
2664
- }
2665
- const tokens = lexer(src, opt);
2666
- if (opt.walkTokens) {
2667
- marked.walkTokens(tokens, opt.walkTokens);
2668
- }
2669
- let html = parser(tokens, opt);
2670
- if (opt.hooks) {
2671
- html = opt.hooks.postprocess(html);
2672
- }
2673
- return html;
2674
- } catch (e) {
2675
- return throwError(e);
2676
- }
2677
- };
2678
- }
2679
-
2680
- /**
2681
- * Marked
2682
- */
2683
- function marked(src, opt, callback) {
2684
- return parseMarkdown(Lexer.lex, Parser.parse)(src, opt, callback);
2685
- }
2686
-
2687
- /**
2688
- * Options
2689
- */
2690
-
2691
- marked.options =
2692
- marked.setOptions = function(opt) {
2693
- marked.defaults = { ...marked.defaults, ...opt };
2694
- changeDefaults(marked.defaults);
2695
- return marked;
2696
- };
2697
-
2698
- marked.getDefaults = getDefaults;
2699
-
2700
- marked.defaults = defaults;
2701
-
2702
- /**
2703
- * Use Extension
2704
- */
2705
-
2706
- marked.use = function(...args) {
2707
- const extensions = marked.defaults.extensions || { renderers: {}, childTokens: {} };
2708
-
2709
- args.forEach((pack) => {
2710
- // copy options to new object
2711
- const opts = { ...pack };
2712
-
2713
- // set async to true if it was set to true before
2714
- opts.async = marked.defaults.async || opts.async || false;
2715
-
2716
- // ==-- Parse "addon" extensions --== //
2717
- if (pack.extensions) {
2718
- pack.extensions.forEach((ext) => {
2719
- if (!ext.name) {
2720
- throw new Error('extension name required');
2721
- }
2722
- if (ext.renderer) { // Renderer extensions
2723
- const prevRenderer = extensions.renderers[ext.name];
2724
- if (prevRenderer) {
2725
- // Replace extension with func to run new extension but fall back if false
2726
- extensions.renderers[ext.name] = function(...args) {
2727
- let ret = ext.renderer.apply(this, args);
2728
- if (ret === false) {
2729
- ret = prevRenderer.apply(this, args);
2730
- }
2731
- return ret;
2732
- };
2733
- } else {
2734
- extensions.renderers[ext.name] = ext.renderer;
2735
- }
2736
- }
2737
- if (ext.tokenizer) { // Tokenizer Extensions
2738
- if (!ext.level || (ext.level !== 'block' && ext.level !== 'inline')) {
2739
- throw new Error("extension level must be 'block' or 'inline'");
2740
- }
2741
- if (extensions[ext.level]) {
2742
- extensions[ext.level].unshift(ext.tokenizer);
2743
- } else {
2744
- extensions[ext.level] = [ext.tokenizer];
2745
- }
2746
- if (ext.start) { // Function to check for start of token
2747
- if (ext.level === 'block') {
2748
- if (extensions.startBlock) {
2749
- extensions.startBlock.push(ext.start);
2750
- } else {
2751
- extensions.startBlock = [ext.start];
2752
- }
2753
- } else if (ext.level === 'inline') {
2754
- if (extensions.startInline) {
2755
- extensions.startInline.push(ext.start);
2756
- } else {
2757
- extensions.startInline = [ext.start];
2758
- }
2759
- }
2760
- }
2761
- }
2762
- if (ext.childTokens) { // Child tokens to be visited by walkTokens
2763
- extensions.childTokens[ext.name] = ext.childTokens;
2764
- }
2765
- });
2766
- opts.extensions = extensions;
2767
- }
2768
-
2769
- // ==-- Parse "overwrite" extensions --== //
2770
- if (pack.renderer) {
2771
- const renderer = marked.defaults.renderer || new Renderer();
2772
- for (const prop in pack.renderer) {
2773
- const prevRenderer = renderer[prop];
2774
- // Replace renderer with func to run extension, but fall back if false
2775
- renderer[prop] = (...args) => {
2776
- let ret = pack.renderer[prop].apply(renderer, args);
2777
- if (ret === false) {
2778
- ret = prevRenderer.apply(renderer, args);
2779
- }
2780
- return ret;
2781
- };
2782
- }
2783
- opts.renderer = renderer;
2784
- }
2785
- if (pack.tokenizer) {
2786
- const tokenizer = marked.defaults.tokenizer || new Tokenizer();
2787
- for (const prop in pack.tokenizer) {
2788
- const prevTokenizer = tokenizer[prop];
2789
- // Replace tokenizer with func to run extension, but fall back if false
2790
- tokenizer[prop] = (...args) => {
2791
- let ret = pack.tokenizer[prop].apply(tokenizer, args);
2792
- if (ret === false) {
2793
- ret = prevTokenizer.apply(tokenizer, args);
2794
- }
2795
- return ret;
2796
- };
2797
- }
2798
- opts.tokenizer = tokenizer;
2799
- }
2800
-
2801
- // ==-- Parse Hooks extensions --== //
2802
- if (pack.hooks) {
2803
- const hooks = marked.defaults.hooks || new Hooks();
2804
- for (const prop in pack.hooks) {
2805
- const prevHook = hooks[prop];
2806
- if (Hooks.passThroughHooks.has(prop)) {
2807
- hooks[prop] = (arg) => {
2808
- if (marked.defaults.async) {
2809
- return Promise.resolve(pack.hooks[prop].call(hooks, arg)).then(ret => {
2810
- return prevHook.call(hooks, ret);
2811
- });
2812
- }
2813
-
2814
- const ret = pack.hooks[prop].call(hooks, arg);
2815
- return prevHook.call(hooks, ret);
2816
- };
2817
- } else {
2818
- hooks[prop] = (...args) => {
2819
- let ret = pack.hooks[prop].apply(hooks, args);
2820
- if (ret === false) {
2821
- ret = prevHook.apply(hooks, args);
2822
- }
2823
- return ret;
2824
- };
2825
- }
2826
- }
2827
- opts.hooks = hooks;
2828
- }
2829
-
2830
- // ==-- Parse WalkTokens extensions --== //
2831
- if (pack.walkTokens) {
2832
- const walkTokens = marked.defaults.walkTokens;
2833
- opts.walkTokens = function(token) {
2834
- let values = [];
2835
- values.push(pack.walkTokens.call(this, token));
2836
- if (walkTokens) {
2837
- values = values.concat(walkTokens.call(this, token));
2838
- }
2839
- return values;
2840
- };
2841
- }
2842
-
2843
- marked.setOptions(opts);
2844
- });
2845
- };
2846
-
2847
- /**
2848
- * Run callback for every token
2849
- */
2850
-
2851
- marked.walkTokens = function(tokens, callback) {
2852
- let values = [];
2853
- for (const token of tokens) {
2854
- values = values.concat(callback.call(marked, token));
2855
- switch (token.type) {
2856
- case 'table': {
2857
- for (const cell of token.header) {
2858
- values = values.concat(marked.walkTokens(cell.tokens, callback));
2859
- }
2860
- for (const row of token.rows) {
2861
- for (const cell of row) {
2862
- values = values.concat(marked.walkTokens(cell.tokens, callback));
2863
- }
2864
- }
2865
- break;
2866
- }
2867
- case 'list': {
2868
- values = values.concat(marked.walkTokens(token.items, callback));
2869
- break;
2870
- }
2871
- default: {
2872
- if (marked.defaults.extensions && marked.defaults.extensions.childTokens && marked.defaults.extensions.childTokens[token.type]) { // Walk any extensions
2873
- marked.defaults.extensions.childTokens[token.type].forEach(function(childTokens) {
2874
- values = values.concat(marked.walkTokens(token[childTokens], callback));
2875
- });
2876
- } else if (token.tokens) {
2877
- values = values.concat(marked.walkTokens(token.tokens, callback));
2878
- }
2879
- }
2880
- }
2881
- }
2882
- return values;
2883
- };
2884
-
2885
- /**
2886
- * Parse Inline
2887
- * @param {string} src
2888
- */
2889
- marked.parseInline = parseMarkdown(Lexer.lexInline, Parser.parseInline);
2890
-
2891
- /**
2892
- * Expose
2893
- */
2894
- marked.Parser = Parser;
2895
- marked.parser = Parser.parse;
2896
- marked.Renderer = Renderer;
2897
- marked.TextRenderer = TextRenderer;
2898
- marked.Lexer = Lexer;
2899
- marked.lexer = Lexer.lex;
2900
- marked.Tokenizer = Tokenizer;
2901
- marked.Slugger = Slugger;
2902
- marked.Hooks = Hooks;
2903
- marked.parse = marked;
2904
-
2905
- const options = marked.options;
2906
- const setOptions = marked.setOptions;
2907
- const use = marked.use;
2908
- const walkTokens = marked.walkTokens;
2909
- const parseInline = marked.parseInline;
2910
- const parse = marked;
2911
- const parser = Parser.parse;
2912
- const lexer = Lexer.lex;
2913
-
2914
-
2915
-
2916
-
2917
- /***/ })
2918
-
2919
- }]);