marked-rails 0.2.10.1 → 9.1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,1165 +1,2412 @@
1
1
  /**
2
- * marked - a markdown parser
3
- * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed)
4
- * https://github.com/chjj/marked
2
+ * marked v9.1.2 - a markdown parser
3
+ * Copyright (c) 2011-2023, Christopher Jeffrey. (MIT Licensed)
4
+ * https://github.com/markedjs/marked
5
5
  */
6
6
 
7
- ;(function() {
8
-
9
- /**
10
- * Block-Level Grammar
11
- */
12
-
13
- var block = {
14
- newline: /^\n+/,
15
- code: /^( {4}[^\n]+\n*)+/,
16
- fences: noop,
17
- hr: /^( *[-*_]){3,} *(?:\n+|$)/,
18
- heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
19
- nptable: noop,
20
- lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
21
- blockquote: /^( *>[^\n]+(\n[^\n]+)*\n*)+/,
22
- list: /^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
23
- html: /^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,
24
- def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
25
- table: noop,
26
- paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
27
- text: /^[^\n]+/
28
- };
29
-
30
- block.bullet = /(?:[*+-]|\d+\.)/;
31
- block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
32
- block.item = replace(block.item, 'gm')
33
- (/bull/g, block.bullet)
34
- ();
35
-
36
- block.list = replace(block.list)
37
- (/bull/g, block.bullet)
38
- ('hr', /\n+(?=(?: *[-*_]){3,} *(?:\n+|$))/)
39
- ();
40
-
41
- block._tag = '(?!(?:'
42
- + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
43
- + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
44
- + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|@)\\b';
45
-
46
- block.html = replace(block.html)
47
- ('comment', /<!--[\s\S]*?-->/)
48
- ('closed', /<(tag)[\s\S]+?<\/\1>/)
49
- ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
50
- (/tag/g, block._tag)
51
- ();
52
-
53
- block.paragraph = replace(block.paragraph)
54
- ('hr', block.hr)
55
- ('heading', block.heading)
56
- ('lheading', block.lheading)
57
- ('blockquote', block.blockquote)
58
- ('tag', '<' + block._tag)
59
- ('def', block.def)
60
- ();
61
-
62
- /**
63
- * Normal Block Grammar
64
- */
65
-
66
- block.normal = merge({}, block);
67
-
68
- /**
69
- * GFM Block Grammar
70
- */
71
-
72
- block.gfm = merge({}, block.normal, {
73
- fences: /^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,
74
- paragraph: /^/
75
- });
76
-
77
- block.gfm.paragraph = replace(block.paragraph)
78
- ('(?!', '(?!'
79
- + block.gfm.fences.source.replace('\\1', '\\2') + '|'
80
- + block.list.source.replace('\\1', '\\3') + '|')
81
- ();
82
-
83
- /**
84
- * GFM + Tables Block Grammar
85
- */
86
-
87
- block.tables = merge({}, block.gfm, {
88
- nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
89
- table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
90
- });
91
-
92
7
  /**
93
- * Block Lexer
8
+ * DO NOT EDIT THIS FILE
9
+ * The code in this file is generated from files in ./src/
94
10
  */
95
11
 
96
- function Lexer(options) {
97
- this.tokens = [];
98
- this.tokens.links = {};
99
- this.options = options || marked.defaults;
100
- this.rules = block.normal;
101
-
102
- if (this.options.gfm) {
103
- if (this.options.tables) {
104
- this.rules = block.tables;
105
- } else {
106
- this.rules = block.gfm;
12
+ (function (global, factory) {
13
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
14
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
15
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.marked = {}));
16
+ })(this, (function (exports) { 'use strict';
17
+
18
+ /**
19
+ * Gets the original marked default options.
20
+ */
21
+ function _getDefaults() {
22
+ return {
23
+ async: false,
24
+ breaks: false,
25
+ extensions: null,
26
+ gfm: true,
27
+ hooks: null,
28
+ pedantic: false,
29
+ renderer: null,
30
+ silent: false,
31
+ tokenizer: null,
32
+ walkTokens: null
33
+ };
107
34
  }
108
- }
109
- }
110
-
111
- /**
112
- * Expose Block Rules
113
- */
114
-
115
- Lexer.rules = block;
116
-
117
- /**
118
- * Static Lex Method
119
- */
120
-
121
- Lexer.lex = function(src, options) {
122
- var lexer = new Lexer(options);
123
- return lexer.lex(src);
124
- };
125
-
126
- /**
127
- * Preprocessing
128
- */
129
-
130
- Lexer.prototype.lex = function(src) {
131
- src = src
132
- .replace(/\r\n|\r/g, '\n')
133
- .replace(/\t/g, ' ')
134
- .replace(/\u00a0/g, ' ')
135
- .replace(/\u2424/g, '\n');
136
-
137
- return this.token(src, true);
138
- };
139
-
140
- /**
141
- * Lexing
142
- */
143
-
144
- Lexer.prototype.token = function(src, top) {
145
- var src = src.replace(/^ +$/gm, '')
146
- , next
147
- , loose
148
- , cap
149
- , bull
150
- , b
151
- , item
152
- , space
153
- , i
154
- , l;
155
-
156
- while (src) {
157
- // newline
158
- if (cap = this.rules.newline.exec(src)) {
159
- src = src.substring(cap[0].length);
160
- if (cap[0].length > 1) {
161
- this.tokens.push({
162
- type: 'space'
163
- });
164
- }
35
+ exports.defaults = _getDefaults();
36
+ function changeDefaults(newDefaults) {
37
+ exports.defaults = newDefaults;
165
38
  }
166
39
 
167
- // code
168
- if (cap = this.rules.code.exec(src)) {
169
- src = src.substring(cap[0].length);
170
- cap = cap[0].replace(/^ {4}/gm, '');
171
- this.tokens.push({
172
- type: 'code',
173
- text: !this.options.pedantic
174
- ? cap.replace(/\n+$/, '')
175
- : cap
176
- });
177
- continue;
178
- }
179
-
180
- // fences (gfm)
181
- if (cap = this.rules.fences.exec(src)) {
182
- src = src.substring(cap[0].length);
183
- this.tokens.push({
184
- type: 'code',
185
- lang: cap[2],
186
- text: cap[3]
187
- });
188
- continue;
189
- }
190
-
191
- // heading
192
- if (cap = this.rules.heading.exec(src)) {
193
- src = src.substring(cap[0].length);
194
- this.tokens.push({
195
- type: 'heading',
196
- depth: cap[1].length,
197
- text: cap[2]
198
- });
199
- continue;
200
- }
201
-
202
- // table no leading pipe (gfm)
203
- if (top && (cap = this.rules.nptable.exec(src))) {
204
- src = src.substring(cap[0].length);
205
-
206
- item = {
207
- type: 'table',
208
- header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
209
- align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
210
- cells: cap[3].replace(/\n$/, '').split('\n')
211
- };
212
-
213
- for (i = 0; i < item.align.length; i++) {
214
- if (/^ *-+: *$/.test(item.align[i])) {
215
- item.align[i] = 'right';
216
- } else if (/^ *:-+: *$/.test(item.align[i])) {
217
- item.align[i] = 'center';
218
- } else if (/^ *:-+ *$/.test(item.align[i])) {
219
- item.align[i] = 'left';
220
- } else {
221
- item.align[i] = null;
222
- }
223
- }
224
-
225
- for (i = 0; i < item.cells.length; i++) {
226
- item.cells[i] = item.cells[i].split(/ *\| */);
227
- }
228
-
229
- this.tokens.push(item);
230
-
231
- continue;
40
+ /**
41
+ * Helpers
42
+ */
43
+ const escapeTest = /[&<>"']/;
44
+ const escapeReplace = new RegExp(escapeTest.source, 'g');
45
+ const escapeTestNoEncode = /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/;
46
+ const escapeReplaceNoEncode = new RegExp(escapeTestNoEncode.source, 'g');
47
+ const escapeReplacements = {
48
+ '&': '&amp;',
49
+ '<': '&lt;',
50
+ '>': '&gt;',
51
+ '"': '&quot;',
52
+ "'": '&#39;'
53
+ };
54
+ const getEscapeReplacement = (ch) => escapeReplacements[ch];
55
+ function escape(html, encode) {
56
+ if (encode) {
57
+ if (escapeTest.test(html)) {
58
+ return html.replace(escapeReplace, getEscapeReplacement);
59
+ }
60
+ }
61
+ else {
62
+ if (escapeTestNoEncode.test(html)) {
63
+ return html.replace(escapeReplaceNoEncode, getEscapeReplacement);
64
+ }
65
+ }
66
+ return html;
232
67
  }
233
-
234
- // lheading
235
- if (cap = this.rules.lheading.exec(src)) {
236
- src = src.substring(cap[0].length);
237
- this.tokens.push({
238
- type: 'heading',
239
- depth: cap[2] === '=' ? 1 : 2,
240
- text: cap[1]
241
- });
242
- continue;
68
+ const unescapeTest = /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig;
69
+ function unescape(html) {
70
+ // explicitly match decimal, hex, and named HTML entities
71
+ return html.replace(unescapeTest, (_, n) => {
72
+ n = n.toLowerCase();
73
+ if (n === 'colon')
74
+ return ':';
75
+ if (n.charAt(0) === '#') {
76
+ return n.charAt(1) === 'x'
77
+ ? String.fromCharCode(parseInt(n.substring(2), 16))
78
+ : String.fromCharCode(+n.substring(1));
79
+ }
80
+ return '';
81
+ });
243
82
  }
244
-
245
- // hr
246
- if (cap = this.rules.hr.exec(src)) {
247
- src = src.substring(cap[0].length);
248
- this.tokens.push({
249
- type: 'hr'
250
- });
251
- continue;
83
+ const caret = /(^|[^\[])\^/g;
84
+ function edit(regex, opt) {
85
+ regex = typeof regex === 'string' ? regex : regex.source;
86
+ opt = opt || '';
87
+ const obj = {
88
+ replace: (name, val) => {
89
+ val = typeof val === 'object' && 'source' in val ? val.source : val;
90
+ val = val.replace(caret, '$1');
91
+ regex = regex.replace(name, val);
92
+ return obj;
93
+ },
94
+ getRegex: () => {
95
+ return new RegExp(regex, opt);
96
+ }
97
+ };
98
+ return obj;
252
99
  }
253
-
254
- // blockquote
255
- if (cap = this.rules.blockquote.exec(src)) {
256
- src = src.substring(cap[0].length);
257
-
258
- this.tokens.push({
259
- type: 'blockquote_start'
260
- });
261
-
262
- cap = cap[0].replace(/^ *> ?/gm, '');
263
-
264
- // Pass `top` to keep the current
265
- // "toplevel" state. This is exactly
266
- // how markdown.pl works.
267
- this.token(cap, top);
268
-
269
- this.tokens.push({
270
- type: 'blockquote_end'
271
- });
272
-
273
- continue;
100
+ function cleanUrl(href) {
101
+ try {
102
+ href = encodeURI(href).replace(/%25/g, '%');
103
+ }
104
+ catch (e) {
105
+ return null;
106
+ }
107
+ return href;
274
108
  }
275
-
276
- // list
277
- if (cap = this.rules.list.exec(src)) {
278
- src = src.substring(cap[0].length);
279
- bull = cap[2];
280
-
281
- this.tokens.push({
282
- type: 'list_start',
283
- ordered: bull.length > 1
284
- });
285
-
286
- // Get each top-level item.
287
- cap = cap[0].match(this.rules.item);
288
-
289
- next = false;
290
- l = cap.length;
291
- i = 0;
292
-
293
- for (; i < l; i++) {
294
- item = cap[i];
295
-
296
- // Remove the list item's bullet
297
- // so it is seen as the next token.
298
- space = item.length;
299
- item = item.replace(/^ *([*+-]|\d+\.) +/, '');
300
-
301
- // Outdent whatever the
302
- // list item contains. Hacky.
303
- if (~item.indexOf('\n ')) {
304
- space -= item.length;
305
- item = !this.options.pedantic
306
- ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
307
- : item.replace(/^ {1,4}/gm, '');
109
+ const noopTest = { exec: () => null };
110
+ function splitCells(tableRow, count) {
111
+ // ensure that every cell-delimiting pipe has a space
112
+ // before it to distinguish it from an escaped pipe
113
+ const row = tableRow.replace(/\|/g, (match, offset, str) => {
114
+ let escaped = false;
115
+ let curr = offset;
116
+ while (--curr >= 0 && str[curr] === '\\')
117
+ escaped = !escaped;
118
+ if (escaped) {
119
+ // odd number of slashes means | is escaped
120
+ // so we leave it alone
121
+ return '|';
122
+ }
123
+ else {
124
+ // add space before unescaped |
125
+ return ' |';
126
+ }
127
+ }), cells = row.split(/ \|/);
128
+ let i = 0;
129
+ // First/last cell in a row cannot be empty if it has no leading/trailing pipe
130
+ if (!cells[0].trim()) {
131
+ cells.shift();
308
132
  }
309
-
310
- // Determine whether the next list item belongs here.
311
- // Backpedal if it does not belong in this list.
312
- if (this.options.smartLists && i !== l - 1) {
313
- b = block.bullet.exec(cap[i + 1])[0];
314
- if (bull !== b && !(bull.length > 1 && b.length > 1)) {
315
- src = cap.slice(i + 1).join('\n') + src;
316
- i = l - 1;
317
- }
133
+ if (cells.length > 0 && !cells[cells.length - 1].trim()) {
134
+ cells.pop();
318
135
  }
319
-
320
- // Determine whether item is loose or not.
321
- // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
322
- // for discount behavior.
323
- loose = next || /\n\n(?!\s*$)/.test(item);
324
- if (i !== l - 1) {
325
- next = item.charAt(item.length - 1) === '\n';
326
- if (!loose) loose = next;
136
+ if (count) {
137
+ if (cells.length > count) {
138
+ cells.splice(count);
139
+ }
140
+ else {
141
+ while (cells.length < count)
142
+ cells.push('');
143
+ }
327
144
  }
328
-
329
- this.tokens.push({
330
- type: loose
331
- ? 'loose_item_start'
332
- : 'list_item_start'
333
- });
334
-
335
- // Recurse.
336
- this.token(item, false);
337
-
338
- this.tokens.push({
339
- type: 'list_item_end'
340
- });
341
- }
342
-
343
- this.tokens.push({
344
- type: 'list_end'
345
- });
346
-
347
- continue;
348
- }
349
-
350
- // html
351
- if (cap = this.rules.html.exec(src)) {
352
- src = src.substring(cap[0].length);
353
- this.tokens.push({
354
- type: this.options.sanitize
355
- ? 'paragraph'
356
- : 'html',
357
- pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',
358
- text: cap[0]
359
- });
360
- continue;
361
- }
362
-
363
- // def
364
- if (top && (cap = this.rules.def.exec(src))) {
365
- src = src.substring(cap[0].length);
366
- this.tokens.links[cap[1].toLowerCase()] = {
367
- href: cap[2],
368
- title: cap[3]
369
- };
370
- continue;
371
- }
372
-
373
- // table (gfm)
374
- if (top && (cap = this.rules.table.exec(src))) {
375
- src = src.substring(cap[0].length);
376
-
377
- item = {
378
- type: 'table',
379
- header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
380
- align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
381
- cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
382
- };
383
-
384
- for (i = 0; i < item.align.length; i++) {
385
- if (/^ *-+: *$/.test(item.align[i])) {
386
- item.align[i] = 'right';
387
- } else if (/^ *:-+: *$/.test(item.align[i])) {
388
- item.align[i] = 'center';
389
- } else if (/^ *:-+ *$/.test(item.align[i])) {
390
- item.align[i] = 'left';
391
- } else {
392
- item.align[i] = null;
393
- }
394
- }
395
-
396
- for (i = 0; i < item.cells.length; i++) {
397
- item.cells[i] = item.cells[i]
398
- .replace(/^ *\| *| *\| *$/g, '')
399
- .split(/ *\| */);
400
- }
401
-
402
- this.tokens.push(item);
403
-
404
- continue;
405
- }
406
-
407
- // top-level paragraph
408
- if (top && (cap = this.rules.paragraph.exec(src))) {
409
- src = src.substring(cap[0].length);
410
- this.tokens.push({
411
- type: 'paragraph',
412
- text: cap[1].charAt(cap[1].length - 1) === '\n'
413
- ? cap[1].slice(0, -1)
414
- : cap[1]
415
- });
416
- continue;
417
- }
418
-
419
- // text
420
- if (cap = this.rules.text.exec(src)) {
421
- // Top-level should never reach here.
422
- src = src.substring(cap[0].length);
423
- this.tokens.push({
424
- type: 'text',
425
- text: cap[0]
426
- });
427
- continue;
428
- }
429
-
430
- if (src) {
431
- throw new
432
- Error('Infinite loop on byte: ' + src.charCodeAt(0));
433
- }
434
- }
435
-
436
- return this.tokens;
437
- };
438
-
439
- /**
440
- * Inline-Level Grammar
441
- */
442
-
443
- var inline = {
444
- escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
445
- autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
446
- url: noop,
447
- tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
448
- link: /^!?\[(inside)\]\(href\)/,
449
- reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
450
- nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
451
- strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
452
- em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
453
- code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
454
- br: /^ {2,}\n(?!\s*$)/,
455
- del: noop,
456
- text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
457
- };
458
-
459
- inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
460
- inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
461
-
462
- inline.link = replace(inline.link)
463
- ('inside', inline._inside)
464
- ('href', inline._href)
465
- ();
466
-
467
- inline.reflink = replace(inline.reflink)
468
- ('inside', inline._inside)
469
- ();
470
-
471
- /**
472
- * Normal Inline Grammar
473
- */
474
-
475
- inline.normal = merge({}, inline);
476
-
477
- /**
478
- * Pedantic Inline Grammar
479
- */
480
-
481
- inline.pedantic = merge({}, inline.normal, {
482
- strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
483
- em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
484
- });
485
-
486
- /**
487
- * GFM Inline Grammar
488
- */
489
-
490
- inline.gfm = merge({}, inline.normal, {
491
- escape: replace(inline.escape)('])', '~|])')(),
492
- url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
493
- del: /^~~(?=\S)([\s\S]*?\S)~~/,
494
- text: replace(inline.text)
495
- (']|', '~]|')
496
- ('|', '|https?://|')
497
- ()
498
- });
499
-
500
- /**
501
- * GFM + Line Breaks Inline Grammar
502
- */
503
-
504
- inline.breaks = merge({}, inline.gfm, {
505
- br: replace(inline.br)('{2,}', '*')(),
506
- text: replace(inline.gfm.text)('{2,}', '*')()
507
- });
508
-
509
- /**
510
- * Inline Lexer & Compiler
511
- */
512
-
513
- function InlineLexer(links, options) {
514
- this.options = options || marked.defaults;
515
- this.links = links;
516
- this.rules = inline.normal;
517
-
518
- if (!this.links) {
519
- throw new
520
- Error('Tokens array requires a `links` property.');
521
- }
522
-
523
- if (this.options.gfm) {
524
- if (this.options.breaks) {
525
- this.rules = inline.breaks;
526
- } else {
527
- this.rules = inline.gfm;
528
- }
529
- } else if (this.options.pedantic) {
530
- this.rules = inline.pedantic;
531
- }
532
- }
533
-
534
- /**
535
- * Expose Inline Rules
536
- */
537
-
538
- InlineLexer.rules = inline;
539
-
540
- /**
541
- * Static Lexing/Compiling Method
542
- */
543
-
544
- InlineLexer.output = function(src, links, options) {
545
- var inline = new InlineLexer(links, options);
546
- return inline.output(src);
547
- };
548
-
549
- /**
550
- * Lexing/Compiling
551
- */
552
-
553
- InlineLexer.prototype.output = function(src) {
554
- var out = ''
555
- , link
556
- , text
557
- , href
558
- , cap;
559
-
560
- while (src) {
561
- // escape
562
- if (cap = this.rules.escape.exec(src)) {
563
- src = src.substring(cap[0].length);
564
- out += cap[1];
565
- continue;
566
- }
567
-
568
- // autolink
569
- if (cap = this.rules.autolink.exec(src)) {
570
- src = src.substring(cap[0].length);
571
- if (cap[2] === '@') {
572
- text = cap[1].charAt(6) === ':'
573
- ? this.mangle(cap[1].substring(7))
574
- : this.mangle(cap[1]);
575
- href = this.mangle('mailto:') + text;
576
- } else {
577
- text = escape(cap[1]);
578
- href = text;
579
- }
580
- out += '<a href="'
581
- + href
582
- + '">'
583
- + text
584
- + '</a>';
585
- continue;
586
- }
587
-
588
- // url (gfm)
589
- if (cap = this.rules.url.exec(src)) {
590
- src = src.substring(cap[0].length);
591
- text = escape(cap[1]);
592
- href = text;
593
- out += '<a href="'
594
- + href
595
- + '">'
596
- + text
597
- + '</a>';
598
- continue;
599
- }
600
-
601
- // tag
602
- if (cap = this.rules.tag.exec(src)) {
603
- src = src.substring(cap[0].length);
604
- out += this.options.sanitize
605
- ? escape(cap[0])
606
- : cap[0];
607
- continue;
608
- }
609
-
610
- // link
611
- if (cap = this.rules.link.exec(src)) {
612
- src = src.substring(cap[0].length);
613
- out += this.outputLink(cap, {
614
- href: cap[2],
615
- title: cap[3]
616
- });
617
- continue;
618
- }
619
-
620
- // reflink, nolink
621
- if ((cap = this.rules.reflink.exec(src))
622
- || (cap = this.rules.nolink.exec(src))) {
623
- src = src.substring(cap[0].length);
624
- link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
625
- link = this.links[link.toLowerCase()];
626
- if (!link || !link.href) {
627
- out += cap[0].charAt(0);
628
- src = cap[0].substring(1) + src;
629
- continue;
630
- }
631
- out += this.outputLink(cap, link);
632
- continue;
633
- }
634
-
635
- // strong
636
- if (cap = this.rules.strong.exec(src)) {
637
- src = src.substring(cap[0].length);
638
- out += '<strong>'
639
- + this.output(cap[2] || cap[1])
640
- + '</strong>';
641
- continue;
642
- }
643
-
644
- // em
645
- if (cap = this.rules.em.exec(src)) {
646
- src = src.substring(cap[0].length);
647
- out += '<em>'
648
- + this.output(cap[2] || cap[1])
649
- + '</em>';
650
- continue;
651
- }
652
-
653
- // code
654
- if (cap = this.rules.code.exec(src)) {
655
- src = src.substring(cap[0].length);
656
- out += '<code>'
657
- + escape(cap[2], true)
658
- + '</code>';
659
- continue;
660
- }
661
-
662
- // br
663
- if (cap = this.rules.br.exec(src)) {
664
- src = src.substring(cap[0].length);
665
- out += '<br>';
666
- continue;
667
- }
668
-
669
- // del (gfm)
670
- if (cap = this.rules.del.exec(src)) {
671
- src = src.substring(cap[0].length);
672
- out += '<del>'
673
- + this.output(cap[1])
674
- + '</del>';
675
- continue;
676
- }
677
-
678
- // text
679
- if (cap = this.rules.text.exec(src)) {
680
- src = src.substring(cap[0].length);
681
- out += escape(this.smartypants(cap[0]));
682
- continue;
145
+ for (; i < cells.length; i++) {
146
+ // leading or trailing whitespace is ignored per the gfm spec
147
+ cells[i] = cells[i].trim().replace(/\\\|/g, '|');
148
+ }
149
+ return cells;
683
150
  }
684
-
685
- if (src) {
686
- throw new
687
- Error('Infinite loop on byte: ' + src.charCodeAt(0));
151
+ /**
152
+ * Remove trailing 'c's. Equivalent to str.replace(/c*$/, '').
153
+ * /c*$/ is vulnerable to REDOS.
154
+ *
155
+ * @param str
156
+ * @param c
157
+ * @param invert Remove suffix of non-c chars instead. Default falsey.
158
+ */
159
+ function rtrim(str, c, invert) {
160
+ const l = str.length;
161
+ if (l === 0) {
162
+ return '';
163
+ }
164
+ // Length of suffix matching the invert condition.
165
+ let suffLen = 0;
166
+ // Step left until we fail to match the invert condition.
167
+ while (suffLen < l) {
168
+ const currChar = str.charAt(l - suffLen - 1);
169
+ if (currChar === c && !invert) {
170
+ suffLen++;
171
+ }
172
+ else if (currChar !== c && invert) {
173
+ suffLen++;
174
+ }
175
+ else {
176
+ break;
177
+ }
178
+ }
179
+ return str.slice(0, l - suffLen);
688
180
  }
689
- }
690
-
691
- return out;
692
- };
693
-
694
- /**
695
- * Compile Link
696
- */
697
-
698
- InlineLexer.prototype.outputLink = function(cap, link) {
699
- if (cap[0].charAt(0) !== '!') {
700
- return '<a href="'
701
- + escape(link.href)
702
- + '"'
703
- + (link.title
704
- ? ' title="'
705
- + escape(link.title)
706
- + '"'
707
- : '')
708
- + '>'
709
- + this.output(cap[1])
710
- + '</a>';
711
- } else {
712
- return '<img src="'
713
- + escape(link.href)
714
- + '" alt="'
715
- + escape(cap[1])
716
- + '"'
717
- + (link.title
718
- ? ' title="'
719
- + escape(link.title)
720
- + '"'
721
- : '')
722
- + '>';
723
- }
724
- };
725
-
726
- /**
727
- * Smartypants Transformations
728
- */
729
-
730
- InlineLexer.prototype.smartypants = function(text) {
731
- if (!this.options.smartypants) return text;
732
- return text
733
- // em-dashes
734
- .replace(/--/g, '\u2014')
735
- // opening singles
736
- .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
737
- // closing singles & apostrophes
738
- .replace(/'/g, '\u2019')
739
- // opening doubles
740
- .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
741
- // closing doubles
742
- .replace(/"/g, '\u201d')
743
- // ellipses
744
- .replace(/\.{3}/g, '\u2026');
745
- };
746
-
747
- /**
748
- * Mangle Links
749
- */
750
-
751
- InlineLexer.prototype.mangle = function(text) {
752
- var out = ''
753
- , l = text.length
754
- , i = 0
755
- , ch;
756
-
757
- for (; i < l; i++) {
758
- ch = text.charCodeAt(i);
759
- if (Math.random() > 0.5) {
760
- ch = 'x' + ch.toString(16);
181
+ function findClosingBracket(str, b) {
182
+ if (str.indexOf(b[1]) === -1) {
183
+ return -1;
184
+ }
185
+ let level = 0;
186
+ for (let i = 0; i < str.length; i++) {
187
+ if (str[i] === '\\') {
188
+ i++;
189
+ }
190
+ else if (str[i] === b[0]) {
191
+ level++;
192
+ }
193
+ else if (str[i] === b[1]) {
194
+ level--;
195
+ if (level < 0) {
196
+ return i;
197
+ }
198
+ }
199
+ }
200
+ return -1;
761
201
  }
762
- out += '&#' + ch + ';';
763
- }
764
-
765
- return out;
766
- };
767
-
768
- /**
769
- * Parsing & Compiling
770
- */
771
-
772
- function Parser(options) {
773
- this.tokens = [];
774
- this.token = null;
775
- this.options = options || marked.defaults;
776
- }
777
202
 
778
- /**
779
- * Static Parse Method
780
- */
781
-
782
- Parser.parse = function(src, options) {
783
- var parser = new Parser(options);
784
- return parser.parse(src);
785
- };
786
-
787
- /**
788
- * Parse Loop
789
- */
790
-
791
- Parser.prototype.parse = function(src) {
792
- this.inline = new InlineLexer(src.links, this.options);
793
- this.tokens = src.reverse();
794
-
795
- var out = '';
796
- while (this.next()) {
797
- out += this.tok();
798
- }
799
-
800
- return out;
801
- };
802
-
803
- /**
804
- * Next Token
805
- */
806
-
807
- Parser.prototype.next = function() {
808
- return this.token = this.tokens.pop();
809
- };
810
-
811
- /**
812
- * Preview Next Token
813
- */
814
-
815
- Parser.prototype.peek = function() {
816
- return this.tokens[this.tokens.length - 1] || 0;
817
- };
818
-
819
- /**
820
- * Parse Text Tokens
821
- */
822
-
823
- Parser.prototype.parseText = function() {
824
- var body = this.token.text;
825
-
826
- while (this.peek().type === 'text') {
827
- body += '\n' + this.next().text;
828
- }
829
-
830
- return this.inline.output(body);
831
- };
832
-
833
- /**
834
- * Parse Current Token
835
- */
836
-
837
- Parser.prototype.tok = function() {
838
- switch (this.token.type) {
839
- case 'space': {
840
- return '';
841
- }
842
- case 'hr': {
843
- return '<hr>\n';
844
- }
845
- case 'heading': {
846
- return '<h'
847
- + this.token.depth
848
- + ' id="'
849
- + this.token.text.toLowerCase().replace(/[^\w]+/g, '-')
850
- + '">'
851
- + this.inline.output(this.token.text)
852
- + '</h'
853
- + this.token.depth
854
- + '>\n';
203
+ function outputLink(cap, link, raw, lexer) {
204
+ const href = link.href;
205
+ const title = link.title ? escape(link.title) : null;
206
+ const text = cap[1].replace(/\\([\[\]])/g, '$1');
207
+ if (cap[0].charAt(0) !== '!') {
208
+ lexer.state.inLink = true;
209
+ const token = {
210
+ type: 'link',
211
+ raw,
212
+ href,
213
+ title,
214
+ text,
215
+ tokens: lexer.inlineTokens(text)
216
+ };
217
+ lexer.state.inLink = false;
218
+ return token;
219
+ }
220
+ return {
221
+ type: 'image',
222
+ raw,
223
+ href,
224
+ title,
225
+ text: escape(text)
226
+ };
855
227
  }
856
- case 'code': {
857
- if (this.options.highlight) {
858
- var code = this.options.highlight(this.token.text, this.token.lang);
859
- if (code != null && code !== this.token.text) {
860
- this.token.escaped = true;
861
- this.token.text = code;
862
- }
863
- }
864
-
865
- if (!this.token.escaped) {
866
- this.token.text = escape(this.token.text, true);
867
- }
868
-
869
- return '<pre><code'
870
- + (this.token.lang
871
- ? ' class="'
872
- + this.options.langPrefix
873
- + this.token.lang
874
- + '"'
875
- : '')
876
- + '>'
877
- + this.token.text
878
- + '</code></pre>\n';
228
+ function indentCodeCompensation(raw, text) {
229
+ const matchIndentToCode = raw.match(/^(\s+)(?:```)/);
230
+ if (matchIndentToCode === null) {
231
+ return text;
232
+ }
233
+ const indentToCode = matchIndentToCode[1];
234
+ return text
235
+ .split('\n')
236
+ .map(node => {
237
+ const matchIndentInNode = node.match(/^\s+/);
238
+ if (matchIndentInNode === null) {
239
+ return node;
240
+ }
241
+ const [indentInNode] = matchIndentInNode;
242
+ if (indentInNode.length >= indentToCode.length) {
243
+ return node.slice(indentToCode.length);
244
+ }
245
+ return node;
246
+ })
247
+ .join('\n');
879
248
  }
880
- case 'table': {
881
- var body = ''
882
- , heading
883
- , i
884
- , row
885
- , cell
886
- , j;
887
-
888
- // header
889
- body += '<thead>\n<tr>\n';
890
- for (i = 0; i < this.token.header.length; i++) {
891
- heading = this.inline.output(this.token.header[i]);
892
- body += '<th';
893
- if (this.token.align[i]) {
894
- body += ' style="text-align:' + this.token.align[i] + '"';
895
- }
896
- body += '>' + heading + '</th>\n';
897
- }
898
- body += '</tr>\n</thead>\n';
899
-
900
- // body
901
- body += '<tbody>\n'
902
- for (i = 0; i < this.token.cells.length; i++) {
903
- row = this.token.cells[i];
904
- body += '<tr>\n';
905
- for (j = 0; j < row.length; j++) {
906
- cell = this.inline.output(row[j]);
907
- body += '<td';
908
- if (this.token.align[j]) {
909
- body += ' style="text-align:' + this.token.align[j] + '"';
910
- }
911
- body += '>' + cell + '</td>\n';
912
- }
913
- body += '</tr>\n';
914
- }
915
- body += '</tbody>\n';
916
-
917
- return '<table>\n'
918
- + body
919
- + '</table>\n';
249
+ /**
250
+ * Tokenizer
251
+ */
252
+ class _Tokenizer {
253
+ options;
254
+ // TODO: Fix this rules type
255
+ rules;
256
+ lexer;
257
+ constructor(options) {
258
+ this.options = options || exports.defaults;
259
+ }
260
+ space(src) {
261
+ const cap = this.rules.block.newline.exec(src);
262
+ if (cap && cap[0].length > 0) {
263
+ return {
264
+ type: 'space',
265
+ raw: cap[0]
266
+ };
267
+ }
268
+ }
269
+ code(src) {
270
+ const cap = this.rules.block.code.exec(src);
271
+ if (cap) {
272
+ const text = cap[0].replace(/^ {1,4}/gm, '');
273
+ return {
274
+ type: 'code',
275
+ raw: cap[0],
276
+ codeBlockStyle: 'indented',
277
+ text: !this.options.pedantic
278
+ ? rtrim(text, '\n')
279
+ : text
280
+ };
281
+ }
282
+ }
283
+ fences(src) {
284
+ const cap = this.rules.block.fences.exec(src);
285
+ if (cap) {
286
+ const raw = cap[0];
287
+ const text = indentCodeCompensation(raw, cap[3] || '');
288
+ return {
289
+ type: 'code',
290
+ raw,
291
+ lang: cap[2] ? cap[2].trim().replace(this.rules.inline._escapes, '$1') : cap[2],
292
+ text
293
+ };
294
+ }
295
+ }
296
+ heading(src) {
297
+ const cap = this.rules.block.heading.exec(src);
298
+ if (cap) {
299
+ let text = cap[2].trim();
300
+ // remove trailing #s
301
+ if (/#$/.test(text)) {
302
+ const trimmed = rtrim(text, '#');
303
+ if (this.options.pedantic) {
304
+ text = trimmed.trim();
305
+ }
306
+ else if (!trimmed || / $/.test(trimmed)) {
307
+ // CommonMark requires space before trailing #s
308
+ text = trimmed.trim();
309
+ }
310
+ }
311
+ return {
312
+ type: 'heading',
313
+ raw: cap[0],
314
+ depth: cap[1].length,
315
+ text,
316
+ tokens: this.lexer.inline(text)
317
+ };
318
+ }
319
+ }
320
+ hr(src) {
321
+ const cap = this.rules.block.hr.exec(src);
322
+ if (cap) {
323
+ return {
324
+ type: 'hr',
325
+ raw: cap[0]
326
+ };
327
+ }
328
+ }
329
+ blockquote(src) {
330
+ const cap = this.rules.block.blockquote.exec(src);
331
+ if (cap) {
332
+ const text = rtrim(cap[0].replace(/^ *>[ \t]?/gm, ''), '\n');
333
+ const top = this.lexer.state.top;
334
+ this.lexer.state.top = true;
335
+ const tokens = this.lexer.blockTokens(text);
336
+ this.lexer.state.top = top;
337
+ return {
338
+ type: 'blockquote',
339
+ raw: cap[0],
340
+ tokens,
341
+ text
342
+ };
343
+ }
344
+ }
345
+ list(src) {
346
+ let cap = this.rules.block.list.exec(src);
347
+ if (cap) {
348
+ let bull = cap[1].trim();
349
+ const isordered = bull.length > 1;
350
+ const list = {
351
+ type: 'list',
352
+ raw: '',
353
+ ordered: isordered,
354
+ start: isordered ? +bull.slice(0, -1) : '',
355
+ loose: false,
356
+ items: []
357
+ };
358
+ bull = isordered ? `\\d{1,9}\\${bull.slice(-1)}` : `\\${bull}`;
359
+ if (this.options.pedantic) {
360
+ bull = isordered ? bull : '[*+-]';
361
+ }
362
+ // Get next list item
363
+ const itemRegex = new RegExp(`^( {0,3}${bull})((?:[\t ][^\\n]*)?(?:\\n|$))`);
364
+ let raw = '';
365
+ let itemContents = '';
366
+ let endsWithBlankLine = false;
367
+ // Check if current bullet point can start a new List Item
368
+ while (src) {
369
+ let endEarly = false;
370
+ if (!(cap = itemRegex.exec(src))) {
371
+ break;
372
+ }
373
+ if (this.rules.block.hr.test(src)) { // End list if bullet was actually HR (possibly move into itemRegex?)
374
+ break;
375
+ }
376
+ raw = cap[0];
377
+ src = src.substring(raw.length);
378
+ let line = cap[2].split('\n', 1)[0].replace(/^\t+/, (t) => ' '.repeat(3 * t.length));
379
+ let nextLine = src.split('\n', 1)[0];
380
+ let indent = 0;
381
+ if (this.options.pedantic) {
382
+ indent = 2;
383
+ itemContents = line.trimStart();
384
+ }
385
+ else {
386
+ indent = cap[2].search(/[^ ]/); // Find first non-space char
387
+ indent = indent > 4 ? 1 : indent; // Treat indented code blocks (> 4 spaces) as having only 1 indent
388
+ itemContents = line.slice(indent);
389
+ indent += cap[1].length;
390
+ }
391
+ let blankLine = false;
392
+ if (!line && /^ *$/.test(nextLine)) { // Items begin with at most one blank line
393
+ raw += nextLine + '\n';
394
+ src = src.substring(nextLine.length + 1);
395
+ endEarly = true;
396
+ }
397
+ if (!endEarly) {
398
+ const nextBulletRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ \t][^\\n]*)?(?:\\n|$))`);
399
+ const hrRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`);
400
+ const fencesBeginRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:\`\`\`|~~~)`);
401
+ const headingBeginRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`);
402
+ // Check if following lines should be included in List Item
403
+ while (src) {
404
+ const rawLine = src.split('\n', 1)[0];
405
+ nextLine = rawLine;
406
+ // Re-align to follow commonmark nesting rules
407
+ if (this.options.pedantic) {
408
+ nextLine = nextLine.replace(/^ {1,4}(?=( {4})*[^ ])/g, ' ');
409
+ }
410
+ // End list item if found code fences
411
+ if (fencesBeginRegex.test(nextLine)) {
412
+ break;
413
+ }
414
+ // End list item if found start of new heading
415
+ if (headingBeginRegex.test(nextLine)) {
416
+ break;
417
+ }
418
+ // End list item if found start of new bullet
419
+ if (nextBulletRegex.test(nextLine)) {
420
+ break;
421
+ }
422
+ // Horizontal rule found
423
+ if (hrRegex.test(src)) {
424
+ break;
425
+ }
426
+ if (nextLine.search(/[^ ]/) >= indent || !nextLine.trim()) { // Dedent if possible
427
+ itemContents += '\n' + nextLine.slice(indent);
428
+ }
429
+ else {
430
+ // not enough indentation
431
+ if (blankLine) {
432
+ break;
433
+ }
434
+ // paragraph continuation unless last line was a different block level element
435
+ if (line.search(/[^ ]/) >= 4) { // indented code block
436
+ break;
437
+ }
438
+ if (fencesBeginRegex.test(line)) {
439
+ break;
440
+ }
441
+ if (headingBeginRegex.test(line)) {
442
+ break;
443
+ }
444
+ if (hrRegex.test(line)) {
445
+ break;
446
+ }
447
+ itemContents += '\n' + nextLine;
448
+ }
449
+ if (!blankLine && !nextLine.trim()) { // Check if current line is blank
450
+ blankLine = true;
451
+ }
452
+ raw += rawLine + '\n';
453
+ src = src.substring(rawLine.length + 1);
454
+ line = nextLine.slice(indent);
455
+ }
456
+ }
457
+ if (!list.loose) {
458
+ // If the previous item ended with a blank line, the list is loose
459
+ if (endsWithBlankLine) {
460
+ list.loose = true;
461
+ }
462
+ else if (/\n *\n *$/.test(raw)) {
463
+ endsWithBlankLine = true;
464
+ }
465
+ }
466
+ let istask = null;
467
+ let ischecked;
468
+ // Check for task list items
469
+ if (this.options.gfm) {
470
+ istask = /^\[[ xX]\] /.exec(itemContents);
471
+ if (istask) {
472
+ ischecked = istask[0] !== '[ ] ';
473
+ itemContents = itemContents.replace(/^\[[ xX]\] +/, '');
474
+ }
475
+ }
476
+ list.items.push({
477
+ type: 'list_item',
478
+ raw,
479
+ task: !!istask,
480
+ checked: ischecked,
481
+ loose: false,
482
+ text: itemContents,
483
+ tokens: []
484
+ });
485
+ list.raw += raw;
486
+ }
487
+ // Do not consume newlines at end of final item. Alternatively, make itemRegex *start* with any newlines to simplify/speed up endsWithBlankLine logic
488
+ list.items[list.items.length - 1].raw = raw.trimEnd();
489
+ list.items[list.items.length - 1].text = itemContents.trimEnd();
490
+ list.raw = list.raw.trimEnd();
491
+ // Item child tokens handled here at end because we needed to have the final item to trim it first
492
+ for (let i = 0; i < list.items.length; i++) {
493
+ this.lexer.state.top = false;
494
+ list.items[i].tokens = this.lexer.blockTokens(list.items[i].text, []);
495
+ if (!list.loose) {
496
+ // Check if list should be loose
497
+ const spacers = list.items[i].tokens.filter(t => t.type === 'space');
498
+ const hasMultipleLineBreaks = spacers.length > 0 && spacers.some(t => /\n.*\n/.test(t.raw));
499
+ list.loose = hasMultipleLineBreaks;
500
+ }
501
+ }
502
+ // Set all items to loose if list is loose
503
+ if (list.loose) {
504
+ for (let i = 0; i < list.items.length; i++) {
505
+ list.items[i].loose = true;
506
+ }
507
+ }
508
+ return list;
509
+ }
510
+ }
511
+ html(src) {
512
+ const cap = this.rules.block.html.exec(src);
513
+ if (cap) {
514
+ const token = {
515
+ type: 'html',
516
+ block: true,
517
+ raw: cap[0],
518
+ pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',
519
+ text: cap[0]
520
+ };
521
+ return token;
522
+ }
523
+ }
524
+ def(src) {
525
+ const cap = this.rules.block.def.exec(src);
526
+ if (cap) {
527
+ const tag = cap[1].toLowerCase().replace(/\s+/g, ' ');
528
+ const href = cap[2] ? cap[2].replace(/^<(.*)>$/, '$1').replace(this.rules.inline._escapes, '$1') : '';
529
+ const title = cap[3] ? cap[3].substring(1, cap[3].length - 1).replace(this.rules.inline._escapes, '$1') : cap[3];
530
+ return {
531
+ type: 'def',
532
+ tag,
533
+ raw: cap[0],
534
+ href,
535
+ title
536
+ };
537
+ }
538
+ }
539
+ table(src) {
540
+ const cap = this.rules.block.table.exec(src);
541
+ if (cap) {
542
+ if (!/[:|]/.test(cap[2])) {
543
+ // delimiter row must have a pipe (|) or colon (:) otherwise it is a setext heading
544
+ return;
545
+ }
546
+ const item = {
547
+ type: 'table',
548
+ raw: cap[0],
549
+ header: splitCells(cap[1]).map(c => {
550
+ return { text: c, tokens: [] };
551
+ }),
552
+ align: cap[2].replace(/^\||\| *$/g, '').split('|'),
553
+ rows: cap[3] && cap[3].trim() ? cap[3].replace(/\n[ \t]*$/, '').split('\n') : []
554
+ };
555
+ if (item.header.length === item.align.length) {
556
+ let l = item.align.length;
557
+ let i, j, k, row;
558
+ for (i = 0; i < l; i++) {
559
+ const align = item.align[i];
560
+ if (align) {
561
+ if (/^ *-+: *$/.test(align)) {
562
+ item.align[i] = 'right';
563
+ }
564
+ else if (/^ *:-+: *$/.test(align)) {
565
+ item.align[i] = 'center';
566
+ }
567
+ else if (/^ *:-+ *$/.test(align)) {
568
+ item.align[i] = 'left';
569
+ }
570
+ else {
571
+ item.align[i] = null;
572
+ }
573
+ }
574
+ }
575
+ l = item.rows.length;
576
+ for (i = 0; i < l; i++) {
577
+ item.rows[i] = splitCells(item.rows[i], item.header.length).map(c => {
578
+ return { text: c, tokens: [] };
579
+ });
580
+ }
581
+ // parse child tokens inside headers and cells
582
+ // header child tokens
583
+ l = item.header.length;
584
+ for (j = 0; j < l; j++) {
585
+ item.header[j].tokens = this.lexer.inline(item.header[j].text);
586
+ }
587
+ // cell child tokens
588
+ l = item.rows.length;
589
+ for (j = 0; j < l; j++) {
590
+ row = item.rows[j];
591
+ for (k = 0; k < row.length; k++) {
592
+ row[k].tokens = this.lexer.inline(row[k].text);
593
+ }
594
+ }
595
+ return item;
596
+ }
597
+ }
598
+ }
599
+ lheading(src) {
600
+ const cap = this.rules.block.lheading.exec(src);
601
+ if (cap) {
602
+ return {
603
+ type: 'heading',
604
+ raw: cap[0],
605
+ depth: cap[2].charAt(0) === '=' ? 1 : 2,
606
+ text: cap[1],
607
+ tokens: this.lexer.inline(cap[1])
608
+ };
609
+ }
610
+ }
611
+ paragraph(src) {
612
+ const cap = this.rules.block.paragraph.exec(src);
613
+ if (cap) {
614
+ const text = cap[1].charAt(cap[1].length - 1) === '\n'
615
+ ? cap[1].slice(0, -1)
616
+ : cap[1];
617
+ return {
618
+ type: 'paragraph',
619
+ raw: cap[0],
620
+ text,
621
+ tokens: this.lexer.inline(text)
622
+ };
623
+ }
624
+ }
625
+ text(src) {
626
+ const cap = this.rules.block.text.exec(src);
627
+ if (cap) {
628
+ return {
629
+ type: 'text',
630
+ raw: cap[0],
631
+ text: cap[0],
632
+ tokens: this.lexer.inline(cap[0])
633
+ };
634
+ }
635
+ }
636
+ escape(src) {
637
+ const cap = this.rules.inline.escape.exec(src);
638
+ if (cap) {
639
+ return {
640
+ type: 'escape',
641
+ raw: cap[0],
642
+ text: escape(cap[1])
643
+ };
644
+ }
645
+ }
646
+ tag(src) {
647
+ const cap = this.rules.inline.tag.exec(src);
648
+ if (cap) {
649
+ if (!this.lexer.state.inLink && /^<a /i.test(cap[0])) {
650
+ this.lexer.state.inLink = true;
651
+ }
652
+ else if (this.lexer.state.inLink && /^<\/a>/i.test(cap[0])) {
653
+ this.lexer.state.inLink = false;
654
+ }
655
+ if (!this.lexer.state.inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
656
+ this.lexer.state.inRawBlock = true;
657
+ }
658
+ else if (this.lexer.state.inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
659
+ this.lexer.state.inRawBlock = false;
660
+ }
661
+ return {
662
+ type: 'html',
663
+ raw: cap[0],
664
+ inLink: this.lexer.state.inLink,
665
+ inRawBlock: this.lexer.state.inRawBlock,
666
+ block: false,
667
+ text: cap[0]
668
+ };
669
+ }
670
+ }
671
+ link(src) {
672
+ const cap = this.rules.inline.link.exec(src);
673
+ if (cap) {
674
+ const trimmedUrl = cap[2].trim();
675
+ if (!this.options.pedantic && /^</.test(trimmedUrl)) {
676
+ // commonmark requires matching angle brackets
677
+ if (!(/>$/.test(trimmedUrl))) {
678
+ return;
679
+ }
680
+ // ending angle bracket cannot be escaped
681
+ const rtrimSlash = rtrim(trimmedUrl.slice(0, -1), '\\');
682
+ if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) {
683
+ return;
684
+ }
685
+ }
686
+ else {
687
+ // find closing parenthesis
688
+ const lastParenIndex = findClosingBracket(cap[2], '()');
689
+ if (lastParenIndex > -1) {
690
+ const start = cap[0].indexOf('!') === 0 ? 5 : 4;
691
+ const linkLen = start + cap[1].length + lastParenIndex;
692
+ cap[2] = cap[2].substring(0, lastParenIndex);
693
+ cap[0] = cap[0].substring(0, linkLen).trim();
694
+ cap[3] = '';
695
+ }
696
+ }
697
+ let href = cap[2];
698
+ let title = '';
699
+ if (this.options.pedantic) {
700
+ // split pedantic href and title
701
+ const link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href);
702
+ if (link) {
703
+ href = link[1];
704
+ title = link[3];
705
+ }
706
+ }
707
+ else {
708
+ title = cap[3] ? cap[3].slice(1, -1) : '';
709
+ }
710
+ href = href.trim();
711
+ if (/^</.test(href)) {
712
+ if (this.options.pedantic && !(/>$/.test(trimmedUrl))) {
713
+ // pedantic allows starting angle bracket without ending angle bracket
714
+ href = href.slice(1);
715
+ }
716
+ else {
717
+ href = href.slice(1, -1);
718
+ }
719
+ }
720
+ return outputLink(cap, {
721
+ href: href ? href.replace(this.rules.inline._escapes, '$1') : href,
722
+ title: title ? title.replace(this.rules.inline._escapes, '$1') : title
723
+ }, cap[0], this.lexer);
724
+ }
725
+ }
726
+ reflink(src, links) {
727
+ let cap;
728
+ if ((cap = this.rules.inline.reflink.exec(src))
729
+ || (cap = this.rules.inline.nolink.exec(src))) {
730
+ let link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
731
+ link = links[link.toLowerCase()];
732
+ if (!link) {
733
+ const text = cap[0].charAt(0);
734
+ return {
735
+ type: 'text',
736
+ raw: text,
737
+ text
738
+ };
739
+ }
740
+ return outputLink(cap, link, cap[0], this.lexer);
741
+ }
742
+ }
743
+ emStrong(src, maskedSrc, prevChar = '') {
744
+ let match = this.rules.inline.emStrong.lDelim.exec(src);
745
+ if (!match)
746
+ return;
747
+ // _ can't be between two alphanumerics. \p{L}\p{N} includes non-english alphabet/numbers as well
748
+ if (match[3] && prevChar.match(/[\p{L}\p{N}]/u))
749
+ return;
750
+ const nextChar = match[1] || match[2] || '';
751
+ if (!nextChar || !prevChar || this.rules.inline.punctuation.exec(prevChar)) {
752
+ // unicode Regex counts emoji as 1 char; spread into array for proper count (used multiple times below)
753
+ const lLength = [...match[0]].length - 1;
754
+ let rDelim, rLength, delimTotal = lLength, midDelimTotal = 0;
755
+ const endReg = match[0][0] === '*' ? this.rules.inline.emStrong.rDelimAst : this.rules.inline.emStrong.rDelimUnd;
756
+ endReg.lastIndex = 0;
757
+ // Clip maskedSrc to same section of string as src (move to lexer?)
758
+ maskedSrc = maskedSrc.slice(-1 * src.length + match[0].length - 1);
759
+ while ((match = endReg.exec(maskedSrc)) != null) {
760
+ rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6];
761
+ if (!rDelim)
762
+ continue; // skip single * in __abc*abc__
763
+ rLength = [...rDelim].length;
764
+ if (match[3] || match[4]) { // found another Left Delim
765
+ delimTotal += rLength;
766
+ continue;
767
+ }
768
+ else if (match[5] || match[6]) { // either Left or Right Delim
769
+ if (lLength % 3 && !((lLength + rLength) % 3)) {
770
+ midDelimTotal += rLength;
771
+ continue; // CommonMark Emphasis Rules 9-10
772
+ }
773
+ }
774
+ delimTotal -= rLength;
775
+ if (delimTotal > 0)
776
+ continue; // Haven't found enough closing delimiters
777
+ // Remove extra characters. *a*** -> *a*
778
+ rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal);
779
+ const raw = [...src].slice(0, lLength + match.index + rLength + 1).join('');
780
+ // Create `em` if smallest delimiter has odd char count. *a***
781
+ if (Math.min(lLength, rLength) % 2) {
782
+ const text = raw.slice(1, -1);
783
+ return {
784
+ type: 'em',
785
+ raw,
786
+ text,
787
+ tokens: this.lexer.inlineTokens(text)
788
+ };
789
+ }
790
+ // Create 'strong' if smallest delimiter has even char count. **a***
791
+ const text = raw.slice(2, -2);
792
+ return {
793
+ type: 'strong',
794
+ raw,
795
+ text,
796
+ tokens: this.lexer.inlineTokens(text)
797
+ };
798
+ }
799
+ }
800
+ }
801
+ codespan(src) {
802
+ const cap = this.rules.inline.code.exec(src);
803
+ if (cap) {
804
+ let text = cap[2].replace(/\n/g, ' ');
805
+ const hasNonSpaceChars = /[^ ]/.test(text);
806
+ const hasSpaceCharsOnBothEnds = /^ /.test(text) && / $/.test(text);
807
+ if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {
808
+ text = text.substring(1, text.length - 1);
809
+ }
810
+ text = escape(text, true);
811
+ return {
812
+ type: 'codespan',
813
+ raw: cap[0],
814
+ text
815
+ };
816
+ }
817
+ }
818
+ br(src) {
819
+ const cap = this.rules.inline.br.exec(src);
820
+ if (cap) {
821
+ return {
822
+ type: 'br',
823
+ raw: cap[0]
824
+ };
825
+ }
826
+ }
827
+ del(src) {
828
+ const cap = this.rules.inline.del.exec(src);
829
+ if (cap) {
830
+ return {
831
+ type: 'del',
832
+ raw: cap[0],
833
+ text: cap[2],
834
+ tokens: this.lexer.inlineTokens(cap[2])
835
+ };
836
+ }
837
+ }
838
+ autolink(src) {
839
+ const cap = this.rules.inline.autolink.exec(src);
840
+ if (cap) {
841
+ let text, href;
842
+ if (cap[2] === '@') {
843
+ text = escape(cap[1]);
844
+ href = 'mailto:' + text;
845
+ }
846
+ else {
847
+ text = escape(cap[1]);
848
+ href = text;
849
+ }
850
+ return {
851
+ type: 'link',
852
+ raw: cap[0],
853
+ text,
854
+ href,
855
+ tokens: [
856
+ {
857
+ type: 'text',
858
+ raw: text,
859
+ text
860
+ }
861
+ ]
862
+ };
863
+ }
864
+ }
865
+ url(src) {
866
+ let cap;
867
+ if (cap = this.rules.inline.url.exec(src)) {
868
+ let text, href;
869
+ if (cap[2] === '@') {
870
+ text = escape(cap[0]);
871
+ href = 'mailto:' + text;
872
+ }
873
+ else {
874
+ // do extended autolink path validation
875
+ let prevCapZero;
876
+ do {
877
+ prevCapZero = cap[0];
878
+ cap[0] = this.rules.inline._backpedal.exec(cap[0])[0];
879
+ } while (prevCapZero !== cap[0]);
880
+ text = escape(cap[0]);
881
+ if (cap[1] === 'www.') {
882
+ href = 'http://' + cap[0];
883
+ }
884
+ else {
885
+ href = cap[0];
886
+ }
887
+ }
888
+ return {
889
+ type: 'link',
890
+ raw: cap[0],
891
+ text,
892
+ href,
893
+ tokens: [
894
+ {
895
+ type: 'text',
896
+ raw: text,
897
+ text
898
+ }
899
+ ]
900
+ };
901
+ }
902
+ }
903
+ inlineText(src) {
904
+ const cap = this.rules.inline.text.exec(src);
905
+ if (cap) {
906
+ let text;
907
+ if (this.lexer.state.inRawBlock) {
908
+ text = cap[0];
909
+ }
910
+ else {
911
+ text = escape(cap[0]);
912
+ }
913
+ return {
914
+ type: 'text',
915
+ raw: cap[0],
916
+ text
917
+ };
918
+ }
919
+ }
920
920
  }
921
- case 'blockquote_start': {
922
- var body = '';
923
921
 
924
- while (this.next().type !== 'blockquote_end') {
925
- body += this.tok();
926
- }
922
+ /**
923
+ * Block-Level Grammar
924
+ */
925
+ // Not all rules are defined in the object literal
926
+ // @ts-expect-error
927
+ const block = {
928
+ newline: /^(?: *(?:\n|$))+/,
929
+ code: /^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,
930
+ fences: /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,
931
+ hr: /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,
932
+ heading: /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,
933
+ blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,
934
+ list: /^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/,
935
+ html: '^ {0,3}(?:' // optional indentation
936
+ + '<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)' // (1)
937
+ + '|comment[^\\n]*(\\n+|$)' // (2)
938
+ + '|<\\?[\\s\\S]*?(?:\\?>\\n*|$)' // (3)
939
+ + '|<![A-Z][\\s\\S]*?(?:>\\n*|$)' // (4)
940
+ + '|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)' // (5)
941
+ + '|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (6)
942
+ + '|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (7) open tag
943
+ + '|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (7) closing tag
944
+ + ')',
945
+ def: /^ {0,3}\[(label)\]: *(?:\n *)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n *)?| *\n *)(title))? *(?:\n+|$)/,
946
+ table: noopTest,
947
+ lheading: /^(?!bull )((?:.|\n(?!\s*?\n|bull ))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,
948
+ // regex template, placeholders will be replaced according to different paragraph
949
+ // interruption rules of commonmark and the original markdown spec:
950
+ _paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,
951
+ text: /^[^\n]+/
952
+ };
953
+ block._label = /(?!\s*\])(?:\\.|[^\[\]\\])+/;
954
+ block._title = /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/;
955
+ block.def = edit(block.def)
956
+ .replace('label', block._label)
957
+ .replace('title', block._title)
958
+ .getRegex();
959
+ block.bullet = /(?:[*+-]|\d{1,9}[.)])/;
960
+ block.listItemStart = edit(/^( *)(bull) */)
961
+ .replace('bull', block.bullet)
962
+ .getRegex();
963
+ block.list = edit(block.list)
964
+ .replace(/bull/g, block.bullet)
965
+ .replace('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))')
966
+ .replace('def', '\\n+(?=' + block.def.source + ')')
967
+ .getRegex();
968
+ block._tag = 'address|article|aside|base|basefont|blockquote|body|caption'
969
+ + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption'
970
+ + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe'
971
+ + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option'
972
+ + '|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr'
973
+ + '|track|ul';
974
+ block._comment = /<!--(?!-?>)[\s\S]*?(?:-->|$)/;
975
+ block.html = edit(block.html, 'i')
976
+ .replace('comment', block._comment)
977
+ .replace('tag', block._tag)
978
+ .replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/)
979
+ .getRegex();
980
+ block.lheading = edit(block.lheading)
981
+ .replace(/bull/g, block.bullet) // lists can interrupt
982
+ .getRegex();
983
+ block.paragraph = edit(block._paragraph)
984
+ .replace('hr', block.hr)
985
+ .replace('heading', ' {0,3}#{1,6} ')
986
+ .replace('|lheading', '') // setex headings don't interrupt commonmark paragraphs
987
+ .replace('|table', '')
988
+ .replace('blockquote', ' {0,3}>')
989
+ .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n')
990
+ .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
991
+ .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)')
992
+ .replace('tag', block._tag) // pars can be interrupted by type (6) html blocks
993
+ .getRegex();
994
+ block.blockquote = edit(block.blockquote)
995
+ .replace('paragraph', block.paragraph)
996
+ .getRegex();
997
+ /**
998
+ * Normal Block Grammar
999
+ */
1000
+ block.normal = { ...block };
1001
+ /**
1002
+ * GFM Block Grammar
1003
+ */
1004
+ block.gfm = {
1005
+ ...block.normal,
1006
+ table: '^ *([^\\n ].*)\\n' // Header
1007
+ + ' {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)' // Align
1008
+ + '(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)' // Cells
1009
+ };
1010
+ block.gfm.table = edit(block.gfm.table)
1011
+ .replace('hr', block.hr)
1012
+ .replace('heading', ' {0,3}#{1,6} ')
1013
+ .replace('blockquote', ' {0,3}>')
1014
+ .replace('code', ' {4}[^\\n]')
1015
+ .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n')
1016
+ .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
1017
+ .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)')
1018
+ .replace('tag', block._tag) // tables can be interrupted by type (6) html blocks
1019
+ .getRegex();
1020
+ block.gfm.paragraph = edit(block._paragraph)
1021
+ .replace('hr', block.hr)
1022
+ .replace('heading', ' {0,3}#{1,6} ')
1023
+ .replace('|lheading', '') // setex headings don't interrupt commonmark paragraphs
1024
+ .replace('table', block.gfm.table) // interrupt paragraphs with table
1025
+ .replace('blockquote', ' {0,3}>')
1026
+ .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n')
1027
+ .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
1028
+ .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)')
1029
+ .replace('tag', block._tag) // pars can be interrupted by type (6) html blocks
1030
+ .getRegex();
1031
+ /**
1032
+ * Pedantic grammar (original John Gruber's loose markdown specification)
1033
+ */
1034
+ block.pedantic = {
1035
+ ...block.normal,
1036
+ html: edit('^ *(?:comment *(?:\\n|\\s*$)'
1037
+ + '|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)' // closed tag
1038
+ + '|<tag(?:"[^"]*"|\'[^\']*\'|\\s[^\'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))')
1039
+ .replace('comment', block._comment)
1040
+ .replace(/tag/g, '(?!(?:'
1041
+ + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub'
1042
+ + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)'
1043
+ + '\\b)\\w+(?!:|[^\\w\\s@]*@)\\b')
1044
+ .getRegex(),
1045
+ def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,
1046
+ heading: /^(#{1,6})(.*)(?:\n+|$)/,
1047
+ fences: noopTest,
1048
+ lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,
1049
+ paragraph: edit(block.normal._paragraph)
1050
+ .replace('hr', block.hr)
1051
+ .replace('heading', ' *#{1,6} *[^\n]')
1052
+ .replace('lheading', block.lheading)
1053
+ .replace('blockquote', ' {0,3}>')
1054
+ .replace('|fences', '')
1055
+ .replace('|list', '')
1056
+ .replace('|html', '')
1057
+ .getRegex()
1058
+ };
1059
+ /**
1060
+ * Inline-Level Grammar
1061
+ */
1062
+ // Not all rules are defined in the object literal
1063
+ // @ts-expect-error
1064
+ const inline = {
1065
+ escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,
1066
+ autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/,
1067
+ url: noopTest,
1068
+ tag: '^comment'
1069
+ + '|^</[a-zA-Z][\\w:-]*\\s*>' // self-closing tag
1070
+ + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag
1071
+ + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. <?php ?>
1072
+ + '|^<![a-zA-Z]+\\s[\\s\\S]*?>' // declaration, e.g. <!DOCTYPE html>
1073
+ + '|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>',
1074
+ link: /^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,
1075
+ reflink: /^!?\[(label)\]\[(ref)\]/,
1076
+ nolink: /^!?\[(ref)\](?:\[\])?/,
1077
+ reflinkSearch: 'reflink|nolink(?!\\()',
1078
+ emStrong: {
1079
+ lDelim: /^(?:\*+(?:((?!\*)[punct])|[^\s*]))|^_+(?:((?!_)[punct])|([^\s_]))/,
1080
+ // (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.
1081
+ // | Skip orphan inside strong | Consume to delim | (1) #*** | (2) a***#, a*** | (3) #***a, ***a | (4) ***# | (5) #***# | (6) a***a
1082
+ rDelimAst: /^[^_*]*?__[^_*]*?\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\*)[punct](\*+)(?=[\s]|$)|[^punct\s](\*+)(?!\*)(?=[punct\s]|$)|(?!\*)[punct\s](\*+)(?=[^punct\s])|[\s](\*+)(?!\*)(?=[punct])|(?!\*)[punct](\*+)(?!\*)(?=[punct])|[^punct\s](\*+)(?=[^punct\s])/,
1083
+ rDelimUnd: /^[^_*]*?\*\*[^_*]*?_[^_*]*?(?=\*\*)|[^_]+(?=[^_])|(?!_)[punct](_+)(?=[\s]|$)|[^punct\s](_+)(?!_)(?=[punct\s]|$)|(?!_)[punct\s](_+)(?=[^punct\s])|[\s](_+)(?!_)(?=[punct])|(?!_)[punct](_+)(?!_)(?=[punct])/ // ^- Not allowed for _
1084
+ },
1085
+ code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,
1086
+ br: /^( {2,}|\\)\n(?!\s*$)/,
1087
+ del: noopTest,
1088
+ text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,
1089
+ punctuation: /^((?![*_])[\spunctuation])/
1090
+ };
1091
+ // list of unicode punctuation marks, plus any missing characters from CommonMark spec
1092
+ inline._punctuation = '\\p{P}$+<=>`^|~';
1093
+ inline.punctuation = edit(inline.punctuation, 'u').replace(/punctuation/g, inline._punctuation).getRegex();
1094
+ // sequences em should skip over [title](link), `code`, <html>
1095
+ inline.blockSkip = /\[[^[\]]*?\]\([^\(\)]*?\)|`[^`]*?`|<[^<>]*?>/g;
1096
+ inline.anyPunctuation = /\\[punct]/g;
1097
+ inline._escapes = /\\([punct])/g;
1098
+ inline._comment = edit(block._comment).replace('(?:-->|$)', '-->').getRegex();
1099
+ inline.emStrong.lDelim = edit(inline.emStrong.lDelim, 'u')
1100
+ .replace(/punct/g, inline._punctuation)
1101
+ .getRegex();
1102
+ inline.emStrong.rDelimAst = edit(inline.emStrong.rDelimAst, 'gu')
1103
+ .replace(/punct/g, inline._punctuation)
1104
+ .getRegex();
1105
+ inline.emStrong.rDelimUnd = edit(inline.emStrong.rDelimUnd, 'gu')
1106
+ .replace(/punct/g, inline._punctuation)
1107
+ .getRegex();
1108
+ inline.anyPunctuation = edit(inline.anyPunctuation, 'gu')
1109
+ .replace(/punct/g, inline._punctuation)
1110
+ .getRegex();
1111
+ inline._escapes = edit(inline._escapes, 'gu')
1112
+ .replace(/punct/g, inline._punctuation)
1113
+ .getRegex();
1114
+ inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/;
1115
+ 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])?)+(?![-_])/;
1116
+ inline.autolink = edit(inline.autolink)
1117
+ .replace('scheme', inline._scheme)
1118
+ .replace('email', inline._email)
1119
+ .getRegex();
1120
+ inline._attribute = /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/;
1121
+ inline.tag = edit(inline.tag)
1122
+ .replace('comment', inline._comment)
1123
+ .replace('attribute', inline._attribute)
1124
+ .getRegex();
1125
+ inline._label = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
1126
+ inline._href = /<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/;
1127
+ inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/;
1128
+ inline.link = edit(inline.link)
1129
+ .replace('label', inline._label)
1130
+ .replace('href', inline._href)
1131
+ .replace('title', inline._title)
1132
+ .getRegex();
1133
+ inline.reflink = edit(inline.reflink)
1134
+ .replace('label', inline._label)
1135
+ .replace('ref', block._label)
1136
+ .getRegex();
1137
+ inline.nolink = edit(inline.nolink)
1138
+ .replace('ref', block._label)
1139
+ .getRegex();
1140
+ inline.reflinkSearch = edit(inline.reflinkSearch, 'g')
1141
+ .replace('reflink', inline.reflink)
1142
+ .replace('nolink', inline.nolink)
1143
+ .getRegex();
1144
+ /**
1145
+ * Normal Inline Grammar
1146
+ */
1147
+ inline.normal = { ...inline };
1148
+ /**
1149
+ * Pedantic Inline Grammar
1150
+ */
1151
+ inline.pedantic = {
1152
+ ...inline.normal,
1153
+ strong: {
1154
+ start: /^__|\*\*/,
1155
+ middle: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
1156
+ endAst: /\*\*(?!\*)/g,
1157
+ endUnd: /__(?!_)/g
1158
+ },
1159
+ em: {
1160
+ start: /^_|\*/,
1161
+ middle: /^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/,
1162
+ endAst: /\*(?!\*)/g,
1163
+ endUnd: /_(?!_)/g
1164
+ },
1165
+ link: edit(/^!?\[(label)\]\((.*?)\)/)
1166
+ .replace('label', inline._label)
1167
+ .getRegex(),
1168
+ reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/)
1169
+ .replace('label', inline._label)
1170
+ .getRegex()
1171
+ };
1172
+ /**
1173
+ * GFM Inline Grammar
1174
+ */
1175
+ inline.gfm = {
1176
+ ...inline.normal,
1177
+ escape: edit(inline.escape).replace('])', '~|])').getRegex(),
1178
+ _extended_email: /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,
1179
+ url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,
1180
+ _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,
1181
+ del: /^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/,
1182
+ text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/
1183
+ };
1184
+ inline.gfm.url = edit(inline.gfm.url, 'i')
1185
+ .replace('email', inline.gfm._extended_email)
1186
+ .getRegex();
1187
+ /**
1188
+ * GFM + Line Breaks Inline Grammar
1189
+ */
1190
+ inline.breaks = {
1191
+ ...inline.gfm,
1192
+ br: edit(inline.br).replace('{2,}', '*').getRegex(),
1193
+ text: edit(inline.gfm.text)
1194
+ .replace('\\b_', '\\b_| {2,}\\n')
1195
+ .replace(/\{2,\}/g, '*')
1196
+ .getRegex()
1197
+ };
927
1198
 
928
- return '<blockquote>\n'
929
- + body
930
- + '</blockquote>\n';
1199
+ /**
1200
+ * Block Lexer
1201
+ */
1202
+ class _Lexer {
1203
+ tokens;
1204
+ options;
1205
+ state;
1206
+ tokenizer;
1207
+ inlineQueue;
1208
+ constructor(options) {
1209
+ // TokenList cannot be created in one go
1210
+ // @ts-expect-error
1211
+ this.tokens = [];
1212
+ this.tokens.links = Object.create(null);
1213
+ this.options = options || exports.defaults;
1214
+ this.options.tokenizer = this.options.tokenizer || new _Tokenizer();
1215
+ this.tokenizer = this.options.tokenizer;
1216
+ this.tokenizer.options = this.options;
1217
+ this.tokenizer.lexer = this;
1218
+ this.inlineQueue = [];
1219
+ this.state = {
1220
+ inLink: false,
1221
+ inRawBlock: false,
1222
+ top: true
1223
+ };
1224
+ const rules = {
1225
+ block: block.normal,
1226
+ inline: inline.normal
1227
+ };
1228
+ if (this.options.pedantic) {
1229
+ rules.block = block.pedantic;
1230
+ rules.inline = inline.pedantic;
1231
+ }
1232
+ else if (this.options.gfm) {
1233
+ rules.block = block.gfm;
1234
+ if (this.options.breaks) {
1235
+ rules.inline = inline.breaks;
1236
+ }
1237
+ else {
1238
+ rules.inline = inline.gfm;
1239
+ }
1240
+ }
1241
+ this.tokenizer.rules = rules;
1242
+ }
1243
+ /**
1244
+ * Expose Rules
1245
+ */
1246
+ static get rules() {
1247
+ return {
1248
+ block,
1249
+ inline
1250
+ };
1251
+ }
1252
+ /**
1253
+ * Static Lex Method
1254
+ */
1255
+ static lex(src, options) {
1256
+ const lexer = new _Lexer(options);
1257
+ return lexer.lex(src);
1258
+ }
1259
+ /**
1260
+ * Static Lex Inline Method
1261
+ */
1262
+ static lexInline(src, options) {
1263
+ const lexer = new _Lexer(options);
1264
+ return lexer.inlineTokens(src);
1265
+ }
1266
+ /**
1267
+ * Preprocessing
1268
+ */
1269
+ lex(src) {
1270
+ src = src
1271
+ .replace(/\r\n|\r/g, '\n');
1272
+ this.blockTokens(src, this.tokens);
1273
+ let next;
1274
+ while (next = this.inlineQueue.shift()) {
1275
+ this.inlineTokens(next.src, next.tokens);
1276
+ }
1277
+ return this.tokens;
1278
+ }
1279
+ blockTokens(src, tokens = []) {
1280
+ if (this.options.pedantic) {
1281
+ src = src.replace(/\t/g, ' ').replace(/^ +$/gm, '');
1282
+ }
1283
+ else {
1284
+ src = src.replace(/^( *)(\t+)/gm, (_, leading, tabs) => {
1285
+ return leading + ' '.repeat(tabs.length);
1286
+ });
1287
+ }
1288
+ let token;
1289
+ let lastToken;
1290
+ let cutSrc;
1291
+ let lastParagraphClipped;
1292
+ while (src) {
1293
+ if (this.options.extensions
1294
+ && this.options.extensions.block
1295
+ && this.options.extensions.block.some((extTokenizer) => {
1296
+ if (token = extTokenizer.call({ lexer: this }, src, tokens)) {
1297
+ src = src.substring(token.raw.length);
1298
+ tokens.push(token);
1299
+ return true;
1300
+ }
1301
+ return false;
1302
+ })) {
1303
+ continue;
1304
+ }
1305
+ // newline
1306
+ if (token = this.tokenizer.space(src)) {
1307
+ src = src.substring(token.raw.length);
1308
+ if (token.raw.length === 1 && tokens.length > 0) {
1309
+ // if there's a single \n as a spacer, it's terminating the last line,
1310
+ // so move it there so that we don't get unnecessary paragraph tags
1311
+ tokens[tokens.length - 1].raw += '\n';
1312
+ }
1313
+ else {
1314
+ tokens.push(token);
1315
+ }
1316
+ continue;
1317
+ }
1318
+ // code
1319
+ if (token = this.tokenizer.code(src)) {
1320
+ src = src.substring(token.raw.length);
1321
+ lastToken = tokens[tokens.length - 1];
1322
+ // An indented code block cannot interrupt a paragraph.
1323
+ if (lastToken && (lastToken.type === 'paragraph' || lastToken.type === 'text')) {
1324
+ lastToken.raw += '\n' + token.raw;
1325
+ lastToken.text += '\n' + token.text;
1326
+ this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
1327
+ }
1328
+ else {
1329
+ tokens.push(token);
1330
+ }
1331
+ continue;
1332
+ }
1333
+ // fences
1334
+ if (token = this.tokenizer.fences(src)) {
1335
+ src = src.substring(token.raw.length);
1336
+ tokens.push(token);
1337
+ continue;
1338
+ }
1339
+ // heading
1340
+ if (token = this.tokenizer.heading(src)) {
1341
+ src = src.substring(token.raw.length);
1342
+ tokens.push(token);
1343
+ continue;
1344
+ }
1345
+ // hr
1346
+ if (token = this.tokenizer.hr(src)) {
1347
+ src = src.substring(token.raw.length);
1348
+ tokens.push(token);
1349
+ continue;
1350
+ }
1351
+ // blockquote
1352
+ if (token = this.tokenizer.blockquote(src)) {
1353
+ src = src.substring(token.raw.length);
1354
+ tokens.push(token);
1355
+ continue;
1356
+ }
1357
+ // list
1358
+ if (token = this.tokenizer.list(src)) {
1359
+ src = src.substring(token.raw.length);
1360
+ tokens.push(token);
1361
+ continue;
1362
+ }
1363
+ // html
1364
+ if (token = this.tokenizer.html(src)) {
1365
+ src = src.substring(token.raw.length);
1366
+ tokens.push(token);
1367
+ continue;
1368
+ }
1369
+ // def
1370
+ if (token = this.tokenizer.def(src)) {
1371
+ src = src.substring(token.raw.length);
1372
+ lastToken = tokens[tokens.length - 1];
1373
+ if (lastToken && (lastToken.type === 'paragraph' || lastToken.type === 'text')) {
1374
+ lastToken.raw += '\n' + token.raw;
1375
+ lastToken.text += '\n' + token.raw;
1376
+ this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
1377
+ }
1378
+ else if (!this.tokens.links[token.tag]) {
1379
+ this.tokens.links[token.tag] = {
1380
+ href: token.href,
1381
+ title: token.title
1382
+ };
1383
+ }
1384
+ continue;
1385
+ }
1386
+ // table (gfm)
1387
+ if (token = this.tokenizer.table(src)) {
1388
+ src = src.substring(token.raw.length);
1389
+ tokens.push(token);
1390
+ continue;
1391
+ }
1392
+ // lheading
1393
+ if (token = this.tokenizer.lheading(src)) {
1394
+ src = src.substring(token.raw.length);
1395
+ tokens.push(token);
1396
+ continue;
1397
+ }
1398
+ // top-level paragraph
1399
+ // prevent paragraph consuming extensions by clipping 'src' to extension start
1400
+ cutSrc = src;
1401
+ if (this.options.extensions && this.options.extensions.startBlock) {
1402
+ let startIndex = Infinity;
1403
+ const tempSrc = src.slice(1);
1404
+ let tempStart;
1405
+ this.options.extensions.startBlock.forEach((getStartIndex) => {
1406
+ tempStart = getStartIndex.call({ lexer: this }, tempSrc);
1407
+ if (typeof tempStart === 'number' && tempStart >= 0) {
1408
+ startIndex = Math.min(startIndex, tempStart);
1409
+ }
1410
+ });
1411
+ if (startIndex < Infinity && startIndex >= 0) {
1412
+ cutSrc = src.substring(0, startIndex + 1);
1413
+ }
1414
+ }
1415
+ if (this.state.top && (token = this.tokenizer.paragraph(cutSrc))) {
1416
+ lastToken = tokens[tokens.length - 1];
1417
+ if (lastParagraphClipped && lastToken.type === 'paragraph') {
1418
+ lastToken.raw += '\n' + token.raw;
1419
+ lastToken.text += '\n' + token.text;
1420
+ this.inlineQueue.pop();
1421
+ this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
1422
+ }
1423
+ else {
1424
+ tokens.push(token);
1425
+ }
1426
+ lastParagraphClipped = (cutSrc.length !== src.length);
1427
+ src = src.substring(token.raw.length);
1428
+ continue;
1429
+ }
1430
+ // text
1431
+ if (token = this.tokenizer.text(src)) {
1432
+ src = src.substring(token.raw.length);
1433
+ lastToken = tokens[tokens.length - 1];
1434
+ if (lastToken && lastToken.type === 'text') {
1435
+ lastToken.raw += '\n' + token.raw;
1436
+ lastToken.text += '\n' + token.text;
1437
+ this.inlineQueue.pop();
1438
+ this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
1439
+ }
1440
+ else {
1441
+ tokens.push(token);
1442
+ }
1443
+ continue;
1444
+ }
1445
+ if (src) {
1446
+ const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
1447
+ if (this.options.silent) {
1448
+ console.error(errMsg);
1449
+ break;
1450
+ }
1451
+ else {
1452
+ throw new Error(errMsg);
1453
+ }
1454
+ }
1455
+ }
1456
+ this.state.top = true;
1457
+ return tokens;
1458
+ }
1459
+ inline(src, tokens = []) {
1460
+ this.inlineQueue.push({ src, tokens });
1461
+ return tokens;
1462
+ }
1463
+ /**
1464
+ * Lexing/Compiling
1465
+ */
1466
+ inlineTokens(src, tokens = []) {
1467
+ let token, lastToken, cutSrc;
1468
+ // String with links masked to avoid interference with em and strong
1469
+ let maskedSrc = src;
1470
+ let match;
1471
+ let keepPrevChar, prevChar;
1472
+ // Mask out reflinks
1473
+ if (this.tokens.links) {
1474
+ const links = Object.keys(this.tokens.links);
1475
+ if (links.length > 0) {
1476
+ while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {
1477
+ if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) {
1478
+ maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);
1479
+ }
1480
+ }
1481
+ }
1482
+ }
1483
+ // Mask out other blocks
1484
+ while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {
1485
+ maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
1486
+ }
1487
+ // Mask out escaped characters
1488
+ while ((match = this.tokenizer.rules.inline.anyPunctuation.exec(maskedSrc)) != null) {
1489
+ maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);
1490
+ }
1491
+ while (src) {
1492
+ if (!keepPrevChar) {
1493
+ prevChar = '';
1494
+ }
1495
+ keepPrevChar = false;
1496
+ // extensions
1497
+ if (this.options.extensions
1498
+ && this.options.extensions.inline
1499
+ && this.options.extensions.inline.some((extTokenizer) => {
1500
+ if (token = extTokenizer.call({ lexer: this }, src, tokens)) {
1501
+ src = src.substring(token.raw.length);
1502
+ tokens.push(token);
1503
+ return true;
1504
+ }
1505
+ return false;
1506
+ })) {
1507
+ continue;
1508
+ }
1509
+ // escape
1510
+ if (token = this.tokenizer.escape(src)) {
1511
+ src = src.substring(token.raw.length);
1512
+ tokens.push(token);
1513
+ continue;
1514
+ }
1515
+ // tag
1516
+ if (token = this.tokenizer.tag(src)) {
1517
+ src = src.substring(token.raw.length);
1518
+ lastToken = tokens[tokens.length - 1];
1519
+ if (lastToken && token.type === 'text' && lastToken.type === 'text') {
1520
+ lastToken.raw += token.raw;
1521
+ lastToken.text += token.text;
1522
+ }
1523
+ else {
1524
+ tokens.push(token);
1525
+ }
1526
+ continue;
1527
+ }
1528
+ // link
1529
+ if (token = this.tokenizer.link(src)) {
1530
+ src = src.substring(token.raw.length);
1531
+ tokens.push(token);
1532
+ continue;
1533
+ }
1534
+ // reflink, nolink
1535
+ if (token = this.tokenizer.reflink(src, this.tokens.links)) {
1536
+ src = src.substring(token.raw.length);
1537
+ lastToken = tokens[tokens.length - 1];
1538
+ if (lastToken && token.type === 'text' && lastToken.type === 'text') {
1539
+ lastToken.raw += token.raw;
1540
+ lastToken.text += token.text;
1541
+ }
1542
+ else {
1543
+ tokens.push(token);
1544
+ }
1545
+ continue;
1546
+ }
1547
+ // em & strong
1548
+ if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) {
1549
+ src = src.substring(token.raw.length);
1550
+ tokens.push(token);
1551
+ continue;
1552
+ }
1553
+ // code
1554
+ if (token = this.tokenizer.codespan(src)) {
1555
+ src = src.substring(token.raw.length);
1556
+ tokens.push(token);
1557
+ continue;
1558
+ }
1559
+ // br
1560
+ if (token = this.tokenizer.br(src)) {
1561
+ src = src.substring(token.raw.length);
1562
+ tokens.push(token);
1563
+ continue;
1564
+ }
1565
+ // del (gfm)
1566
+ if (token = this.tokenizer.del(src)) {
1567
+ src = src.substring(token.raw.length);
1568
+ tokens.push(token);
1569
+ continue;
1570
+ }
1571
+ // autolink
1572
+ if (token = this.tokenizer.autolink(src)) {
1573
+ src = src.substring(token.raw.length);
1574
+ tokens.push(token);
1575
+ continue;
1576
+ }
1577
+ // url (gfm)
1578
+ if (!this.state.inLink && (token = this.tokenizer.url(src))) {
1579
+ src = src.substring(token.raw.length);
1580
+ tokens.push(token);
1581
+ continue;
1582
+ }
1583
+ // text
1584
+ // prevent inlineText consuming extensions by clipping 'src' to extension start
1585
+ cutSrc = src;
1586
+ if (this.options.extensions && this.options.extensions.startInline) {
1587
+ let startIndex = Infinity;
1588
+ const tempSrc = src.slice(1);
1589
+ let tempStart;
1590
+ this.options.extensions.startInline.forEach((getStartIndex) => {
1591
+ tempStart = getStartIndex.call({ lexer: this }, tempSrc);
1592
+ if (typeof tempStart === 'number' && tempStart >= 0) {
1593
+ startIndex = Math.min(startIndex, tempStart);
1594
+ }
1595
+ });
1596
+ if (startIndex < Infinity && startIndex >= 0) {
1597
+ cutSrc = src.substring(0, startIndex + 1);
1598
+ }
1599
+ }
1600
+ if (token = this.tokenizer.inlineText(cutSrc)) {
1601
+ src = src.substring(token.raw.length);
1602
+ if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started
1603
+ prevChar = token.raw.slice(-1);
1604
+ }
1605
+ keepPrevChar = true;
1606
+ lastToken = tokens[tokens.length - 1];
1607
+ if (lastToken && lastToken.type === 'text') {
1608
+ lastToken.raw += token.raw;
1609
+ lastToken.text += token.text;
1610
+ }
1611
+ else {
1612
+ tokens.push(token);
1613
+ }
1614
+ continue;
1615
+ }
1616
+ if (src) {
1617
+ const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
1618
+ if (this.options.silent) {
1619
+ console.error(errMsg);
1620
+ break;
1621
+ }
1622
+ else {
1623
+ throw new Error(errMsg);
1624
+ }
1625
+ }
1626
+ }
1627
+ return tokens;
1628
+ }
931
1629
  }
932
- case 'list_start': {
933
- var type = this.token.ordered ? 'ol' : 'ul'
934
- , body = '';
935
1630
 
936
- while (this.next().type !== 'list_end') {
937
- body += this.tok();
938
- }
939
-
940
- return '<'
941
- + type
942
- + '>\n'
943
- + body
944
- + '</'
945
- + type
946
- + '>\n';
1631
+ /**
1632
+ * Renderer
1633
+ */
1634
+ class _Renderer {
1635
+ options;
1636
+ constructor(options) {
1637
+ this.options = options || exports.defaults;
1638
+ }
1639
+ code(code, infostring, escaped) {
1640
+ const lang = (infostring || '').match(/^\S*/)?.[0];
1641
+ code = code.replace(/\n$/, '') + '\n';
1642
+ if (!lang) {
1643
+ return '<pre><code>'
1644
+ + (escaped ? code : escape(code, true))
1645
+ + '</code></pre>\n';
1646
+ }
1647
+ return '<pre><code class="language-'
1648
+ + escape(lang)
1649
+ + '">'
1650
+ + (escaped ? code : escape(code, true))
1651
+ + '</code></pre>\n';
1652
+ }
1653
+ blockquote(quote) {
1654
+ return `<blockquote>\n${quote}</blockquote>\n`;
1655
+ }
1656
+ html(html, block) {
1657
+ return html;
1658
+ }
1659
+ heading(text, level, raw) {
1660
+ // ignore IDs
1661
+ return `<h${level}>${text}</h${level}>\n`;
1662
+ }
1663
+ hr() {
1664
+ return '<hr>\n';
1665
+ }
1666
+ list(body, ordered, start) {
1667
+ const type = ordered ? 'ol' : 'ul';
1668
+ const startatt = (ordered && start !== 1) ? (' start="' + start + '"') : '';
1669
+ return '<' + type + startatt + '>\n' + body + '</' + type + '>\n';
1670
+ }
1671
+ listitem(text, task, checked) {
1672
+ return `<li>${text}</li>\n`;
1673
+ }
1674
+ checkbox(checked) {
1675
+ return '<input '
1676
+ + (checked ? 'checked="" ' : '')
1677
+ + 'disabled="" type="checkbox">';
1678
+ }
1679
+ paragraph(text) {
1680
+ return `<p>${text}</p>\n`;
1681
+ }
1682
+ table(header, body) {
1683
+ if (body)
1684
+ body = `<tbody>${body}</tbody>`;
1685
+ return '<table>\n'
1686
+ + '<thead>\n'
1687
+ + header
1688
+ + '</thead>\n'
1689
+ + body
1690
+ + '</table>\n';
1691
+ }
1692
+ tablerow(content) {
1693
+ return `<tr>\n${content}</tr>\n`;
1694
+ }
1695
+ tablecell(content, flags) {
1696
+ const type = flags.header ? 'th' : 'td';
1697
+ const tag = flags.align
1698
+ ? `<${type} align="${flags.align}">`
1699
+ : `<${type}>`;
1700
+ return tag + content + `</${type}>\n`;
1701
+ }
1702
+ /**
1703
+ * span level renderer
1704
+ */
1705
+ strong(text) {
1706
+ return `<strong>${text}</strong>`;
1707
+ }
1708
+ em(text) {
1709
+ return `<em>${text}</em>`;
1710
+ }
1711
+ codespan(text) {
1712
+ return `<code>${text}</code>`;
1713
+ }
1714
+ br() {
1715
+ return '<br>';
1716
+ }
1717
+ del(text) {
1718
+ return `<del>${text}</del>`;
1719
+ }
1720
+ link(href, title, text) {
1721
+ const cleanHref = cleanUrl(href);
1722
+ if (cleanHref === null) {
1723
+ return text;
1724
+ }
1725
+ href = cleanHref;
1726
+ let out = '<a href="' + href + '"';
1727
+ if (title) {
1728
+ out += ' title="' + title + '"';
1729
+ }
1730
+ out += '>' + text + '</a>';
1731
+ return out;
1732
+ }
1733
+ image(href, title, text) {
1734
+ const cleanHref = cleanUrl(href);
1735
+ if (cleanHref === null) {
1736
+ return text;
1737
+ }
1738
+ href = cleanHref;
1739
+ let out = `<img src="${href}" alt="${text}"`;
1740
+ if (title) {
1741
+ out += ` title="${title}"`;
1742
+ }
1743
+ out += '>';
1744
+ return out;
1745
+ }
1746
+ text(text) {
1747
+ return text;
1748
+ }
947
1749
  }
948
- case 'list_item_start': {
949
- var body = '';
950
-
951
- while (this.next().type !== 'list_item_end') {
952
- body += this.token.type === 'text'
953
- ? this.parseText()
954
- : this.tok();
955
- }
956
1750
 
957
- return '<li>'
958
- + body
959
- + '</li>\n';
1751
+ /**
1752
+ * TextRenderer
1753
+ * returns only the textual part of the token
1754
+ */
1755
+ class _TextRenderer {
1756
+ // no need for block level renderers
1757
+ strong(text) {
1758
+ return text;
1759
+ }
1760
+ em(text) {
1761
+ return text;
1762
+ }
1763
+ codespan(text) {
1764
+ return text;
1765
+ }
1766
+ del(text) {
1767
+ return text;
1768
+ }
1769
+ html(text) {
1770
+ return text;
1771
+ }
1772
+ text(text) {
1773
+ return text;
1774
+ }
1775
+ link(href, title, text) {
1776
+ return '' + text;
1777
+ }
1778
+ image(href, title, text) {
1779
+ return '' + text;
1780
+ }
1781
+ br() {
1782
+ return '';
1783
+ }
960
1784
  }
961
- case 'loose_item_start': {
962
- var body = '';
963
-
964
- while (this.next().type !== 'list_item_end') {
965
- body += this.tok();
966
- }
967
1785
 
968
- return '<li>'
969
- + body
970
- + '</li>\n';
971
- }
972
- case 'html': {
973
- return !this.token.pre && !this.options.pedantic
974
- ? this.inline.output(this.token.text)
975
- : this.token.text;
976
- }
977
- case 'paragraph': {
978
- return '<p>'
979
- + this.inline.output(this.token.text)
980
- + '</p>\n';
981
- }
982
- case 'text': {
983
- return '<p>'
984
- + this.parseText()
985
- + '</p>\n';
1786
+ /**
1787
+ * Parsing & Compiling
1788
+ */
1789
+ class _Parser {
1790
+ options;
1791
+ renderer;
1792
+ textRenderer;
1793
+ constructor(options) {
1794
+ this.options = options || exports.defaults;
1795
+ this.options.renderer = this.options.renderer || new _Renderer();
1796
+ this.renderer = this.options.renderer;
1797
+ this.renderer.options = this.options;
1798
+ this.textRenderer = new _TextRenderer();
1799
+ }
1800
+ /**
1801
+ * Static Parse Method
1802
+ */
1803
+ static parse(tokens, options) {
1804
+ const parser = new _Parser(options);
1805
+ return parser.parse(tokens);
1806
+ }
1807
+ /**
1808
+ * Static Parse Inline Method
1809
+ */
1810
+ static parseInline(tokens, options) {
1811
+ const parser = new _Parser(options);
1812
+ return parser.parseInline(tokens);
1813
+ }
1814
+ /**
1815
+ * Parse Loop
1816
+ */
1817
+ parse(tokens, top = true) {
1818
+ let out = '';
1819
+ for (let i = 0; i < tokens.length; i++) {
1820
+ const token = tokens[i];
1821
+ // Run any renderer extensions
1822
+ if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {
1823
+ const genericToken = token;
1824
+ const ret = this.options.extensions.renderers[genericToken.type].call({ parser: this }, genericToken);
1825
+ if (ret !== false || !['space', 'hr', 'heading', 'code', 'table', 'blockquote', 'list', 'html', 'paragraph', 'text'].includes(genericToken.type)) {
1826
+ out += ret || '';
1827
+ continue;
1828
+ }
1829
+ }
1830
+ switch (token.type) {
1831
+ case 'space': {
1832
+ continue;
1833
+ }
1834
+ case 'hr': {
1835
+ out += this.renderer.hr();
1836
+ continue;
1837
+ }
1838
+ case 'heading': {
1839
+ const headingToken = token;
1840
+ out += this.renderer.heading(this.parseInline(headingToken.tokens), headingToken.depth, unescape(this.parseInline(headingToken.tokens, this.textRenderer)));
1841
+ continue;
1842
+ }
1843
+ case 'code': {
1844
+ const codeToken = token;
1845
+ out += this.renderer.code(codeToken.text, codeToken.lang, !!codeToken.escaped);
1846
+ continue;
1847
+ }
1848
+ case 'table': {
1849
+ const tableToken = token;
1850
+ let header = '';
1851
+ // header
1852
+ let cell = '';
1853
+ for (let j = 0; j < tableToken.header.length; j++) {
1854
+ cell += this.renderer.tablecell(this.parseInline(tableToken.header[j].tokens), { header: true, align: tableToken.align[j] });
1855
+ }
1856
+ header += this.renderer.tablerow(cell);
1857
+ let body = '';
1858
+ for (let j = 0; j < tableToken.rows.length; j++) {
1859
+ const row = tableToken.rows[j];
1860
+ cell = '';
1861
+ for (let k = 0; k < row.length; k++) {
1862
+ cell += this.renderer.tablecell(this.parseInline(row[k].tokens), { header: false, align: tableToken.align[k] });
1863
+ }
1864
+ body += this.renderer.tablerow(cell);
1865
+ }
1866
+ out += this.renderer.table(header, body);
1867
+ continue;
1868
+ }
1869
+ case 'blockquote': {
1870
+ const blockquoteToken = token;
1871
+ const body = this.parse(blockquoteToken.tokens);
1872
+ out += this.renderer.blockquote(body);
1873
+ continue;
1874
+ }
1875
+ case 'list': {
1876
+ const listToken = token;
1877
+ const ordered = listToken.ordered;
1878
+ const start = listToken.start;
1879
+ const loose = listToken.loose;
1880
+ let body = '';
1881
+ for (let j = 0; j < listToken.items.length; j++) {
1882
+ const item = listToken.items[j];
1883
+ const checked = item.checked;
1884
+ const task = item.task;
1885
+ let itemBody = '';
1886
+ if (item.task) {
1887
+ const checkbox = this.renderer.checkbox(!!checked);
1888
+ if (loose) {
1889
+ if (item.tokens.length > 0 && item.tokens[0].type === 'paragraph') {
1890
+ item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
1891
+ if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {
1892
+ item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text;
1893
+ }
1894
+ }
1895
+ else {
1896
+ item.tokens.unshift({
1897
+ type: 'text',
1898
+ text: checkbox + ' '
1899
+ });
1900
+ }
1901
+ }
1902
+ else {
1903
+ itemBody += checkbox + ' ';
1904
+ }
1905
+ }
1906
+ itemBody += this.parse(item.tokens, loose);
1907
+ body += this.renderer.listitem(itemBody, task, !!checked);
1908
+ }
1909
+ out += this.renderer.list(body, ordered, start);
1910
+ continue;
1911
+ }
1912
+ case 'html': {
1913
+ const htmlToken = token;
1914
+ out += this.renderer.html(htmlToken.text, htmlToken.block);
1915
+ continue;
1916
+ }
1917
+ case 'paragraph': {
1918
+ const paragraphToken = token;
1919
+ out += this.renderer.paragraph(this.parseInline(paragraphToken.tokens));
1920
+ continue;
1921
+ }
1922
+ case 'text': {
1923
+ let textToken = token;
1924
+ let body = textToken.tokens ? this.parseInline(textToken.tokens) : textToken.text;
1925
+ while (i + 1 < tokens.length && tokens[i + 1].type === 'text') {
1926
+ textToken = tokens[++i];
1927
+ body += '\n' + (textToken.tokens ? this.parseInline(textToken.tokens) : textToken.text);
1928
+ }
1929
+ out += top ? this.renderer.paragraph(body) : body;
1930
+ continue;
1931
+ }
1932
+ default: {
1933
+ const errMsg = 'Token with "' + token.type + '" type was not found.';
1934
+ if (this.options.silent) {
1935
+ console.error(errMsg);
1936
+ return '';
1937
+ }
1938
+ else {
1939
+ throw new Error(errMsg);
1940
+ }
1941
+ }
1942
+ }
1943
+ }
1944
+ return out;
1945
+ }
1946
+ /**
1947
+ * Parse Inline Tokens
1948
+ */
1949
+ parseInline(tokens, renderer) {
1950
+ renderer = renderer || this.renderer;
1951
+ let out = '';
1952
+ for (let i = 0; i < tokens.length; i++) {
1953
+ const token = tokens[i];
1954
+ // Run any renderer extensions
1955
+ if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {
1956
+ const ret = this.options.extensions.renderers[token.type].call({ parser: this }, token);
1957
+ if (ret !== false || !['escape', 'html', 'link', 'image', 'strong', 'em', 'codespan', 'br', 'del', 'text'].includes(token.type)) {
1958
+ out += ret || '';
1959
+ continue;
1960
+ }
1961
+ }
1962
+ switch (token.type) {
1963
+ case 'escape': {
1964
+ const escapeToken = token;
1965
+ out += renderer.text(escapeToken.text);
1966
+ break;
1967
+ }
1968
+ case 'html': {
1969
+ const tagToken = token;
1970
+ out += renderer.html(tagToken.text);
1971
+ break;
1972
+ }
1973
+ case 'link': {
1974
+ const linkToken = token;
1975
+ out += renderer.link(linkToken.href, linkToken.title, this.parseInline(linkToken.tokens, renderer));
1976
+ break;
1977
+ }
1978
+ case 'image': {
1979
+ const imageToken = token;
1980
+ out += renderer.image(imageToken.href, imageToken.title, imageToken.text);
1981
+ break;
1982
+ }
1983
+ case 'strong': {
1984
+ const strongToken = token;
1985
+ out += renderer.strong(this.parseInline(strongToken.tokens, renderer));
1986
+ break;
1987
+ }
1988
+ case 'em': {
1989
+ const emToken = token;
1990
+ out += renderer.em(this.parseInline(emToken.tokens, renderer));
1991
+ break;
1992
+ }
1993
+ case 'codespan': {
1994
+ const codespanToken = token;
1995
+ out += renderer.codespan(codespanToken.text);
1996
+ break;
1997
+ }
1998
+ case 'br': {
1999
+ out += renderer.br();
2000
+ break;
2001
+ }
2002
+ case 'del': {
2003
+ const delToken = token;
2004
+ out += renderer.del(this.parseInline(delToken.tokens, renderer));
2005
+ break;
2006
+ }
2007
+ case 'text': {
2008
+ const textToken = token;
2009
+ out += renderer.text(textToken.text);
2010
+ break;
2011
+ }
2012
+ default: {
2013
+ const errMsg = 'Token with "' + token.type + '" type was not found.';
2014
+ if (this.options.silent) {
2015
+ console.error(errMsg);
2016
+ return '';
2017
+ }
2018
+ else {
2019
+ throw new Error(errMsg);
2020
+ }
2021
+ }
2022
+ }
2023
+ }
2024
+ return out;
2025
+ }
986
2026
  }
987
- }
988
- };
989
-
990
- /**
991
- * Helpers
992
- */
993
-
994
- function escape(html, encode) {
995
- return html
996
- .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;')
997
- .replace(/</g, '&lt;')
998
- .replace(/>/g, '&gt;')
999
- .replace(/"/g, '&quot;')
1000
- .replace(/'/g, '&#39;');
1001
- }
1002
-
1003
- function replace(regex, opt) {
1004
- regex = regex.source;
1005
- opt = opt || '';
1006
- return function self(name, val) {
1007
- if (!name) return new RegExp(regex, opt);
1008
- val = val.source || val;
1009
- val = val.replace(/(^|[^\[])\^/g, '$1');
1010
- regex = regex.replace(name, val);
1011
- return self;
1012
- };
1013
- }
1014
-
1015
- function noop() {}
1016
- noop.exec = noop;
1017
2027
 
1018
- function merge(obj) {
1019
- var i = 1
1020
- , target
1021
- , key;
1022
-
1023
- for (; i < arguments.length; i++) {
1024
- target = arguments[i];
1025
- for (key in target) {
1026
- if (Object.prototype.hasOwnProperty.call(target, key)) {
1027
- obj[key] = target[key];
1028
- }
2028
+ class _Hooks {
2029
+ options;
2030
+ constructor(options) {
2031
+ this.options = options || exports.defaults;
2032
+ }
2033
+ static passThroughHooks = new Set([
2034
+ 'preprocess',
2035
+ 'postprocess'
2036
+ ]);
2037
+ /**
2038
+ * Process markdown before marked
2039
+ */
2040
+ preprocess(markdown) {
2041
+ return markdown;
2042
+ }
2043
+ /**
2044
+ * Process HTML after marked is finished
2045
+ */
2046
+ postprocess(html) {
2047
+ return html;
2048
+ }
1029
2049
  }
1030
- }
1031
-
1032
- return obj;
1033
- }
1034
-
1035
- /**
1036
- * Marked
1037
- */
1038
2050
 
1039
- function marked(src, opt, callback) {
1040
- if (callback || typeof opt === 'function') {
1041
- if (!callback) {
1042
- callback = opt;
1043
- opt = null;
2051
+ class Marked {
2052
+ defaults = _getDefaults();
2053
+ options = this.setOptions;
2054
+ parse = this.#parseMarkdown(_Lexer.lex, _Parser.parse);
2055
+ parseInline = this.#parseMarkdown(_Lexer.lexInline, _Parser.parseInline);
2056
+ Parser = _Parser;
2057
+ parser = _Parser.parse;
2058
+ Renderer = _Renderer;
2059
+ TextRenderer = _TextRenderer;
2060
+ Lexer = _Lexer;
2061
+ lexer = _Lexer.lex;
2062
+ Tokenizer = _Tokenizer;
2063
+ Hooks = _Hooks;
2064
+ constructor(...args) {
2065
+ this.use(...args);
2066
+ }
2067
+ /**
2068
+ * Run callback for every token
2069
+ */
2070
+ walkTokens(tokens, callback) {
2071
+ let values = [];
2072
+ for (const token of tokens) {
2073
+ values = values.concat(callback.call(this, token));
2074
+ switch (token.type) {
2075
+ case 'table': {
2076
+ const tableToken = token;
2077
+ for (const cell of tableToken.header) {
2078
+ values = values.concat(this.walkTokens(cell.tokens, callback));
2079
+ }
2080
+ for (const row of tableToken.rows) {
2081
+ for (const cell of row) {
2082
+ values = values.concat(this.walkTokens(cell.tokens, callback));
2083
+ }
2084
+ }
2085
+ break;
2086
+ }
2087
+ case 'list': {
2088
+ const listToken = token;
2089
+ values = values.concat(this.walkTokens(listToken.items, callback));
2090
+ break;
2091
+ }
2092
+ default: {
2093
+ const genericToken = token;
2094
+ if (this.defaults.extensions?.childTokens?.[genericToken.type]) {
2095
+ this.defaults.extensions.childTokens[genericToken.type].forEach((childTokens) => {
2096
+ values = values.concat(this.walkTokens(genericToken[childTokens], callback));
2097
+ });
2098
+ }
2099
+ else if (genericToken.tokens) {
2100
+ values = values.concat(this.walkTokens(genericToken.tokens, callback));
2101
+ }
2102
+ }
2103
+ }
2104
+ }
2105
+ return values;
2106
+ }
2107
+ use(...args) {
2108
+ const extensions = this.defaults.extensions || { renderers: {}, childTokens: {} };
2109
+ args.forEach((pack) => {
2110
+ // copy options to new object
2111
+ const opts = { ...pack };
2112
+ // set async to true if it was set to true before
2113
+ opts.async = this.defaults.async || opts.async || false;
2114
+ // ==-- Parse "addon" extensions --== //
2115
+ if (pack.extensions) {
2116
+ pack.extensions.forEach((ext) => {
2117
+ if (!ext.name) {
2118
+ throw new Error('extension name required');
2119
+ }
2120
+ if ('renderer' in ext) { // Renderer extensions
2121
+ const prevRenderer = extensions.renderers[ext.name];
2122
+ if (prevRenderer) {
2123
+ // Replace extension with func to run new extension but fall back if false
2124
+ extensions.renderers[ext.name] = function (...args) {
2125
+ let ret = ext.renderer.apply(this, args);
2126
+ if (ret === false) {
2127
+ ret = prevRenderer.apply(this, args);
2128
+ }
2129
+ return ret;
2130
+ };
2131
+ }
2132
+ else {
2133
+ extensions.renderers[ext.name] = ext.renderer;
2134
+ }
2135
+ }
2136
+ if ('tokenizer' in ext) { // Tokenizer Extensions
2137
+ if (!ext.level || (ext.level !== 'block' && ext.level !== 'inline')) {
2138
+ throw new Error("extension level must be 'block' or 'inline'");
2139
+ }
2140
+ const extLevel = extensions[ext.level];
2141
+ if (extLevel) {
2142
+ extLevel.unshift(ext.tokenizer);
2143
+ }
2144
+ else {
2145
+ extensions[ext.level] = [ext.tokenizer];
2146
+ }
2147
+ if (ext.start) { // Function to check for start of token
2148
+ if (ext.level === 'block') {
2149
+ if (extensions.startBlock) {
2150
+ extensions.startBlock.push(ext.start);
2151
+ }
2152
+ else {
2153
+ extensions.startBlock = [ext.start];
2154
+ }
2155
+ }
2156
+ else if (ext.level === 'inline') {
2157
+ if (extensions.startInline) {
2158
+ extensions.startInline.push(ext.start);
2159
+ }
2160
+ else {
2161
+ extensions.startInline = [ext.start];
2162
+ }
2163
+ }
2164
+ }
2165
+ }
2166
+ if ('childTokens' in ext && ext.childTokens) { // Child tokens to be visited by walkTokens
2167
+ extensions.childTokens[ext.name] = ext.childTokens;
2168
+ }
2169
+ });
2170
+ opts.extensions = extensions;
2171
+ }
2172
+ // ==-- Parse "overwrite" extensions --== //
2173
+ if (pack.renderer) {
2174
+ const renderer = this.defaults.renderer || new _Renderer(this.defaults);
2175
+ for (const prop in pack.renderer) {
2176
+ const rendererFunc = pack.renderer[prop];
2177
+ const rendererKey = prop;
2178
+ const prevRenderer = renderer[rendererKey];
2179
+ // Replace renderer with func to run extension, but fall back if false
2180
+ renderer[rendererKey] = (...args) => {
2181
+ let ret = rendererFunc.apply(renderer, args);
2182
+ if (ret === false) {
2183
+ ret = prevRenderer.apply(renderer, args);
2184
+ }
2185
+ return ret || '';
2186
+ };
2187
+ }
2188
+ opts.renderer = renderer;
2189
+ }
2190
+ if (pack.tokenizer) {
2191
+ const tokenizer = this.defaults.tokenizer || new _Tokenizer(this.defaults);
2192
+ for (const prop in pack.tokenizer) {
2193
+ const tokenizerFunc = pack.tokenizer[prop];
2194
+ const tokenizerKey = prop;
2195
+ const prevTokenizer = tokenizer[tokenizerKey];
2196
+ // Replace tokenizer with func to run extension, but fall back if false
2197
+ tokenizer[tokenizerKey] = (...args) => {
2198
+ let ret = tokenizerFunc.apply(tokenizer, args);
2199
+ if (ret === false) {
2200
+ ret = prevTokenizer.apply(tokenizer, args);
2201
+ }
2202
+ return ret;
2203
+ };
2204
+ }
2205
+ opts.tokenizer = tokenizer;
2206
+ }
2207
+ // ==-- Parse Hooks extensions --== //
2208
+ if (pack.hooks) {
2209
+ const hooks = this.defaults.hooks || new _Hooks();
2210
+ for (const prop in pack.hooks) {
2211
+ const hooksFunc = pack.hooks[prop];
2212
+ const hooksKey = prop;
2213
+ const prevHook = hooks[hooksKey];
2214
+ if (_Hooks.passThroughHooks.has(prop)) {
2215
+ hooks[hooksKey] = (arg) => {
2216
+ if (this.defaults.async) {
2217
+ return Promise.resolve(hooksFunc.call(hooks, arg)).then(ret => {
2218
+ return prevHook.call(hooks, ret);
2219
+ });
2220
+ }
2221
+ const ret = hooksFunc.call(hooks, arg);
2222
+ return prevHook.call(hooks, ret);
2223
+ };
2224
+ }
2225
+ else {
2226
+ hooks[hooksKey] = (...args) => {
2227
+ let ret = hooksFunc.apply(hooks, args);
2228
+ if (ret === false) {
2229
+ ret = prevHook.apply(hooks, args);
2230
+ }
2231
+ return ret;
2232
+ };
2233
+ }
2234
+ }
2235
+ opts.hooks = hooks;
2236
+ }
2237
+ // ==-- Parse WalkTokens extensions --== //
2238
+ if (pack.walkTokens) {
2239
+ const walkTokens = this.defaults.walkTokens;
2240
+ const packWalktokens = pack.walkTokens;
2241
+ opts.walkTokens = function (token) {
2242
+ let values = [];
2243
+ values.push(packWalktokens.call(this, token));
2244
+ if (walkTokens) {
2245
+ values = values.concat(walkTokens.call(this, token));
2246
+ }
2247
+ return values;
2248
+ };
2249
+ }
2250
+ this.defaults = { ...this.defaults, ...opts };
2251
+ });
2252
+ return this;
2253
+ }
2254
+ setOptions(opt) {
2255
+ this.defaults = { ...this.defaults, ...opt };
2256
+ return this;
2257
+ }
2258
+ #parseMarkdown(lexer, parser) {
2259
+ return (src, options) => {
2260
+ const origOpt = { ...options };
2261
+ const opt = { ...this.defaults, ...origOpt };
2262
+ // Show warning if an extension set async to true but the parse was called with async: false
2263
+ if (this.defaults.async === true && origOpt.async === false) {
2264
+ if (!opt.silent) {
2265
+ console.warn('marked(): The async option was set to true by an extension. The async: false option sent to parse will be ignored.');
2266
+ }
2267
+ opt.async = true;
2268
+ }
2269
+ const throwError = this.#onError(!!opt.silent, !!opt.async);
2270
+ // throw error in case of non string input
2271
+ if (typeof src === 'undefined' || src === null) {
2272
+ return throwError(new Error('marked(): input parameter is undefined or null'));
2273
+ }
2274
+ if (typeof src !== 'string') {
2275
+ return throwError(new Error('marked(): input parameter is of type '
2276
+ + Object.prototype.toString.call(src) + ', string expected'));
2277
+ }
2278
+ if (opt.hooks) {
2279
+ opt.hooks.options = opt;
2280
+ }
2281
+ if (opt.async) {
2282
+ return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src)
2283
+ .then(src => lexer(src, opt))
2284
+ .then(tokens => opt.walkTokens ? Promise.all(this.walkTokens(tokens, opt.walkTokens)).then(() => tokens) : tokens)
2285
+ .then(tokens => parser(tokens, opt))
2286
+ .then(html => opt.hooks ? opt.hooks.postprocess(html) : html)
2287
+ .catch(throwError);
2288
+ }
2289
+ try {
2290
+ if (opt.hooks) {
2291
+ src = opt.hooks.preprocess(src);
2292
+ }
2293
+ const tokens = lexer(src, opt);
2294
+ if (opt.walkTokens) {
2295
+ this.walkTokens(tokens, opt.walkTokens);
2296
+ }
2297
+ let html = parser(tokens, opt);
2298
+ if (opt.hooks) {
2299
+ html = opt.hooks.postprocess(html);
2300
+ }
2301
+ return html;
2302
+ }
2303
+ catch (e) {
2304
+ return throwError(e);
2305
+ }
2306
+ };
2307
+ }
2308
+ #onError(silent, async) {
2309
+ return (e) => {
2310
+ e.message += '\nPlease report this to https://github.com/markedjs/marked.';
2311
+ if (silent) {
2312
+ const msg = '<p>An error occurred:</p><pre>'
2313
+ + escape(e.message + '', true)
2314
+ + '</pre>';
2315
+ if (async) {
2316
+ return Promise.resolve(msg);
2317
+ }
2318
+ return msg;
2319
+ }
2320
+ if (async) {
2321
+ return Promise.reject(e);
2322
+ }
2323
+ throw e;
2324
+ };
2325
+ }
1044
2326
  }
1045
2327
 
1046
- opt = merge({}, marked.defaults, opt || {});
1047
-
1048
- var highlight = opt.highlight
1049
- , tokens
1050
- , pending
1051
- , i = 0;
1052
-
1053
- try {
1054
- tokens = Lexer.lex(src, opt)
1055
- } catch (e) {
1056
- return callback(e);
2328
+ const markedInstance = new Marked();
2329
+ function marked(src, opt) {
2330
+ return markedInstance.parse(src, opt);
1057
2331
  }
1058
-
1059
- pending = tokens.length;
1060
-
1061
- var done = function() {
1062
- var out, err;
1063
-
1064
- try {
1065
- out = Parser.parse(tokens, opt);
1066
- } catch (e) {
1067
- err = e;
1068
- }
1069
-
1070
- opt.highlight = highlight;
1071
-
1072
- return err
1073
- ? callback(err)
1074
- : callback(null, out);
2332
+ /**
2333
+ * Sets the default options.
2334
+ *
2335
+ * @param options Hash of options
2336
+ */
2337
+ marked.options =
2338
+ marked.setOptions = function (options) {
2339
+ markedInstance.setOptions(options);
2340
+ marked.defaults = markedInstance.defaults;
2341
+ changeDefaults(marked.defaults);
2342
+ return marked;
2343
+ };
2344
+ /**
2345
+ * Gets the original marked default options.
2346
+ */
2347
+ marked.getDefaults = _getDefaults;
2348
+ marked.defaults = exports.defaults;
2349
+ /**
2350
+ * Use Extension
2351
+ */
2352
+ marked.use = function (...args) {
2353
+ markedInstance.use(...args);
2354
+ marked.defaults = markedInstance.defaults;
2355
+ changeDefaults(marked.defaults);
2356
+ return marked;
1075
2357
  };
1076
-
1077
- if (!highlight || highlight.length < 3) {
1078
- return done();
1079
- }
1080
-
1081
- delete opt.highlight;
1082
-
1083
- if (!pending) return done();
1084
-
1085
- for (; i < tokens.length; i++) {
1086
- (function(token) {
1087
- if (token.type !== 'code') {
1088
- return --pending || done();
1089
- }
1090
- return highlight(token.text, token.lang, function(err, code) {
1091
- if (code == null || code === token.text) {
1092
- return --pending || done();
1093
- }
1094
- token.text = code;
1095
- token.escaped = true;
1096
- --pending || done();
1097
- });
1098
- })(tokens[i]);
1099
- }
1100
-
1101
- return;
1102
- }
1103
- try {
1104
- if (opt) opt = merge({}, marked.defaults, opt);
1105
- return Parser.parse(Lexer.lex(src, opt), opt);
1106
- } catch (e) {
1107
- e.message += '\nPlease report this to https://github.com/chjj/marked.';
1108
- if ((opt || marked.defaults).silent) {
1109
- return '<p>An error occured:</p><pre>'
1110
- + escape(e.message + '', true)
1111
- + '</pre>';
1112
- }
1113
- throw e;
1114
- }
1115
- }
1116
-
1117
- /**
1118
- * Options
1119
- */
1120
-
1121
- marked.options =
1122
- marked.setOptions = function(opt) {
1123
- merge(marked.defaults, opt);
1124
- return marked;
1125
- };
1126
-
1127
- marked.defaults = {
1128
- gfm: true,
1129
- tables: true,
1130
- breaks: false,
1131
- pedantic: false,
1132
- sanitize: false,
1133
- smartLists: false,
1134
- silent: false,
1135
- highlight: null,
1136
- langPrefix: 'lang-',
1137
- smartypants: false
1138
- };
1139
-
1140
- /**
1141
- * Expose
1142
- */
1143
-
1144
- marked.Parser = Parser;
1145
- marked.parser = Parser.parse;
1146
-
1147
- marked.Lexer = Lexer;
1148
- marked.lexer = Lexer.lex;
1149
-
1150
- marked.InlineLexer = InlineLexer;
1151
- marked.inlineLexer = InlineLexer.output;
1152
-
1153
- marked.parse = marked;
1154
-
1155
- if (typeof exports === 'object') {
1156
- module.exports = marked;
1157
- } else if (typeof define === 'function' && define.amd) {
1158
- define(function() { return marked; });
1159
- } else {
1160
- this.marked = marked;
1161
- }
1162
-
1163
- }).call(function() {
1164
- return this || (typeof window !== 'undefined' ? window : global);
1165
- }());
2358
+ /**
2359
+ * Run callback for every token
2360
+ */
2361
+ marked.walkTokens = function (tokens, callback) {
2362
+ return markedInstance.walkTokens(tokens, callback);
2363
+ };
2364
+ /**
2365
+ * Compiles markdown to HTML without enclosing `p` tag.
2366
+ *
2367
+ * @param src String of markdown source to be compiled
2368
+ * @param options Hash of options
2369
+ * @return String of compiled HTML
2370
+ */
2371
+ marked.parseInline = markedInstance.parseInline;
2372
+ /**
2373
+ * Expose
2374
+ */
2375
+ marked.Parser = _Parser;
2376
+ marked.parser = _Parser.parse;
2377
+ marked.Renderer = _Renderer;
2378
+ marked.TextRenderer = _TextRenderer;
2379
+ marked.Lexer = _Lexer;
2380
+ marked.lexer = _Lexer.lex;
2381
+ marked.Tokenizer = _Tokenizer;
2382
+ marked.Hooks = _Hooks;
2383
+ marked.parse = marked;
2384
+ const options = marked.options;
2385
+ const setOptions = marked.setOptions;
2386
+ const use = marked.use;
2387
+ const walkTokens = marked.walkTokens;
2388
+ const parseInline = marked.parseInline;
2389
+ const parse = marked;
2390
+ const parser = _Parser.parse;
2391
+ const lexer = _Lexer.lex;
2392
+
2393
+ exports.Hooks = _Hooks;
2394
+ exports.Lexer = _Lexer;
2395
+ exports.Marked = Marked;
2396
+ exports.Parser = _Parser;
2397
+ exports.Renderer = _Renderer;
2398
+ exports.TextRenderer = _TextRenderer;
2399
+ exports.Tokenizer = _Tokenizer;
2400
+ exports.getDefaults = _getDefaults;
2401
+ exports.lexer = lexer;
2402
+ exports.marked = marked;
2403
+ exports.options = options;
2404
+ exports.parse = parse;
2405
+ exports.parseInline = parseInline;
2406
+ exports.parser = parser;
2407
+ exports.setOptions = setOptions;
2408
+ exports.use = use;
2409
+ exports.walkTokens = walkTokens;
2410
+
2411
+ }));
2412
+ //# sourceMappingURL=marked.umd.js.map