@subiz/widget-v4 4.0.88 → 4.0.90

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