@subiz/widget-v4 4.1.32 → 4.1.35

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