@subiz/widget-v4 4.0.98 → 4.1.1

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