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