marked 0.8.1 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/marked.esm.js CHANGED
@@ -31,6 +31,8 @@ function getDefaults() {
31
31
  silent: false,
32
32
  smartLists: false,
33
33
  smartypants: false,
34
+ tokenizer: null,
35
+ walkTokens: null,
34
36
  xhtml: false
35
37
  };
36
38
  }
@@ -293,6 +295,666 @@ var helpers = {
293
295
  checkSanitizeDeprecation
294
296
  };
295
297
 
298
+ const { defaults: defaults$1 } = defaults;
299
+ const {
300
+ rtrim: rtrim$1,
301
+ splitCells: splitCells$1,
302
+ escape: escape$1,
303
+ findClosingBracket: findClosingBracket$1
304
+ } = helpers;
305
+
306
+ function outputLink(cap, link, raw) {
307
+ const href = link.href;
308
+ const title = link.title ? escape$1(link.title) : null;
309
+ const text = cap[1].replace(/\\([\[\]])/g, '$1');
310
+
311
+ if (cap[0].charAt(0) !== '!') {
312
+ return {
313
+ type: 'link',
314
+ raw,
315
+ href,
316
+ title,
317
+ text
318
+ };
319
+ } else {
320
+ return {
321
+ type: 'image',
322
+ raw,
323
+ href,
324
+ title,
325
+ text: escape$1(text)
326
+ };
327
+ }
328
+ }
329
+
330
+ function indentCodeCompensation(raw, text) {
331
+ const matchIndentToCode = raw.match(/^(\s+)(?:```)/);
332
+
333
+ if (matchIndentToCode === null) {
334
+ return text;
335
+ }
336
+
337
+ const indentToCode = matchIndentToCode[1];
338
+
339
+ return text
340
+ .split('\n')
341
+ .map(node => {
342
+ const matchIndentInNode = node.match(/^\s+/);
343
+ if (matchIndentInNode === null) {
344
+ return node;
345
+ }
346
+
347
+ const [indentInNode] = matchIndentInNode;
348
+
349
+ if (indentInNode.length >= indentToCode.length) {
350
+ return node.slice(indentToCode.length);
351
+ }
352
+
353
+ return node;
354
+ })
355
+ .join('\n');
356
+ }
357
+
358
+ /**
359
+ * Tokenizer
360
+ */
361
+ var Tokenizer_1 = class Tokenizer {
362
+ constructor(options) {
363
+ this.options = options || defaults$1;
364
+ }
365
+
366
+ space(src) {
367
+ const cap = this.rules.block.newline.exec(src);
368
+ if (cap) {
369
+ if (cap[0].length > 1) {
370
+ return {
371
+ type: 'space',
372
+ raw: cap[0]
373
+ };
374
+ }
375
+ return { raw: '\n' };
376
+ }
377
+ }
378
+
379
+ code(src, tokens) {
380
+ const cap = this.rules.block.code.exec(src);
381
+ if (cap) {
382
+ const lastToken = tokens[tokens.length - 1];
383
+ // An indented code block cannot interrupt a paragraph.
384
+ if (lastToken && lastToken.type === 'paragraph') {
385
+ return {
386
+ raw: cap[0],
387
+ text: cap[0].trimRight()
388
+ };
389
+ }
390
+
391
+ const text = cap[0].replace(/^ {4}/gm, '');
392
+ return {
393
+ type: 'code',
394
+ raw: cap[0],
395
+ codeBlockStyle: 'indented',
396
+ text: !this.options.pedantic
397
+ ? rtrim$1(text, '\n')
398
+ : text
399
+ };
400
+ }
401
+ }
402
+
403
+ fences(src) {
404
+ const cap = this.rules.block.fences.exec(src);
405
+ if (cap) {
406
+ const raw = cap[0];
407
+ const text = indentCodeCompensation(raw, cap[3] || '');
408
+
409
+ return {
410
+ type: 'code',
411
+ raw,
412
+ lang: cap[2] ? cap[2].trim() : cap[2],
413
+ text
414
+ };
415
+ }
416
+ }
417
+
418
+ heading(src) {
419
+ const cap = this.rules.block.heading.exec(src);
420
+ if (cap) {
421
+ return {
422
+ type: 'heading',
423
+ raw: cap[0],
424
+ depth: cap[1].length,
425
+ text: cap[2]
426
+ };
427
+ }
428
+ }
429
+
430
+ nptable(src) {
431
+ const cap = this.rules.block.nptable.exec(src);
432
+ if (cap) {
433
+ const item = {
434
+ type: 'table',
435
+ header: splitCells$1(cap[1].replace(/^ *| *\| *$/g, '')),
436
+ align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
437
+ cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : [],
438
+ raw: cap[0]
439
+ };
440
+
441
+ if (item.header.length === item.align.length) {
442
+ let l = item.align.length;
443
+ let i;
444
+ for (i = 0; i < l; i++) {
445
+ if (/^ *-+: *$/.test(item.align[i])) {
446
+ item.align[i] = 'right';
447
+ } else if (/^ *:-+: *$/.test(item.align[i])) {
448
+ item.align[i] = 'center';
449
+ } else if (/^ *:-+ *$/.test(item.align[i])) {
450
+ item.align[i] = 'left';
451
+ } else {
452
+ item.align[i] = null;
453
+ }
454
+ }
455
+
456
+ l = item.cells.length;
457
+ for (i = 0; i < l; i++) {
458
+ item.cells[i] = splitCells$1(item.cells[i], item.header.length);
459
+ }
460
+
461
+ return item;
462
+ }
463
+ }
464
+ }
465
+
466
+ hr(src) {
467
+ const cap = this.rules.block.hr.exec(src);
468
+ if (cap) {
469
+ return {
470
+ type: 'hr',
471
+ raw: cap[0]
472
+ };
473
+ }
474
+ }
475
+
476
+ blockquote(src) {
477
+ const cap = this.rules.block.blockquote.exec(src);
478
+ if (cap) {
479
+ const text = cap[0].replace(/^ *> ?/gm, '');
480
+
481
+ return {
482
+ type: 'blockquote',
483
+ raw: cap[0],
484
+ text
485
+ };
486
+ }
487
+ }
488
+
489
+ list(src) {
490
+ const cap = this.rules.block.list.exec(src);
491
+ if (cap) {
492
+ let raw = cap[0];
493
+ const bull = cap[2];
494
+ const isordered = bull.length > 1;
495
+ const isparen = bull[bull.length - 1] === ')';
496
+
497
+ const list = {
498
+ type: 'list',
499
+ raw,
500
+ ordered: isordered,
501
+ start: isordered ? +bull.slice(0, -1) : '',
502
+ loose: false,
503
+ items: []
504
+ };
505
+
506
+ // Get each top-level item.
507
+ const itemMatch = cap[0].match(this.rules.block.item);
508
+
509
+ let next = false,
510
+ item,
511
+ space,
512
+ b,
513
+ addBack,
514
+ loose,
515
+ istask,
516
+ ischecked;
517
+
518
+ const l = itemMatch.length;
519
+ for (let i = 0; i < l; i++) {
520
+ item = itemMatch[i];
521
+ raw = item;
522
+
523
+ // Remove the list item's bullet
524
+ // so it is seen as the next token.
525
+ space = item.length;
526
+ item = item.replace(/^ *([*+-]|\d+[.)]) */, '');
527
+
528
+ // Outdent whatever the
529
+ // list item contains. Hacky.
530
+ if (~item.indexOf('\n ')) {
531
+ space -= item.length;
532
+ item = !this.options.pedantic
533
+ ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
534
+ : item.replace(/^ {1,4}/gm, '');
535
+ }
536
+
537
+ // Determine whether the next list item belongs here.
538
+ // Backpedal if it does not belong in this list.
539
+ if (i !== l - 1) {
540
+ b = this.rules.block.bullet.exec(itemMatch[i + 1])[0];
541
+ if (isordered ? b.length === 1 || (!isparen && b[b.length - 1] === ')')
542
+ : (b.length > 1 || (this.options.smartLists && b !== bull))) {
543
+ addBack = itemMatch.slice(i + 1).join('\n');
544
+ list.raw = list.raw.substring(0, list.raw.length - addBack.length);
545
+ i = l - 1;
546
+ }
547
+ }
548
+
549
+ // Determine whether item is loose or not.
550
+ // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
551
+ // for discount behavior.
552
+ loose = next || /\n\n(?!\s*$)/.test(item);
553
+ if (i !== l - 1) {
554
+ next = item.charAt(item.length - 1) === '\n';
555
+ if (!loose) loose = next;
556
+ }
557
+
558
+ if (loose) {
559
+ list.loose = true;
560
+ }
561
+
562
+ // Check for task list items
563
+ istask = /^\[[ xX]\] /.test(item);
564
+ ischecked = undefined;
565
+ if (istask) {
566
+ ischecked = item[1] !== ' ';
567
+ item = item.replace(/^\[[ xX]\] +/, '');
568
+ }
569
+
570
+ list.items.push({
571
+ type: 'list_item',
572
+ raw,
573
+ task: istask,
574
+ checked: ischecked,
575
+ loose: loose,
576
+ text: item
577
+ });
578
+ }
579
+
580
+ return list;
581
+ }
582
+ }
583
+
584
+ html(src) {
585
+ const cap = this.rules.block.html.exec(src);
586
+ if (cap) {
587
+ return {
588
+ type: this.options.sanitize
589
+ ? 'paragraph'
590
+ : 'html',
591
+ raw: cap[0],
592
+ pre: !this.options.sanitizer
593
+ && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
594
+ text: this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape$1(cap[0])) : cap[0]
595
+ };
596
+ }
597
+ }
598
+
599
+ def(src) {
600
+ const cap = this.rules.block.def.exec(src);
601
+ if (cap) {
602
+ if (cap[3]) cap[3] = cap[3].substring(1, cap[3].length - 1);
603
+ const tag = cap[1].toLowerCase().replace(/\s+/g, ' ');
604
+ return {
605
+ tag,
606
+ raw: cap[0],
607
+ href: cap[2],
608
+ title: cap[3]
609
+ };
610
+ }
611
+ }
612
+
613
+ table(src) {
614
+ const cap = this.rules.block.table.exec(src);
615
+ if (cap) {
616
+ const item = {
617
+ type: 'table',
618
+ header: splitCells$1(cap[1].replace(/^ *| *\| *$/g, '')),
619
+ align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
620
+ cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : []
621
+ };
622
+
623
+ if (item.header.length === item.align.length) {
624
+ item.raw = cap[0];
625
+
626
+ let l = item.align.length;
627
+ let i;
628
+ for (i = 0; i < l; i++) {
629
+ if (/^ *-+: *$/.test(item.align[i])) {
630
+ item.align[i] = 'right';
631
+ } else if (/^ *:-+: *$/.test(item.align[i])) {
632
+ item.align[i] = 'center';
633
+ } else if (/^ *:-+ *$/.test(item.align[i])) {
634
+ item.align[i] = 'left';
635
+ } else {
636
+ item.align[i] = null;
637
+ }
638
+ }
639
+
640
+ l = item.cells.length;
641
+ for (i = 0; i < l; i++) {
642
+ item.cells[i] = splitCells$1(
643
+ item.cells[i].replace(/^ *\| *| *\| *$/g, ''),
644
+ item.header.length);
645
+ }
646
+
647
+ return item;
648
+ }
649
+ }
650
+ }
651
+
652
+ lheading(src) {
653
+ const cap = this.rules.block.lheading.exec(src);
654
+ if (cap) {
655
+ return {
656
+ type: 'heading',
657
+ raw: cap[0],
658
+ depth: cap[2].charAt(0) === '=' ? 1 : 2,
659
+ text: cap[1]
660
+ };
661
+ }
662
+ }
663
+
664
+ paragraph(src) {
665
+ const cap = this.rules.block.paragraph.exec(src);
666
+ if (cap) {
667
+ return {
668
+ type: 'paragraph',
669
+ raw: cap[0],
670
+ text: cap[1].charAt(cap[1].length - 1) === '\n'
671
+ ? cap[1].slice(0, -1)
672
+ : cap[1]
673
+ };
674
+ }
675
+ }
676
+
677
+ text(src, tokens) {
678
+ const cap = this.rules.block.text.exec(src);
679
+ if (cap) {
680
+ const lastToken = tokens[tokens.length - 1];
681
+ if (lastToken && lastToken.type === 'text') {
682
+ return {
683
+ raw: cap[0],
684
+ text: cap[0]
685
+ };
686
+ }
687
+
688
+ return {
689
+ type: 'text',
690
+ raw: cap[0],
691
+ text: cap[0]
692
+ };
693
+ }
694
+ }
695
+
696
+ escape(src) {
697
+ const cap = this.rules.inline.escape.exec(src);
698
+ if (cap) {
699
+ return {
700
+ type: 'escape',
701
+ raw: cap[0],
702
+ text: escape$1(cap[1])
703
+ };
704
+ }
705
+ }
706
+
707
+ tag(src, inLink, inRawBlock) {
708
+ const cap = this.rules.inline.tag.exec(src);
709
+ if (cap) {
710
+ if (!inLink && /^<a /i.test(cap[0])) {
711
+ inLink = true;
712
+ } else if (inLink && /^<\/a>/i.test(cap[0])) {
713
+ inLink = false;
714
+ }
715
+ if (!inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
716
+ inRawBlock = true;
717
+ } else if (inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
718
+ inRawBlock = false;
719
+ }
720
+
721
+ return {
722
+ type: this.options.sanitize
723
+ ? 'text'
724
+ : 'html',
725
+ raw: cap[0],
726
+ inLink,
727
+ inRawBlock,
728
+ text: this.options.sanitize
729
+ ? (this.options.sanitizer
730
+ ? this.options.sanitizer(cap[0])
731
+ : escape$1(cap[0]))
732
+ : cap[0]
733
+ };
734
+ }
735
+ }
736
+
737
+ link(src) {
738
+ const cap = this.rules.inline.link.exec(src);
739
+ if (cap) {
740
+ const lastParenIndex = findClosingBracket$1(cap[2], '()');
741
+ if (lastParenIndex > -1) {
742
+ const start = cap[0].indexOf('!') === 0 ? 5 : 4;
743
+ const linkLen = start + cap[1].length + lastParenIndex;
744
+ cap[2] = cap[2].substring(0, lastParenIndex);
745
+ cap[0] = cap[0].substring(0, linkLen).trim();
746
+ cap[3] = '';
747
+ }
748
+ let href = cap[2];
749
+ let title = '';
750
+ if (this.options.pedantic) {
751
+ const link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href);
752
+
753
+ if (link) {
754
+ href = link[1];
755
+ title = link[3];
756
+ } else {
757
+ title = '';
758
+ }
759
+ } else {
760
+ title = cap[3] ? cap[3].slice(1, -1) : '';
761
+ }
762
+ href = href.trim().replace(/^<([\s\S]*)>$/, '$1');
763
+ const token = outputLink(cap, {
764
+ href: href ? href.replace(this.rules.inline._escapes, '$1') : href,
765
+ title: title ? title.replace(this.rules.inline._escapes, '$1') : title
766
+ }, cap[0]);
767
+ return token;
768
+ }
769
+ }
770
+
771
+ reflink(src, links) {
772
+ let cap;
773
+ if ((cap = this.rules.inline.reflink.exec(src))
774
+ || (cap = this.rules.inline.nolink.exec(src))) {
775
+ let link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
776
+ link = links[link.toLowerCase()];
777
+ if (!link || !link.href) {
778
+ const text = cap[0].charAt(0);
779
+ return {
780
+ type: 'text',
781
+ raw: text,
782
+ text
783
+ };
784
+ }
785
+ const token = outputLink(cap, link, cap[0]);
786
+ return token;
787
+ }
788
+ }
789
+
790
+ strong(src, maskedSrc, prevChar = '') {
791
+ let match = this.rules.inline.strong.start.exec(src);
792
+
793
+ if (match && (!match[1] || (match[1] && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar))))) {
794
+ maskedSrc = maskedSrc.slice(-1 * src.length);
795
+ const endReg = match[0] === '**' ? this.rules.inline.strong.endAst : this.rules.inline.strong.endUnd;
796
+
797
+ endReg.lastIndex = 0;
798
+
799
+ let cap;
800
+ while ((match = endReg.exec(maskedSrc)) != null) {
801
+ cap = this.rules.inline.strong.middle.exec(maskedSrc.slice(0, match.index + 3));
802
+ if (cap) {
803
+ return {
804
+ type: 'strong',
805
+ raw: src.slice(0, cap[0].length),
806
+ text: src.slice(2, cap[0].length - 2)
807
+ };
808
+ }
809
+ }
810
+ }
811
+ }
812
+
813
+ em(src, maskedSrc, prevChar = '') {
814
+ let match = this.rules.inline.em.start.exec(src);
815
+
816
+ if (match && (!match[1] || (match[1] && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar))))) {
817
+ maskedSrc = maskedSrc.slice(-1 * src.length);
818
+ const endReg = match[0] === '*' ? this.rules.inline.em.endAst : this.rules.inline.em.endUnd;
819
+
820
+ endReg.lastIndex = 0;
821
+
822
+ let cap;
823
+ while ((match = endReg.exec(maskedSrc)) != null) {
824
+ cap = this.rules.inline.em.middle.exec(maskedSrc.slice(0, match.index + 2));
825
+ if (cap) {
826
+ return {
827
+ type: 'em',
828
+ raw: src.slice(0, cap[0].length),
829
+ text: src.slice(1, cap[0].length - 1)
830
+ };
831
+ }
832
+ }
833
+ }
834
+ }
835
+
836
+ codespan(src) {
837
+ const cap = this.rules.inline.code.exec(src);
838
+ if (cap) {
839
+ let text = cap[2].replace(/\n/g, ' ');
840
+ const hasNonSpaceChars = /[^ ]/.test(text);
841
+ const hasSpaceCharsOnBothEnds = text.startsWith(' ') && text.endsWith(' ');
842
+ if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {
843
+ text = text.substring(1, text.length - 1);
844
+ }
845
+ text = escape$1(text, true);
846
+ return {
847
+ type: 'codespan',
848
+ raw: cap[0],
849
+ text
850
+ };
851
+ }
852
+ }
853
+
854
+ br(src) {
855
+ const cap = this.rules.inline.br.exec(src);
856
+ if (cap) {
857
+ return {
858
+ type: 'br',
859
+ raw: cap[0]
860
+ };
861
+ }
862
+ }
863
+
864
+ del(src) {
865
+ const cap = this.rules.inline.del.exec(src);
866
+ if (cap) {
867
+ return {
868
+ type: 'del',
869
+ raw: cap[0],
870
+ text: cap[1]
871
+ };
872
+ }
873
+ }
874
+
875
+ autolink(src, mangle) {
876
+ const cap = this.rules.inline.autolink.exec(src);
877
+ if (cap) {
878
+ let text, href;
879
+ if (cap[2] === '@') {
880
+ text = escape$1(this.options.mangle ? mangle(cap[1]) : cap[1]);
881
+ href = 'mailto:' + text;
882
+ } else {
883
+ text = escape$1(cap[1]);
884
+ href = text;
885
+ }
886
+
887
+ return {
888
+ type: 'link',
889
+ raw: cap[0],
890
+ text,
891
+ href,
892
+ tokens: [
893
+ {
894
+ type: 'text',
895
+ raw: text,
896
+ text
897
+ }
898
+ ]
899
+ };
900
+ }
901
+ }
902
+
903
+ url(src, mangle) {
904
+ let cap;
905
+ if (cap = this.rules.inline.url.exec(src)) {
906
+ let text, href;
907
+ if (cap[2] === '@') {
908
+ text = escape$1(this.options.mangle ? mangle(cap[0]) : cap[0]);
909
+ href = 'mailto:' + text;
910
+ } else {
911
+ // do extended autolink path validation
912
+ let prevCapZero;
913
+ do {
914
+ prevCapZero = cap[0];
915
+ cap[0] = this.rules.inline._backpedal.exec(cap[0])[0];
916
+ } while (prevCapZero !== cap[0]);
917
+ text = escape$1(cap[0]);
918
+ if (cap[1] === 'www.') {
919
+ href = 'http://' + text;
920
+ } else {
921
+ href = text;
922
+ }
923
+ }
924
+ return {
925
+ type: 'link',
926
+ raw: cap[0],
927
+ text,
928
+ href,
929
+ tokens: [
930
+ {
931
+ type: 'text',
932
+ raw: text,
933
+ text
934
+ }
935
+ ]
936
+ };
937
+ }
938
+ }
939
+
940
+ inlineText(src, inRawBlock, smartypants) {
941
+ const cap = this.rules.inline.text.exec(src);
942
+ if (cap) {
943
+ let text;
944
+ if (inRawBlock) {
945
+ text = this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape$1(cap[0])) : cap[0];
946
+ } else {
947
+ text = escape$1(this.options.smartypants ? smartypants(cap[0]) : cap[0]);
948
+ }
949
+ return {
950
+ type: 'text',
951
+ raw: cap[0],
952
+ text
953
+ };
954
+ }
955
+ }
956
+ };
957
+
296
958
  const {
297
959
  noopTest: noopTest$1,
298
960
  edit: edit$1,
@@ -337,7 +999,7 @@ block.def = edit$1(block.def)
337
999
  .replace('title', block._title)
338
1000
  .getRegex();
339
1001
 
340
- block.bullet = /(?:[*+-]|\d{1,9}\.)/;
1002
+ block.bullet = /(?:[*+-]|\d{1,9}[.)])/;
341
1003
  block.item = /^( *)(bull) ?[^\n]*(?:\n(?!\1bull ?)[^\n]*)*/;
342
1004
  block.item = edit$1(block.item, 'gm')
343
1005
  .replace(/bull/g, block.bullet)
@@ -463,18 +1125,74 @@ const inline = {
463
1125
  link: /^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,
464
1126
  reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,
465
1127
  nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,
466
- strong: /^__([^\s_])__(?!_)|^\*\*([^\s*])\*\*(?!\*)|^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)/,
467
- em: /^_([^\s_])_(?!_)|^\*([^\s*<\[])\*(?!\*)|^_([^\s<][\s\S]*?[^\s_])_(?!_|[^\spunctuation])|^_([^\s_<][\s\S]*?[^\s])_(?!_|[^\spunctuation])|^\*([^\s<"][\s\S]*?[^\s\*])\*(?!\*|[^\spunctuation])|^\*([^\s*"<\[][\s\S]*?[^\s])\*(?!\*)/,
1128
+ reflinkSearch: 'reflink|nolink(?!\\()',
1129
+ strong: {
1130
+ start: /^(?:(\*\*(?=[*punctuation]))|\*\*)(?![\s])|__/, // (1) returns if starts w/ punctuation
1131
+ middle: /^\*\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*\*$|^__(?![\s])((?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?)__$/,
1132
+ endAst: /[^punctuation\s]\*\*(?!\*)|[punctuation]\*\*(?!\*)(?:(?=[punctuation\s]|$))/, // last char can't be punct, or final * must also be followed by punct (or endline)
1133
+ endUnd: /[^\s]__(?!_)(?:(?=[punctuation\s])|$)/ // last char can't be a space, and final _ must preceed punct or \s (or endline)
1134
+ },
1135
+ em: {
1136
+ start: /^(?:(\*(?=[punctuation]))|\*)(?![*\s])|_/, // (1) returns if starts w/ punctuation
1137
+ middle: /^\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*$|^_(?![_\s])(?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?_$/,
1138
+ endAst: /[^punctuation\s]\*(?!\*)|[punctuation]\*(?!\*)(?:(?=[punctuation\s]|$))/, // last char can't be punct, or final * must also be followed by punct (or endline)
1139
+ endUnd: /[^\s]_(?!_)(?:(?=[punctuation\s])|$)/ // last char can't be a space, and final _ must preceed punct or \s (or endline)
1140
+ },
468
1141
  code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,
469
1142
  br: /^( {2,}|\\)\n(?!\s*$)/,
470
1143
  del: noopTest$1,
471
- text: /^(`+|[^`])(?:[\s\S]*?(?:(?=[\\<!\[`*]|\b_|$)|[^ ](?= {2,}\n))|(?= {2,}\n))/
1144
+ text: /^(`+|[^`])(?:[\s\S]*?(?:(?=[\\<!\[`*]|\b_|$)|[^ ](?= {2,}\n))|(?= {2,}\n))/,
1145
+ punctuation: /^([\s*punctuation])/
472
1146
  };
473
1147
 
474
1148
  // list of punctuation marks from common mark spec
475
- // without ` and ] to workaround Rule 17 (inline code blocks/links)
476
- inline._punctuation = '!"#$%&\'()*+,\\-./:;<=>?@\\[^_{|}~';
477
- inline.em = edit$1(inline.em).replace(/punctuation/g, inline._punctuation).getRegex();
1149
+ // without * and _ to workaround cases with double emphasis
1150
+ inline._punctuation = '!"#$%&\'()+\\-.,/:;<=>?@\\[\\]`^{|}~';
1151
+ inline.punctuation = edit$1(inline.punctuation).replace(/punctuation/g, inline._punctuation).getRegex();
1152
+
1153
+ // sequences em should skip over [title](link), `code`, <html>
1154
+ inline._blockSkip = '\\[[^\\]]*?\\]\\([^\\)]*?\\)|`[^`]*?`|<[^>]*?>';
1155
+ inline._overlapSkip = '__[^_]*?__|\\*\\*\\[^\\*\\]*?\\*\\*';
1156
+
1157
+ inline.em.start = edit$1(inline.em.start)
1158
+ .replace(/punctuation/g, inline._punctuation)
1159
+ .getRegex();
1160
+
1161
+ inline.em.middle = edit$1(inline.em.middle)
1162
+ .replace(/punctuation/g, inline._punctuation)
1163
+ .replace(/overlapSkip/g, inline._overlapSkip)
1164
+ .getRegex();
1165
+
1166
+ inline.em.endAst = edit$1(inline.em.endAst, 'g')
1167
+ .replace(/punctuation/g, inline._punctuation)
1168
+ .getRegex();
1169
+
1170
+ inline.em.endUnd = edit$1(inline.em.endUnd, 'g')
1171
+ .replace(/punctuation/g, inline._punctuation)
1172
+ .getRegex();
1173
+
1174
+ inline.strong.start = edit$1(inline.strong.start)
1175
+ .replace(/punctuation/g, inline._punctuation)
1176
+ .getRegex();
1177
+
1178
+ inline.strong.middle = edit$1(inline.strong.middle)
1179
+ .replace(/punctuation/g, inline._punctuation)
1180
+ .replace(/blockSkip/g, inline._blockSkip)
1181
+ .getRegex();
1182
+
1183
+ inline.strong.endAst = edit$1(inline.strong.endAst, 'g')
1184
+ .replace(/punctuation/g, inline._punctuation)
1185
+ .getRegex();
1186
+
1187
+ inline.strong.endUnd = edit$1(inline.strong.endUnd, 'g')
1188
+ .replace(/punctuation/g, inline._punctuation)
1189
+ .getRegex();
1190
+
1191
+ inline.blockSkip = edit$1(inline._blockSkip, 'g')
1192
+ .getRegex();
1193
+
1194
+ inline.overlapSkip = edit$1(inline._overlapSkip, 'g')
1195
+ .getRegex();
478
1196
 
479
1197
  inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;
480
1198
 
@@ -492,7 +1210,7 @@ inline.tag = edit$1(inline.tag)
492
1210
  .replace('attribute', inline._attribute)
493
1211
  .getRegex();
494
1212
 
495
- inline._label = /(?:\[[^\[\]]*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
1213
+ inline._label = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
496
1214
  inline._href = /<(?:\\[<>]?|[^\s<>\\])*>|[^\s\x00-\x1f]*/;
497
1215
  inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/;
498
1216
 
@@ -506,6 +1224,11 @@ inline.reflink = edit$1(inline.reflink)
506
1224
  .replace('label', inline._label)
507
1225
  .getRegex();
508
1226
 
1227
+ inline.reflinkSearch = edit$1(inline.reflinkSearch, 'g')
1228
+ .replace('reflink', inline.reflink)
1229
+ .replace('nolink', inline.nolink)
1230
+ .getRegex();
1231
+
509
1232
  /**
510
1233
  * Normal Inline Grammar
511
1234
  */
@@ -517,8 +1240,18 @@ inline.normal = merge$1({}, inline);
517
1240
  */
518
1241
 
519
1242
  inline.pedantic = merge$1({}, inline.normal, {
520
- strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
521
- em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/,
1243
+ strong: {
1244
+ start: /^__|\*\*/,
1245
+ middle: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
1246
+ endAst: /\*\*(?!\*)/g,
1247
+ endUnd: /__(?!_)/g
1248
+ },
1249
+ em: {
1250
+ start: /^_|\*/,
1251
+ middle: /^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/,
1252
+ endAst: /\*(?!\*)/g,
1253
+ endUnd: /_(?!_)/g
1254
+ },
522
1255
  link: edit$1(/^!?\[(label)\]\((.*?)\)/)
523
1256
  .replace('label', inline._label)
524
1257
  .getRegex(),
@@ -560,13 +1293,49 @@ var rules = {
560
1293
  inline
561
1294
  };
562
1295
 
563
- const { defaults: defaults$1 } = defaults;
564
- const { block: block$1 } = rules;
565
- const {
566
- rtrim: rtrim$1,
567
- splitCells: splitCells$1,
568
- escape: escape$1
569
- } = helpers;
1296
+ const { defaults: defaults$2 } = defaults;
1297
+ const { block: block$1, inline: inline$1 } = rules;
1298
+
1299
+ /**
1300
+ * smartypants text replacement
1301
+ */
1302
+ function smartypants(text) {
1303
+ return text
1304
+ // em-dashes
1305
+ .replace(/---/g, '\u2014')
1306
+ // en-dashes
1307
+ .replace(/--/g, '\u2013')
1308
+ // opening singles
1309
+ .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
1310
+ // closing singles & apostrophes
1311
+ .replace(/'/g, '\u2019')
1312
+ // opening doubles
1313
+ .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
1314
+ // closing doubles
1315
+ .replace(/"/g, '\u201d')
1316
+ // ellipses
1317
+ .replace(/\.{3}/g, '\u2026');
1318
+ }
1319
+
1320
+ /**
1321
+ * mangle email addresses
1322
+ */
1323
+ function mangle(text) {
1324
+ let out = '',
1325
+ i,
1326
+ ch;
1327
+
1328
+ const l = text.length;
1329
+ for (i = 0; i < l; i++) {
1330
+ ch = text.charCodeAt(i);
1331
+ if (Math.random() > 0.5) {
1332
+ ch = 'x' + ch.toString(16);
1333
+ }
1334
+ out += '&#' + ch + ';';
1335
+ }
1336
+
1337
+ return out;
1338
+ }
570
1339
 
571
1340
  /**
572
1341
  * Block Lexer
@@ -575,21 +1344,38 @@ var Lexer_1 = class Lexer {
575
1344
  constructor(options) {
576
1345
  this.tokens = [];
577
1346
  this.tokens.links = Object.create(null);
578
- this.options = options || defaults$1;
579
- this.rules = block$1.normal;
1347
+ this.options = options || defaults$2;
1348
+ this.options.tokenizer = this.options.tokenizer || new Tokenizer_1();
1349
+ this.tokenizer = this.options.tokenizer;
1350
+ this.tokenizer.options = this.options;
1351
+
1352
+ const rules = {
1353
+ block: block$1.normal,
1354
+ inline: inline$1.normal
1355
+ };
580
1356
 
581
1357
  if (this.options.pedantic) {
582
- this.rules = block$1.pedantic;
1358
+ rules.block = block$1.pedantic;
1359
+ rules.inline = inline$1.pedantic;
583
1360
  } else if (this.options.gfm) {
584
- this.rules = block$1.gfm;
1361
+ rules.block = block$1.gfm;
1362
+ if (this.options.breaks) {
1363
+ rules.inline = inline$1.breaks;
1364
+ } else {
1365
+ rules.inline = inline$1.gfm;
1366
+ }
585
1367
  }
1368
+ this.tokenizer.rules = rules;
586
1369
  }
587
1370
 
588
1371
  /**
589
- * Expose Block Rules
1372
+ * Expose Rules
590
1373
  */
591
1374
  static get rules() {
592
- return block$1;
1375
+ return {
1376
+ block: block$1,
1377
+ inline: inline$1
1378
+ };
593
1379
  }
594
1380
 
595
1381
  /**
@@ -598,7 +1384,7 @@ var Lexer_1 = class Lexer {
598
1384
  static lex(src, options) {
599
1385
  const lexer = new Lexer(options);
600
1386
  return lexer.lex(src);
601
- };
1387
+ }
602
1388
 
603
1389
  /**
604
1390
  * Preprocessing
@@ -608,362 +1394,358 @@ var Lexer_1 = class Lexer {
608
1394
  .replace(/\r\n|\r/g, '\n')
609
1395
  .replace(/\t/g, ' ');
610
1396
 
611
- return this.token(src, true);
612
- };
1397
+ this.blockTokens(src, this.tokens, true);
1398
+
1399
+ this.inline(this.tokens);
1400
+
1401
+ return this.tokens;
1402
+ }
613
1403
 
614
1404
  /**
615
1405
  * Lexing
616
1406
  */
617
- token(src, top) {
1407
+ blockTokens(src, tokens = [], top = true) {
618
1408
  src = src.replace(/^ +$/gm, '');
619
- let next,
620
- loose,
621
- cap,
622
- bull,
623
- b,
624
- item,
625
- listStart,
626
- listItems,
627
- t,
628
- space,
629
- i,
630
- tag,
631
- l,
632
- isordered,
633
- istask,
634
- ischecked;
1409
+ let token, i, l, lastToken;
635
1410
 
636
1411
  while (src) {
637
1412
  // newline
638
- if (cap = this.rules.newline.exec(src)) {
639
- src = src.substring(cap[0].length);
640
- if (cap[0].length > 1) {
641
- this.tokens.push({
642
- type: 'space'
643
- });
1413
+ if (token = this.tokenizer.space(src)) {
1414
+ src = src.substring(token.raw.length);
1415
+ if (token.type) {
1416
+ tokens.push(token);
644
1417
  }
1418
+ continue;
645
1419
  }
646
1420
 
647
1421
  // code
648
- if (cap = this.rules.code.exec(src)) {
649
- const lastToken = this.tokens[this.tokens.length - 1];
650
- src = src.substring(cap[0].length);
651
- // An indented code block cannot interrupt a paragraph.
652
- if (lastToken && lastToken.type === 'paragraph') {
653
- lastToken.text += '\n' + cap[0].trimRight();
1422
+ if (token = this.tokenizer.code(src, tokens)) {
1423
+ src = src.substring(token.raw.length);
1424
+ if (token.type) {
1425
+ tokens.push(token);
654
1426
  } else {
655
- cap = cap[0].replace(/^ {4}/gm, '');
656
- this.tokens.push({
657
- type: 'code',
658
- codeBlockStyle: 'indented',
659
- text: !this.options.pedantic
660
- ? rtrim$1(cap, '\n')
661
- : cap
662
- });
1427
+ lastToken = tokens[tokens.length - 1];
1428
+ lastToken.raw += '\n' + token.raw;
1429
+ lastToken.text += '\n' + token.text;
663
1430
  }
664
1431
  continue;
665
1432
  }
666
1433
 
667
1434
  // fences
668
- if (cap = this.rules.fences.exec(src)) {
669
- src = src.substring(cap[0].length);
670
- this.tokens.push({
671
- type: 'code',
672
- lang: cap[2] ? cap[2].trim() : cap[2],
673
- text: cap[3] || ''
674
- });
1435
+ if (token = this.tokenizer.fences(src)) {
1436
+ src = src.substring(token.raw.length);
1437
+ tokens.push(token);
675
1438
  continue;
676
1439
  }
677
1440
 
678
1441
  // heading
679
- if (cap = this.rules.heading.exec(src)) {
680
- src = src.substring(cap[0].length);
681
- this.tokens.push({
682
- type: 'heading',
683
- depth: cap[1].length,
684
- text: cap[2]
685
- });
1442
+ if (token = this.tokenizer.heading(src)) {
1443
+ src = src.substring(token.raw.length);
1444
+ tokens.push(token);
686
1445
  continue;
687
1446
  }
688
1447
 
689
1448
  // table no leading pipe (gfm)
690
- if (cap = this.rules.nptable.exec(src)) {
691
- item = {
692
- type: 'table',
693
- header: splitCells$1(cap[1].replace(/^ *| *\| *$/g, '')),
694
- align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
695
- cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : []
696
- };
697
-
698
- if (item.header.length === item.align.length) {
699
- src = src.substring(cap[0].length);
700
-
701
- for (i = 0; i < item.align.length; i++) {
702
- if (/^ *-+: *$/.test(item.align[i])) {
703
- item.align[i] = 'right';
704
- } else if (/^ *:-+: *$/.test(item.align[i])) {
705
- item.align[i] = 'center';
706
- } else if (/^ *:-+ *$/.test(item.align[i])) {
707
- item.align[i] = 'left';
708
- } else {
709
- item.align[i] = null;
710
- }
711
- }
712
-
713
- for (i = 0; i < item.cells.length; i++) {
714
- item.cells[i] = splitCells$1(item.cells[i], item.header.length);
715
- }
716
-
717
- this.tokens.push(item);
718
-
719
- continue;
720
- }
721
- }
1449
+ if (token = this.tokenizer.nptable(src)) {
1450
+ src = src.substring(token.raw.length);
1451
+ tokens.push(token);
1452
+ continue;
1453
+ }
722
1454
 
723
1455
  // hr
724
- if (cap = this.rules.hr.exec(src)) {
725
- src = src.substring(cap[0].length);
726
- this.tokens.push({
727
- type: 'hr'
728
- });
1456
+ if (token = this.tokenizer.hr(src)) {
1457
+ src = src.substring(token.raw.length);
1458
+ tokens.push(token);
729
1459
  continue;
730
1460
  }
731
1461
 
732
1462
  // blockquote
733
- if (cap = this.rules.blockquote.exec(src)) {
734
- src = src.substring(cap[0].length);
735
-
736
- this.tokens.push({
737
- type: 'blockquote_start'
738
- });
1463
+ if (token = this.tokenizer.blockquote(src)) {
1464
+ src = src.substring(token.raw.length);
1465
+ token.tokens = this.blockTokens(token.text, [], top);
1466
+ tokens.push(token);
1467
+ continue;
1468
+ }
739
1469
 
740
- cap = cap[0].replace(/^ *> ?/gm, '');
1470
+ // list
1471
+ if (token = this.tokenizer.list(src)) {
1472
+ src = src.substring(token.raw.length);
1473
+ l = token.items.length;
1474
+ for (i = 0; i < l; i++) {
1475
+ token.items[i].tokens = this.blockTokens(token.items[i].text, [], false);
1476
+ }
1477
+ tokens.push(token);
1478
+ continue;
1479
+ }
741
1480
 
742
- // Pass `top` to keep the current
743
- // "toplevel" state. This is exactly
744
- // how markdown.pl works.
745
- this.token(cap, top);
1481
+ // html
1482
+ if (token = this.tokenizer.html(src)) {
1483
+ src = src.substring(token.raw.length);
1484
+ tokens.push(token);
1485
+ continue;
1486
+ }
746
1487
 
747
- this.tokens.push({
748
- type: 'blockquote_end'
749
- });
1488
+ // def
1489
+ if (top && (token = this.tokenizer.def(src))) {
1490
+ src = src.substring(token.raw.length);
1491
+ if (!this.tokens.links[token.tag]) {
1492
+ this.tokens.links[token.tag] = {
1493
+ href: token.href,
1494
+ title: token.title
1495
+ };
1496
+ }
1497
+ continue;
1498
+ }
750
1499
 
1500
+ // table (gfm)
1501
+ if (token = this.tokenizer.table(src)) {
1502
+ src = src.substring(token.raw.length);
1503
+ tokens.push(token);
751
1504
  continue;
752
1505
  }
753
1506
 
754
- // list
755
- if (cap = this.rules.list.exec(src)) {
756
- src = src.substring(cap[0].length);
757
- bull = cap[2];
758
- isordered = bull.length > 1;
759
-
760
- listStart = {
761
- type: 'list_start',
762
- ordered: isordered,
763
- start: isordered ? +bull : '',
764
- loose: false
765
- };
1507
+ // lheading
1508
+ if (token = this.tokenizer.lheading(src)) {
1509
+ src = src.substring(token.raw.length);
1510
+ tokens.push(token);
1511
+ continue;
1512
+ }
766
1513
 
767
- this.tokens.push(listStart);
1514
+ // top-level paragraph
1515
+ if (top && (token = this.tokenizer.paragraph(src))) {
1516
+ src = src.substring(token.raw.length);
1517
+ tokens.push(token);
1518
+ continue;
1519
+ }
768
1520
 
769
- // Get each top-level item.
770
- cap = cap[0].match(this.rules.item);
1521
+ // text
1522
+ if (token = this.tokenizer.text(src, tokens)) {
1523
+ src = src.substring(token.raw.length);
1524
+ if (token.type) {
1525
+ tokens.push(token);
1526
+ } else {
1527
+ lastToken = tokens[tokens.length - 1];
1528
+ lastToken.raw += '\n' + token.raw;
1529
+ lastToken.text += '\n' + token.text;
1530
+ }
1531
+ continue;
1532
+ }
771
1533
 
772
- listItems = [];
773
- next = false;
774
- l = cap.length;
775
- i = 0;
1534
+ if (src) {
1535
+ const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
1536
+ if (this.options.silent) {
1537
+ console.error(errMsg);
1538
+ break;
1539
+ } else {
1540
+ throw new Error(errMsg);
1541
+ }
1542
+ }
1543
+ }
776
1544
 
777
- for (; i < l; i++) {
778
- item = cap[i];
1545
+ return tokens;
1546
+ }
779
1547
 
780
- // Remove the list item's bullet
781
- // so it is seen as the next token.
782
- space = item.length;
783
- item = item.replace(/^ *([*+-]|\d+\.) */, '');
1548
+ inline(tokens) {
1549
+ let i,
1550
+ j,
1551
+ k,
1552
+ l2,
1553
+ row,
1554
+ token;
1555
+
1556
+ const l = tokens.length;
1557
+ for (i = 0; i < l; i++) {
1558
+ token = tokens[i];
1559
+ switch (token.type) {
1560
+ case 'paragraph':
1561
+ case 'text':
1562
+ case 'heading': {
1563
+ token.tokens = [];
1564
+ this.inlineTokens(token.text, token.tokens);
1565
+ break;
1566
+ }
1567
+ case 'table': {
1568
+ token.tokens = {
1569
+ header: [],
1570
+ cells: []
1571
+ };
784
1572
 
785
- // Outdent whatever the
786
- // list item contains. Hacky.
787
- if (~item.indexOf('\n ')) {
788
- space -= item.length;
789
- item = !this.options.pedantic
790
- ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
791
- : item.replace(/^ {1,4}/gm, '');
1573
+ // header
1574
+ l2 = token.header.length;
1575
+ for (j = 0; j < l2; j++) {
1576
+ token.tokens.header[j] = [];
1577
+ this.inlineTokens(token.header[j], token.tokens.header[j]);
792
1578
  }
793
1579
 
794
- // Determine whether the next list item belongs here.
795
- // Backpedal if it does not belong in this list.
796
- if (i !== l - 1) {
797
- b = block$1.bullet.exec(cap[i + 1])[0];
798
- if (bull.length > 1 ? b.length === 1
799
- : (b.length > 1 || (this.options.smartLists && b !== bull))) {
800
- src = cap.slice(i + 1).join('\n') + src;
801
- i = l - 1;
1580
+ // cells
1581
+ l2 = token.cells.length;
1582
+ for (j = 0; j < l2; j++) {
1583
+ row = token.cells[j];
1584
+ token.tokens.cells[j] = [];
1585
+ for (k = 0; k < row.length; k++) {
1586
+ token.tokens.cells[j][k] = [];
1587
+ this.inlineTokens(row[k], token.tokens.cells[j][k]);
802
1588
  }
803
1589
  }
804
1590
 
805
- // Determine whether item is loose or not.
806
- // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
807
- // for discount behavior.
808
- loose = next || /\n\n(?!\s*$)/.test(item);
809
- if (i !== l - 1) {
810
- next = item.charAt(item.length - 1) === '\n';
811
- if (!loose) loose = next;
812
- }
813
-
814
- if (loose) {
815
- listStart.loose = true;
816
- }
817
-
818
- // Check for task list items
819
- istask = /^\[[ xX]\] /.test(item);
820
- ischecked = undefined;
821
- if (istask) {
822
- ischecked = item[1] !== ' ';
823
- item = item.replace(/^\[[ xX]\] +/, '');
1591
+ break;
1592
+ }
1593
+ case 'blockquote': {
1594
+ this.inline(token.tokens);
1595
+ break;
1596
+ }
1597
+ case 'list': {
1598
+ l2 = token.items.length;
1599
+ for (j = 0; j < l2; j++) {
1600
+ this.inline(token.items[j].tokens);
824
1601
  }
825
-
826
- t = {
827
- type: 'list_item_start',
828
- task: istask,
829
- checked: ischecked,
830
- loose: loose
831
- };
832
-
833
- listItems.push(t);
834
- this.tokens.push(t);
835
-
836
- // Recurse.
837
- this.token(item, false);
838
-
839
- this.tokens.push({
840
- type: 'list_item_end'
841
- });
1602
+ break;
842
1603
  }
1604
+ }
1605
+ }
1606
+
1607
+ return tokens;
1608
+ }
843
1609
 
844
- if (listStart.loose) {
845
- l = listItems.length;
846
- i = 0;
847
- for (; i < l; i++) {
848
- listItems[i].loose = true;
1610
+ /**
1611
+ * Lexing/Compiling
1612
+ */
1613
+ inlineTokens(src, tokens = [], inLink = false, inRawBlock = false, prevChar = '') {
1614
+ let token;
1615
+
1616
+ // String with links masked to avoid interference with em and strong
1617
+ let maskedSrc = src;
1618
+ let match;
1619
+
1620
+ // Mask out reflinks
1621
+ if (this.tokens.links) {
1622
+ const links = Object.keys(this.tokens.links);
1623
+ if (links.length > 0) {
1624
+ while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {
1625
+ if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) {
1626
+ maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);
849
1627
  }
850
1628
  }
1629
+ }
1630
+ }
1631
+ // Mask out other blocks
1632
+ while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {
1633
+ maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
1634
+ }
851
1635
 
852
- this.tokens.push({
853
- type: 'list_end'
854
- });
1636
+ while (src) {
1637
+ // escape
1638
+ if (token = this.tokenizer.escape(src)) {
1639
+ src = src.substring(token.raw.length);
1640
+ tokens.push(token);
1641
+ continue;
1642
+ }
855
1643
 
1644
+ // tag
1645
+ if (token = this.tokenizer.tag(src, inLink, inRawBlock)) {
1646
+ src = src.substring(token.raw.length);
1647
+ inLink = token.inLink;
1648
+ inRawBlock = token.inRawBlock;
1649
+ tokens.push(token);
856
1650
  continue;
857
1651
  }
858
1652
 
859
- // html
860
- if (cap = this.rules.html.exec(src)) {
861
- src = src.substring(cap[0].length);
862
- this.tokens.push({
863
- type: this.options.sanitize
864
- ? 'paragraph'
865
- : 'html',
866
- pre: !this.options.sanitizer
867
- && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
868
- text: this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape$1(cap[0])) : cap[0]
869
- });
1653
+ // link
1654
+ if (token = this.tokenizer.link(src)) {
1655
+ src = src.substring(token.raw.length);
1656
+ if (token.type === 'link') {
1657
+ token.tokens = this.inlineTokens(token.text, [], true, inRawBlock);
1658
+ }
1659
+ tokens.push(token);
870
1660
  continue;
871
1661
  }
872
1662
 
873
- // def
874
- if (top && (cap = this.rules.def.exec(src))) {
875
- src = src.substring(cap[0].length);
876
- if (cap[3]) cap[3] = cap[3].substring(1, cap[3].length - 1);
877
- tag = cap[1].toLowerCase().replace(/\s+/g, ' ');
878
- if (!this.tokens.links[tag]) {
879
- this.tokens.links[tag] = {
880
- href: cap[2],
881
- title: cap[3]
882
- };
1663
+ // reflink, nolink
1664
+ if (token = this.tokenizer.reflink(src, this.tokens.links)) {
1665
+ src = src.substring(token.raw.length);
1666
+ if (token.type === 'link') {
1667
+ token.tokens = this.inlineTokens(token.text, [], true, inRawBlock);
883
1668
  }
1669
+ tokens.push(token);
884
1670
  continue;
885
1671
  }
886
1672
 
887
- // table (gfm)
888
- if (cap = this.rules.table.exec(src)) {
889
- item = {
890
- type: 'table',
891
- header: splitCells$1(cap[1].replace(/^ *| *\| *$/g, '')),
892
- align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
893
- cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : []
894
- };
1673
+ // strong
1674
+ if (token = this.tokenizer.strong(src, maskedSrc, prevChar)) {
1675
+ src = src.substring(token.raw.length);
1676
+ token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock);
1677
+ tokens.push(token);
1678
+ continue;
1679
+ }
895
1680
 
896
- if (item.header.length === item.align.length) {
897
- src = src.substring(cap[0].length);
898
-
899
- for (i = 0; i < item.align.length; i++) {
900
- if (/^ *-+: *$/.test(item.align[i])) {
901
- item.align[i] = 'right';
902
- } else if (/^ *:-+: *$/.test(item.align[i])) {
903
- item.align[i] = 'center';
904
- } else if (/^ *:-+ *$/.test(item.align[i])) {
905
- item.align[i] = 'left';
906
- } else {
907
- item.align[i] = null;
908
- }
909
- }
1681
+ // em
1682
+ if (token = this.tokenizer.em(src, maskedSrc, prevChar)) {
1683
+ src = src.substring(token.raw.length);
1684
+ token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock);
1685
+ tokens.push(token);
1686
+ continue;
1687
+ }
910
1688
 
911
- for (i = 0; i < item.cells.length; i++) {
912
- item.cells[i] = splitCells$1(
913
- item.cells[i].replace(/^ *\| *| *\| *$/g, ''),
914
- item.header.length);
915
- }
1689
+ // code
1690
+ if (token = this.tokenizer.codespan(src)) {
1691
+ src = src.substring(token.raw.length);
1692
+ tokens.push(token);
1693
+ continue;
1694
+ }
916
1695
 
917
- this.tokens.push(item);
1696
+ // br
1697
+ if (token = this.tokenizer.br(src)) {
1698
+ src = src.substring(token.raw.length);
1699
+ tokens.push(token);
1700
+ continue;
1701
+ }
918
1702
 
919
- continue;
920
- }
1703
+ // del (gfm)
1704
+ if (token = this.tokenizer.del(src)) {
1705
+ src = src.substring(token.raw.length);
1706
+ token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock);
1707
+ tokens.push(token);
1708
+ continue;
921
1709
  }
922
1710
 
923
- // lheading
924
- if (cap = this.rules.lheading.exec(src)) {
925
- src = src.substring(cap[0].length);
926
- this.tokens.push({
927
- type: 'heading',
928
- depth: cap[2].charAt(0) === '=' ? 1 : 2,
929
- text: cap[1]
930
- });
1711
+ // autolink
1712
+ if (token = this.tokenizer.autolink(src, mangle)) {
1713
+ src = src.substring(token.raw.length);
1714
+ tokens.push(token);
931
1715
  continue;
932
1716
  }
933
1717
 
934
- // top-level paragraph
935
- if (top && (cap = this.rules.paragraph.exec(src))) {
936
- src = src.substring(cap[0].length);
937
- this.tokens.push({
938
- type: 'paragraph',
939
- text: cap[1].charAt(cap[1].length - 1) === '\n'
940
- ? cap[1].slice(0, -1)
941
- : cap[1]
942
- });
1718
+ // url (gfm)
1719
+ if (!inLink && (token = this.tokenizer.url(src, mangle))) {
1720
+ src = src.substring(token.raw.length);
1721
+ tokens.push(token);
943
1722
  continue;
944
1723
  }
945
1724
 
946
1725
  // text
947
- if (cap = this.rules.text.exec(src)) {
948
- // Top-level should never reach here.
949
- src = src.substring(cap[0].length);
950
- this.tokens.push({
951
- type: 'text',
952
- text: cap[0]
953
- });
1726
+ if (token = this.tokenizer.inlineText(src, inRawBlock, smartypants)) {
1727
+ src = src.substring(token.raw.length);
1728
+ prevChar = token.raw.slice(-1);
1729
+ tokens.push(token);
954
1730
  continue;
955
1731
  }
956
1732
 
957
1733
  if (src) {
958
- throw new Error('Infinite loop on byte: ' + src.charCodeAt(0));
1734
+ const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
1735
+ if (this.options.silent) {
1736
+ console.error(errMsg);
1737
+ break;
1738
+ } else {
1739
+ throw new Error(errMsg);
1740
+ }
959
1741
  }
960
1742
  }
961
1743
 
962
- return this.tokens;
963
- };
1744
+ return tokens;
1745
+ }
964
1746
  };
965
1747
 
966
- const { defaults: defaults$2 } = defaults;
1748
+ const { defaults: defaults$3 } = defaults;
967
1749
  const {
968
1750
  cleanUrl: cleanUrl$1,
969
1751
  escape: escape$2
@@ -974,7 +1756,7 @@ const {
974
1756
  */
975
1757
  var Renderer_1 = class Renderer {
976
1758
  constructor(options) {
977
- this.options = options || defaults$2;
1759
+ this.options = options || defaults$3;
978
1760
  }
979
1761
 
980
1762
  code(code, infostring, escaped) {
@@ -990,7 +1772,7 @@ var Renderer_1 = class Renderer {
990
1772
  if (!lang) {
991
1773
  return '<pre><code>'
992
1774
  + (escaped ? code : escape$2(code, true))
993
- + '</code></pre>';
1775
+ + '</code></pre>\n';
994
1776
  }
995
1777
 
996
1778
  return '<pre><code class="'
@@ -999,15 +1781,15 @@ var Renderer_1 = class Renderer {
999
1781
  + '">'
1000
1782
  + (escaped ? code : escape$2(code, true))
1001
1783
  + '</code></pre>\n';
1002
- };
1784
+ }
1003
1785
 
1004
1786
  blockquote(quote) {
1005
1787
  return '<blockquote>\n' + quote + '</blockquote>\n';
1006
- };
1788
+ }
1007
1789
 
1008
1790
  html(html) {
1009
1791
  return html;
1010
- };
1792
+ }
1011
1793
 
1012
1794
  heading(text, level, raw, slugger) {
1013
1795
  if (this.options.headerIds) {
@@ -1024,21 +1806,21 @@ var Renderer_1 = class Renderer {
1024
1806
  }
1025
1807
  // ignore IDs
1026
1808
  return '<h' + level + '>' + text + '</h' + level + '>\n';
1027
- };
1809
+ }
1028
1810
 
1029
1811
  hr() {
1030
1812
  return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
1031
- };
1813
+ }
1032
1814
 
1033
1815
  list(body, ordered, start) {
1034
1816
  const type = ordered ? 'ol' : 'ul',
1035
1817
  startatt = (ordered && start !== 1) ? (' start="' + start + '"') : '';
1036
1818
  return '<' + type + startatt + '>\n' + body + '</' + type + '>\n';
1037
- };
1819
+ }
1038
1820
 
1039
1821
  listitem(text) {
1040
1822
  return '<li>' + text + '</li>\n';
1041
- };
1823
+ }
1042
1824
 
1043
1825
  checkbox(checked) {
1044
1826
  return '<input '
@@ -1046,11 +1828,11 @@ var Renderer_1 = class Renderer {
1046
1828
  + 'disabled="" type="checkbox"'
1047
1829
  + (this.options.xhtml ? ' /' : '')
1048
1830
  + '> ';
1049
- };
1831
+ }
1050
1832
 
1051
1833
  paragraph(text) {
1052
1834
  return '<p>' + text + '</p>\n';
1053
- };
1835
+ }
1054
1836
 
1055
1837
  table(header, body) {
1056
1838
  if (body) body = '<tbody>' + body + '</tbody>';
@@ -1061,11 +1843,11 @@ var Renderer_1 = class Renderer {
1061
1843
  + '</thead>\n'
1062
1844
  + body
1063
1845
  + '</table>\n';
1064
- };
1846
+ }
1065
1847
 
1066
1848
  tablerow(content) {
1067
1849
  return '<tr>\n' + content + '</tr>\n';
1068
- };
1850
+ }
1069
1851
 
1070
1852
  tablecell(content, flags) {
1071
1853
  const type = flags.header ? 'th' : 'td';
@@ -1073,28 +1855,28 @@ var Renderer_1 = class Renderer {
1073
1855
  ? '<' + type + ' align="' + flags.align + '">'
1074
1856
  : '<' + type + '>';
1075
1857
  return tag + content + '</' + type + '>\n';
1076
- };
1858
+ }
1077
1859
 
1078
1860
  // span level renderer
1079
1861
  strong(text) {
1080
1862
  return '<strong>' + text + '</strong>';
1081
- };
1863
+ }
1082
1864
 
1083
1865
  em(text) {
1084
1866
  return '<em>' + text + '</em>';
1085
- };
1867
+ }
1086
1868
 
1087
1869
  codespan(text) {
1088
1870
  return '<code>' + text + '</code>';
1089
- };
1871
+ }
1090
1872
 
1091
1873
  br() {
1092
1874
  return this.options.xhtml ? '<br/>' : '<br>';
1093
- };
1875
+ }
1094
1876
 
1095
1877
  del(text) {
1096
1878
  return '<del>' + text + '</del>';
1097
- };
1879
+ }
1098
1880
 
1099
1881
  link(href, title, text) {
1100
1882
  href = cleanUrl$1(this.options.sanitize, this.options.baseUrl, href);
@@ -1107,7 +1889,7 @@ var Renderer_1 = class Renderer {
1107
1889
  }
1108
1890
  out += '>' + text + '</a>';
1109
1891
  return out;
1110
- };
1892
+ }
1111
1893
 
1112
1894
  image(href, title, text) {
1113
1895
  href = cleanUrl$1(this.options.sanitize, this.options.baseUrl, href);
@@ -1121,11 +1903,54 @@ var Renderer_1 = class Renderer {
1121
1903
  }
1122
1904
  out += this.options.xhtml ? '/>' : '>';
1123
1905
  return out;
1124
- };
1906
+ }
1125
1907
 
1126
1908
  text(text) {
1127
1909
  return text;
1128
- };
1910
+ }
1911
+ };
1912
+
1913
+ /**
1914
+ * TextRenderer
1915
+ * returns only the textual part of the token
1916
+ */
1917
+ var TextRenderer_1 = class TextRenderer {
1918
+ // no need for block level renderers
1919
+ strong(text) {
1920
+ return text;
1921
+ }
1922
+
1923
+ em(text) {
1924
+ return text;
1925
+ }
1926
+
1927
+ codespan(text) {
1928
+ return text;
1929
+ }
1930
+
1931
+ del(text) {
1932
+ return text;
1933
+ }
1934
+
1935
+ html(text) {
1936
+ return text;
1937
+ }
1938
+
1939
+ text(text) {
1940
+ return text;
1941
+ }
1942
+
1943
+ link(href, title, text) {
1944
+ return '' + text;
1945
+ }
1946
+
1947
+ image(href, title, text) {
1948
+ return '' + text;
1949
+ }
1950
+
1951
+ br() {
1952
+ return '';
1953
+ }
1129
1954
  };
1130
1955
 
1131
1956
  /**
@@ -1143,6 +1968,9 @@ var Slugger_1 = class Slugger {
1143
1968
  let slug = value
1144
1969
  .toLowerCase()
1145
1970
  .trim()
1971
+ // remove html tags
1972
+ .replace(/<[!\/a-z].*?>/ig, '')
1973
+ // remove unwanted chars
1146
1974
  .replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '')
1147
1975
  .replace(/\s/g, '-');
1148
1976
 
@@ -1156,548 +1984,266 @@ var Slugger_1 = class Slugger {
1156
1984
  this.seen[slug] = 0;
1157
1985
 
1158
1986
  return slug;
1159
- };
1987
+ }
1160
1988
  };
1161
1989
 
1162
- const { defaults: defaults$3 } = defaults;
1163
- const { inline: inline$1 } = rules;
1990
+ const { defaults: defaults$4 } = defaults;
1164
1991
  const {
1165
- findClosingBracket: findClosingBracket$1,
1166
- escape: escape$3
1992
+ unescape: unescape$1
1167
1993
  } = helpers;
1168
1994
 
1169
1995
  /**
1170
- * Inline Lexer & Compiler
1996
+ * Parsing & Compiling
1171
1997
  */
1172
- var InlineLexer_1 = class InlineLexer {
1173
- constructor(links, options) {
1174
- this.options = options || defaults$3;
1175
- this.links = links;
1176
- this.rules = inline$1.normal;
1998
+ var Parser_1 = class Parser {
1999
+ constructor(options) {
2000
+ this.options = options || defaults$4;
1177
2001
  this.options.renderer = this.options.renderer || new Renderer_1();
1178
2002
  this.renderer = this.options.renderer;
1179
2003
  this.renderer.options = this.options;
1180
-
1181
- if (!this.links) {
1182
- throw new Error('Tokens array requires a `links` property.');
1183
- }
1184
-
1185
- if (this.options.pedantic) {
1186
- this.rules = inline$1.pedantic;
1187
- } else if (this.options.gfm) {
1188
- if (this.options.breaks) {
1189
- this.rules = inline$1.breaks;
1190
- } else {
1191
- this.rules = inline$1.gfm;
1192
- }
1193
- }
1194
- }
1195
-
1196
- /**
1197
- * Expose Inline Rules
1198
- */
1199
- static get rules() {
1200
- return inline$1;
2004
+ this.textRenderer = new TextRenderer_1();
2005
+ this.slugger = new Slugger_1();
1201
2006
  }
1202
2007
 
1203
2008
  /**
1204
- * Static Lexing/Compiling Method
2009
+ * Static Parse Method
1205
2010
  */
1206
- static output(src, links, options) {
1207
- const inline = new InlineLexer(links, options);
1208
- return inline.output(src);
2011
+ static parse(tokens, options) {
2012
+ const parser = new Parser(options);
2013
+ return parser.parse(tokens);
1209
2014
  }
1210
2015
 
1211
2016
  /**
1212
- * Lexing/Compiling
2017
+ * Parse Loop
1213
2018
  */
1214
- output(src) {
2019
+ parse(tokens, top = true) {
1215
2020
  let out = '',
1216
- link,
1217
- text,
1218
- href,
1219
- title,
1220
- cap,
1221
- prevCapZero;
1222
-
1223
- while (src) {
1224
- // escape
1225
- if (cap = this.rules.escape.exec(src)) {
1226
- src = src.substring(cap[0].length);
1227
- out += escape$3(cap[1]);
1228
- continue;
1229
- }
1230
-
1231
- // tag
1232
- if (cap = this.rules.tag.exec(src)) {
1233
- if (!this.inLink && /^<a /i.test(cap[0])) {
1234
- this.inLink = true;
1235
- } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
1236
- this.inLink = false;
2021
+ i,
2022
+ j,
2023
+ k,
2024
+ l2,
2025
+ l3,
2026
+ row,
2027
+ cell,
2028
+ header,
2029
+ body,
2030
+ token,
2031
+ ordered,
2032
+ start,
2033
+ loose,
2034
+ itemBody,
2035
+ item,
2036
+ checked,
2037
+ task,
2038
+ checkbox;
2039
+
2040
+ const l = tokens.length;
2041
+ for (i = 0; i < l; i++) {
2042
+ token = tokens[i];
2043
+ switch (token.type) {
2044
+ case 'space': {
2045
+ continue;
1237
2046
  }
1238
- if (!this.inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
1239
- this.inRawBlock = true;
1240
- } else if (this.inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
1241
- this.inRawBlock = false;
2047
+ case 'hr': {
2048
+ out += this.renderer.hr();
2049
+ continue;
1242
2050
  }
2051
+ case 'heading': {
2052
+ out += this.renderer.heading(
2053
+ this.parseInline(token.tokens),
2054
+ token.depth,
2055
+ unescape$1(this.parseInline(token.tokens, this.textRenderer)),
2056
+ this.slugger);
2057
+ continue;
2058
+ }
2059
+ case 'code': {
2060
+ out += this.renderer.code(token.text,
2061
+ token.lang,
2062
+ token.escaped);
2063
+ continue;
2064
+ }
2065
+ case 'table': {
2066
+ header = '';
1243
2067
 
1244
- src = src.substring(cap[0].length);
1245
- out += this.renderer.html(this.options.sanitize
1246
- ? (this.options.sanitizer
1247
- ? this.options.sanitizer(cap[0])
1248
- : escape$3(cap[0]))
1249
- : cap[0]);
1250
- continue;
1251
- }
2068
+ // header
2069
+ cell = '';
2070
+ l2 = token.header.length;
2071
+ for (j = 0; j < l2; j++) {
2072
+ cell += this.renderer.tablecell(
2073
+ this.parseInline(token.tokens.header[j]),
2074
+ { header: true, align: token.align[j] }
2075
+ );
2076
+ }
2077
+ header += this.renderer.tablerow(cell);
2078
+
2079
+ body = '';
2080
+ l2 = token.cells.length;
2081
+ for (j = 0; j < l2; j++) {
2082
+ row = token.tokens.cells[j];
2083
+
2084
+ cell = '';
2085
+ l3 = row.length;
2086
+ for (k = 0; k < l3; k++) {
2087
+ cell += this.renderer.tablecell(
2088
+ this.parseInline(row[k]),
2089
+ { header: false, align: token.align[k] }
2090
+ );
2091
+ }
1252
2092
 
1253
- // link
1254
- if (cap = this.rules.link.exec(src)) {
1255
- const lastParenIndex = findClosingBracket$1(cap[2], '()');
1256
- if (lastParenIndex > -1) {
1257
- const start = cap[0].indexOf('!') === 0 ? 5 : 4;
1258
- const linkLen = start + cap[1].length + lastParenIndex;
1259
- cap[2] = cap[2].substring(0, lastParenIndex);
1260
- cap[0] = cap[0].substring(0, linkLen).trim();
1261
- cap[3] = '';
1262
- }
1263
- src = src.substring(cap[0].length);
1264
- this.inLink = true;
1265
- href = cap[2];
1266
- if (this.options.pedantic) {
1267
- link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href);
1268
-
1269
- if (link) {
1270
- href = link[1];
1271
- title = link[3];
1272
- } else {
1273
- title = '';
2093
+ body += this.renderer.tablerow(cell);
1274
2094
  }
1275
- } else {
1276
- title = cap[3] ? cap[3].slice(1, -1) : '';
2095
+ out += this.renderer.table(header, body);
2096
+ continue;
1277
2097
  }
1278
- href = href.trim().replace(/^<([\s\S]*)>$/, '$1');
1279
- out += this.outputLink(cap, {
1280
- href: InlineLexer.escapes(href),
1281
- title: InlineLexer.escapes(title)
1282
- });
1283
- this.inLink = false;
1284
- continue;
1285
- }
1286
-
1287
- // reflink, nolink
1288
- if ((cap = this.rules.reflink.exec(src))
1289
- || (cap = this.rules.nolink.exec(src))) {
1290
- src = src.substring(cap[0].length);
1291
- link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
1292
- link = this.links[link.toLowerCase()];
1293
- if (!link || !link.href) {
1294
- out += cap[0].charAt(0);
1295
- src = cap[0].substring(1) + src;
2098
+ case 'blockquote': {
2099
+ body = this.parse(token.tokens);
2100
+ out += this.renderer.blockquote(body);
1296
2101
  continue;
1297
2102
  }
1298
- this.inLink = true;
1299
- out += this.outputLink(cap, link);
1300
- this.inLink = false;
1301
- continue;
1302
- }
1303
-
1304
- // strong
1305
- if (cap = this.rules.strong.exec(src)) {
1306
- src = src.substring(cap[0].length);
1307
- out += this.renderer.strong(this.output(cap[4] || cap[3] || cap[2] || cap[1]));
1308
- continue;
1309
- }
1310
-
1311
- // em
1312
- if (cap = this.rules.em.exec(src)) {
1313
- src = src.substring(cap[0].length);
1314
- out += this.renderer.em(this.output(cap[6] || cap[5] || cap[4] || cap[3] || cap[2] || cap[1]));
1315
- continue;
1316
- }
1317
-
1318
- // code
1319
- if (cap = this.rules.code.exec(src)) {
1320
- src = src.substring(cap[0].length);
1321
- out += this.renderer.codespan(escape$3(cap[2].trim(), true));
1322
- continue;
1323
- }
1324
-
1325
- // br
1326
- if (cap = this.rules.br.exec(src)) {
1327
- src = src.substring(cap[0].length);
1328
- out += this.renderer.br();
1329
- continue;
1330
- }
2103
+ case 'list': {
2104
+ ordered = token.ordered;
2105
+ start = token.start;
2106
+ loose = token.loose;
2107
+ l2 = token.items.length;
2108
+
2109
+ body = '';
2110
+ for (j = 0; j < l2; j++) {
2111
+ item = token.items[j];
2112
+ checked = item.checked;
2113
+ task = item.task;
2114
+
2115
+ itemBody = '';
2116
+ if (item.task) {
2117
+ checkbox = this.renderer.checkbox(checked);
2118
+ if (loose) {
2119
+ if (item.tokens.length > 0 && item.tokens[0].type === 'text') {
2120
+ item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
2121
+ if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {
2122
+ item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text;
2123
+ }
2124
+ } else {
2125
+ item.tokens.unshift({
2126
+ type: 'text',
2127
+ text: checkbox
2128
+ });
2129
+ }
2130
+ } else {
2131
+ itemBody += checkbox;
2132
+ }
2133
+ }
1331
2134
 
1332
- // del (gfm)
1333
- if (cap = this.rules.del.exec(src)) {
1334
- src = src.substring(cap[0].length);
1335
- out += this.renderer.del(this.output(cap[1]));
1336
- continue;
1337
- }
2135
+ itemBody += this.parse(item.tokens, loose);
2136
+ body += this.renderer.listitem(itemBody, task, checked);
2137
+ }
1338
2138
 
1339
- // autolink
1340
- if (cap = this.rules.autolink.exec(src)) {
1341
- src = src.substring(cap[0].length);
1342
- if (cap[2] === '@') {
1343
- text = escape$3(this.mangle(cap[1]));
1344
- href = 'mailto:' + text;
1345
- } else {
1346
- text = escape$3(cap[1]);
1347
- href = text;
2139
+ out += this.renderer.list(body, ordered, start);
2140
+ continue;
1348
2141
  }
1349
- out += this.renderer.link(href, null, text);
1350
- continue;
1351
- }
1352
-
1353
- // url (gfm)
1354
- if (!this.inLink && (cap = this.rules.url.exec(src))) {
1355
- if (cap[2] === '@') {
1356
- text = escape$3(cap[0]);
1357
- href = 'mailto:' + text;
1358
- } else {
1359
- // do extended autolink path validation
1360
- do {
1361
- prevCapZero = cap[0];
1362
- cap[0] = this.rules._backpedal.exec(cap[0])[0];
1363
- } while (prevCapZero !== cap[0]);
1364
- text = escape$3(cap[0]);
1365
- if (cap[1] === 'www.') {
1366
- href = 'http://' + text;
1367
- } else {
1368
- href = text;
2142
+ case 'html': {
2143
+ // TODO parse inline content if parameter markdown=1
2144
+ out += this.renderer.html(token.text);
2145
+ continue;
2146
+ }
2147
+ case 'paragraph': {
2148
+ out += this.renderer.paragraph(this.parseInline(token.tokens));
2149
+ continue;
2150
+ }
2151
+ case 'text': {
2152
+ body = token.tokens ? this.parseInline(token.tokens) : token.text;
2153
+ while (i + 1 < l && tokens[i + 1].type === 'text') {
2154
+ token = tokens[++i];
2155
+ body += '\n' + (token.tokens ? this.parseInline(token.tokens) : token.text);
1369
2156
  }
2157
+ out += top ? this.renderer.paragraph(body) : body;
2158
+ continue;
1370
2159
  }
1371
- src = src.substring(cap[0].length);
1372
- out += this.renderer.link(href, null, text);
1373
- continue;
1374
- }
1375
-
1376
- // text
1377
- if (cap = this.rules.text.exec(src)) {
1378
- src = src.substring(cap[0].length);
1379
- if (this.inRawBlock) {
1380
- out += this.renderer.text(this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape$3(cap[0])) : cap[0]);
1381
- } else {
1382
- out += this.renderer.text(escape$3(this.smartypants(cap[0])));
2160
+ default: {
2161
+ const errMsg = 'Token with "' + token.type + '" type was not found.';
2162
+ if (this.options.silent) {
2163
+ console.error(errMsg);
2164
+ return;
2165
+ } else {
2166
+ throw new Error(errMsg);
2167
+ }
1383
2168
  }
1384
- continue;
1385
- }
1386
-
1387
- if (src) {
1388
- throw new Error('Infinite loop on byte: ' + src.charCodeAt(0));
1389
2169
  }
1390
2170
  }
1391
2171
 
1392
2172
  return out;
1393
2173
  }
1394
2174
 
1395
- static escapes(text) {
1396
- return text ? text.replace(InlineLexer.rules._escapes, '$1') : text;
1397
- }
1398
-
1399
2175
  /**
1400
- * Compile Link
2176
+ * Parse Inline Tokens
1401
2177
  */
1402
- outputLink(cap, link) {
1403
- const href = link.href,
1404
- title = link.title ? escape$3(link.title) : null;
1405
-
1406
- return cap[0].charAt(0) !== '!'
1407
- ? this.renderer.link(href, title, this.output(cap[1]))
1408
- : this.renderer.image(href, title, escape$3(cap[1]));
1409
- }
1410
-
1411
- /**
1412
- * Smartypants Transformations
1413
- */
1414
- smartypants(text) {
1415
- if (!this.options.smartypants) return text;
1416
- return text
1417
- // em-dashes
1418
- .replace(/---/g, '\u2014')
1419
- // en-dashes
1420
- .replace(/--/g, '\u2013')
1421
- // opening singles
1422
- .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
1423
- // closing singles & apostrophes
1424
- .replace(/'/g, '\u2019')
1425
- // opening doubles
1426
- .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
1427
- // closing doubles
1428
- .replace(/"/g, '\u201d')
1429
- // ellipses
1430
- .replace(/\.{3}/g, '\u2026');
1431
- }
1432
-
1433
- /**
1434
- * Mangle Links
1435
- */
1436
- mangle(text) {
1437
- if (!this.options.mangle) return text;
1438
- const l = text.length;
2178
+ parseInline(tokens, renderer) {
2179
+ renderer = renderer || this.renderer;
1439
2180
  let out = '',
1440
- i = 0,
1441
- ch;
1442
-
1443
- for (; i < l; i++) {
1444
- ch = text.charCodeAt(i);
1445
- if (Math.random() > 0.5) {
1446
- ch = 'x' + ch.toString(16);
1447
- }
1448
- out += '&#' + ch + ';';
1449
- }
1450
-
1451
- return out;
1452
- }
1453
- };
1454
-
1455
- /**
1456
- * TextRenderer
1457
- * returns only the textual part of the token
1458
- */
1459
- var TextRenderer_1 = class TextRenderer {
1460
- // no need for block level renderers
1461
- strong(text) {
1462
- return text;
1463
- }
1464
-
1465
- em(text) {
1466
- return text;
1467
- }
1468
-
1469
- codespan(text) {
1470
- return text;
1471
- }
1472
-
1473
- del(text) {
1474
- return text;
1475
- }
1476
-
1477
- text(text) {
1478
- return text;
1479
- }
1480
-
1481
- link(href, title, text) {
1482
- return '' + text;
1483
- }
1484
-
1485
- image(href, title, text) {
1486
- return '' + text;
1487
- }
1488
-
1489
- br() {
1490
- return '';
1491
- }
1492
- };
1493
-
1494
- const { defaults: defaults$4 } = defaults;
1495
- const {
1496
- merge: merge$2,
1497
- unescape: unescape$1
1498
- } = helpers;
1499
-
1500
- /**
1501
- * Parsing & Compiling
1502
- */
1503
- var Parser_1 = class Parser {
1504
- constructor(options) {
1505
- this.tokens = [];
1506
- this.token = null;
1507
- this.options = options || defaults$4;
1508
- this.options.renderer = this.options.renderer || new Renderer_1();
1509
- this.renderer = this.options.renderer;
1510
- this.renderer.options = this.options;
1511
- this.slugger = new Slugger_1();
1512
- }
1513
-
1514
- /**
1515
- * Static Parse Method
1516
- */
1517
- static parse(tokens, options) {
1518
- const parser = new Parser(options);
1519
- return parser.parse(tokens);
1520
- };
1521
-
1522
- /**
1523
- * Parse Loop
1524
- */
1525
- parse(tokens) {
1526
- this.inline = new InlineLexer_1(tokens.links, this.options);
1527
- // use an InlineLexer with a TextRenderer to extract pure text
1528
- this.inlineText = new InlineLexer_1(
1529
- tokens.links,
1530
- merge$2({}, this.options, { renderer: new TextRenderer_1() })
1531
- );
1532
- this.tokens = tokens.reverse();
1533
-
1534
- let out = '';
1535
- while (this.next()) {
1536
- out += this.tok();
1537
- }
1538
-
1539
- return out;
1540
- };
1541
-
1542
- /**
1543
- * Next Token
1544
- */
1545
- next() {
1546
- this.token = this.tokens.pop();
1547
- return this.token;
1548
- };
1549
-
1550
- /**
1551
- * Preview Next Token
1552
- */
1553
- peek() {
1554
- return this.tokens[this.tokens.length - 1] || 0;
1555
- };
1556
-
1557
- /**
1558
- * Parse Text Tokens
1559
- */
1560
- parseText() {
1561
- let body = this.token.text;
1562
-
1563
- while (this.peek().type === 'text') {
1564
- body += '\n' + this.next().text;
1565
- }
1566
-
1567
- return this.inline.output(body);
1568
- };
1569
-
1570
- /**
1571
- * Parse Current Token
1572
- */
1573
- tok() {
1574
- let body = '';
1575
- switch (this.token.type) {
1576
- case 'space': {
1577
- return '';
1578
- }
1579
- case 'hr': {
1580
- return this.renderer.hr();
1581
- }
1582
- case 'heading': {
1583
- return this.renderer.heading(
1584
- this.inline.output(this.token.text),
1585
- this.token.depth,
1586
- unescape$1(this.inlineText.output(this.token.text)),
1587
- this.slugger);
1588
- }
1589
- case 'code': {
1590
- return this.renderer.code(this.token.text,
1591
- this.token.lang,
1592
- this.token.escaped);
1593
- }
1594
- case 'table': {
1595
- let header = '',
1596
- i,
1597
- row,
1598
- cell,
1599
- j;
1600
-
1601
- // header
1602
- cell = '';
1603
- for (i = 0; i < this.token.header.length; i++) {
1604
- cell += this.renderer.tablecell(
1605
- this.inline.output(this.token.header[i]),
1606
- { header: true, align: this.token.align[i] }
1607
- );
2181
+ i,
2182
+ token;
2183
+
2184
+ const l = tokens.length;
2185
+ for (i = 0; i < l; i++) {
2186
+ token = tokens[i];
2187
+ switch (token.type) {
2188
+ case 'escape': {
2189
+ out += renderer.text(token.text);
2190
+ break;
1608
2191
  }
1609
- header += this.renderer.tablerow(cell);
1610
-
1611
- for (i = 0; i < this.token.cells.length; i++) {
1612
- row = this.token.cells[i];
1613
-
1614
- cell = '';
1615
- for (j = 0; j < row.length; j++) {
1616
- cell += this.renderer.tablecell(
1617
- this.inline.output(row[j]),
1618
- { header: false, align: this.token.align[j] }
1619
- );
1620
- }
1621
-
1622
- body += this.renderer.tablerow(cell);
2192
+ case 'html': {
2193
+ out += renderer.html(token.text);
2194
+ break;
1623
2195
  }
1624
- return this.renderer.table(header, body);
1625
- }
1626
- case 'blockquote_start': {
1627
- body = '';
1628
-
1629
- while (this.next().type !== 'blockquote_end') {
1630
- body += this.tok();
2196
+ case 'link': {
2197
+ out += renderer.link(token.href, token.title, this.parseInline(token.tokens, renderer));
2198
+ break;
1631
2199
  }
1632
-
1633
- return this.renderer.blockquote(body);
1634
- }
1635
- case 'list_start': {
1636
- body = '';
1637
- const ordered = this.token.ordered,
1638
- start = this.token.start;
1639
-
1640
- while (this.next().type !== 'list_end') {
1641
- body += this.tok();
2200
+ case 'image': {
2201
+ out += renderer.image(token.href, token.title, token.text);
2202
+ break;
1642
2203
  }
1643
-
1644
- return this.renderer.list(body, ordered, start);
1645
- }
1646
- case 'list_item_start': {
1647
- body = '';
1648
- const loose = this.token.loose;
1649
- const checked = this.token.checked;
1650
- const task = this.token.task;
1651
-
1652
- if (this.token.task) {
1653
- if (loose) {
1654
- if (this.peek().type === 'text') {
1655
- const nextToken = this.peek();
1656
- nextToken.text = this.renderer.checkbox(checked) + ' ' + nextToken.text;
1657
- } else {
1658
- this.tokens.push({
1659
- type: 'text',
1660
- text: this.renderer.checkbox(checked)
1661
- });
1662
- }
1663
- } else {
1664
- body += this.renderer.checkbox(checked);
1665
- }
2204
+ case 'strong': {
2205
+ out += renderer.strong(this.parseInline(token.tokens, renderer));
2206
+ break;
1666
2207
  }
1667
-
1668
- while (this.next().type !== 'list_item_end') {
1669
- body += !loose && this.token.type === 'text'
1670
- ? this.parseText()
1671
- : this.tok();
2208
+ case 'em': {
2209
+ out += renderer.em(this.parseInline(token.tokens, renderer));
2210
+ break;
1672
2211
  }
1673
- return this.renderer.listitem(body, task, checked);
1674
- }
1675
- case 'html': {
1676
- // TODO parse inline content if parameter markdown=1
1677
- return this.renderer.html(this.token.text);
1678
- }
1679
- case 'paragraph': {
1680
- return this.renderer.paragraph(this.inline.output(this.token.text));
1681
- }
1682
- case 'text': {
1683
- return this.renderer.paragraph(this.parseText());
1684
- }
1685
- default: {
1686
- const errMsg = 'Token with "' + this.token.type + '" type was not found.';
1687
- if (this.options.silent) {
1688
- console.log(errMsg);
1689
- } else {
1690
- throw new Error(errMsg);
2212
+ case 'codespan': {
2213
+ out += renderer.codespan(token.text);
2214
+ break;
2215
+ }
2216
+ case 'br': {
2217
+ out += renderer.br();
2218
+ break;
2219
+ }
2220
+ case 'del': {
2221
+ out += renderer.del(this.parseInline(token.tokens, renderer));
2222
+ break;
2223
+ }
2224
+ case 'text': {
2225
+ out += renderer.text(token.text);
2226
+ break;
2227
+ }
2228
+ default: {
2229
+ const errMsg = 'Token with "' + token.type + '" type was not found.';
2230
+ if (this.options.silent) {
2231
+ console.error(errMsg);
2232
+ return;
2233
+ } else {
2234
+ throw new Error(errMsg);
2235
+ }
1691
2236
  }
1692
2237
  }
1693
2238
  }
1694
- };
2239
+ return out;
2240
+ }
1695
2241
  };
1696
2242
 
1697
2243
  const {
1698
- merge: merge$3,
2244
+ merge: merge$2,
1699
2245
  checkSanitizeDeprecation: checkSanitizeDeprecation$1,
1700
- escape: escape$4
2246
+ escape: escape$3
1701
2247
  } = helpers;
1702
2248
  const {
1703
2249
  getDefaults,
@@ -1718,18 +2264,17 @@ function marked(src, opt, callback) {
1718
2264
  + Object.prototype.toString.call(src) + ', string expected');
1719
2265
  }
1720
2266
 
1721
- if (callback || typeof opt === 'function') {
1722
- if (!callback) {
1723
- callback = opt;
1724
- opt = null;
1725
- }
2267
+ if (typeof opt === 'function') {
2268
+ callback = opt;
2269
+ opt = null;
2270
+ }
2271
+
2272
+ opt = merge$2({}, marked.defaults, opt || {});
2273
+ checkSanitizeDeprecation$1(opt);
1726
2274
 
1727
- opt = merge$3({}, marked.defaults, opt || {});
1728
- checkSanitizeDeprecation$1(opt);
2275
+ if (callback) {
1729
2276
  const highlight = opt.highlight;
1730
- let tokens,
1731
- pending,
1732
- i = 0;
2277
+ let tokens;
1733
2278
 
1734
2279
  try {
1735
2280
  tokens = Lexer_1.lex(src, opt);
@@ -1737,20 +2282,15 @@ function marked(src, opt, callback) {
1737
2282
  return callback(e);
1738
2283
  }
1739
2284
 
1740
- pending = tokens.length;
1741
-
1742
2285
  const done = function(err) {
1743
- if (err) {
1744
- opt.highlight = highlight;
1745
- return callback(err);
1746
- }
1747
-
1748
2286
  let out;
1749
2287
 
1750
- try {
1751
- out = Parser_1.parse(tokens, opt);
1752
- } catch (e) {
1753
- err = e;
2288
+ if (!err) {
2289
+ try {
2290
+ out = Parser_1.parse(tokens, opt);
2291
+ } catch (e) {
2292
+ err = e;
2293
+ }
1754
2294
  }
1755
2295
 
1756
2296
  opt.highlight = highlight;
@@ -1766,36 +2306,49 @@ function marked(src, opt, callback) {
1766
2306
 
1767
2307
  delete opt.highlight;
1768
2308
 
1769
- if (!pending) return done();
2309
+ if (!tokens.length) return done();
1770
2310
 
1771
- for (; i < tokens.length; i++) {
1772
- (function(token) {
1773
- if (token.type !== 'code') {
1774
- return --pending || done();
1775
- }
1776
- return highlight(token.text, token.lang, function(err, code) {
1777
- if (err) return done(err);
1778
- if (code == null || code === token.text) {
1779
- return --pending || done();
1780
- }
1781
- token.text = code;
1782
- token.escaped = true;
1783
- --pending || done();
1784
- });
1785
- })(tokens[i]);
2311
+ let pending = 0;
2312
+ marked.walkTokens(tokens, function(token) {
2313
+ if (token.type === 'code') {
2314
+ pending++;
2315
+ setTimeout(() => {
2316
+ highlight(token.text, token.lang, function(err, code) {
2317
+ if (err) {
2318
+ return done(err);
2319
+ }
2320
+ if (code != null && code !== token.text) {
2321
+ token.text = code;
2322
+ token.escaped = true;
2323
+ }
2324
+
2325
+ pending--;
2326
+ if (pending === 0) {
2327
+ done();
2328
+ }
2329
+ });
2330
+ }, 0);
2331
+ }
2332
+ });
2333
+
2334
+ if (pending === 0) {
2335
+ done();
1786
2336
  }
1787
2337
 
1788
2338
  return;
1789
2339
  }
2340
+
1790
2341
  try {
1791
- opt = merge$3({}, marked.defaults, opt || {});
1792
- checkSanitizeDeprecation$1(opt);
1793
- return Parser_1.parse(Lexer_1.lex(src, opt), opt);
2342
+ const tokens = Lexer_1.lex(src, opt);
2343
+ if (opt.walkTokens) {
2344
+ marked.walkTokens(tokens, opt.walkTokens);
2345
+ }
2346
+ return Parser_1.parse(tokens, opt);
1794
2347
  } catch (e) {
1795
2348
  e.message += '\nPlease report this to https://github.com/markedjs/marked.';
1796
- if ((opt || marked.defaults).silent) {
2349
+ if (opt.silent) {
1797
2350
  return '<p>An error occurred:</p><pre>'
1798
- + escape$4(e.message + '', true)
2351
+ + escape$3(e.message + '', true)
1799
2352
  + '</pre>';
1800
2353
  }
1801
2354
  throw e;
@@ -1808,7 +2361,7 @@ function marked(src, opt, callback) {
1808
2361
 
1809
2362
  marked.options =
1810
2363
  marked.setOptions = function(opt) {
1811
- merge$3(marked.defaults, opt);
2364
+ merge$2(marked.defaults, opt);
1812
2365
  changeDefaults(marked.defaults);
1813
2366
  return marked;
1814
2367
  };
@@ -1817,6 +2370,84 @@ marked.getDefaults = getDefaults;
1817
2370
 
1818
2371
  marked.defaults = defaults$5;
1819
2372
 
2373
+ /**
2374
+ * Use Extension
2375
+ */
2376
+
2377
+ marked.use = function(extension) {
2378
+ const opts = merge$2({}, extension);
2379
+ if (extension.renderer) {
2380
+ const renderer = marked.defaults.renderer || new Renderer_1();
2381
+ for (const prop in extension.renderer) {
2382
+ const prevRenderer = renderer[prop];
2383
+ renderer[prop] = (...args) => {
2384
+ let ret = extension.renderer[prop].apply(renderer, args);
2385
+ if (ret === false) {
2386
+ ret = prevRenderer.apply(renderer, args);
2387
+ }
2388
+ return ret;
2389
+ };
2390
+ }
2391
+ opts.renderer = renderer;
2392
+ }
2393
+ if (extension.tokenizer) {
2394
+ const tokenizer = marked.defaults.tokenizer || new Tokenizer_1();
2395
+ for (const prop in extension.tokenizer) {
2396
+ const prevTokenizer = tokenizer[prop];
2397
+ tokenizer[prop] = (...args) => {
2398
+ let ret = extension.tokenizer[prop].apply(tokenizer, args);
2399
+ if (ret === false) {
2400
+ ret = prevTokenizer.apply(tokenizer, args);
2401
+ }
2402
+ return ret;
2403
+ };
2404
+ }
2405
+ opts.tokenizer = tokenizer;
2406
+ }
2407
+ if (extension.walkTokens) {
2408
+ const walkTokens = marked.defaults.walkTokens;
2409
+ opts.walkTokens = (token) => {
2410
+ extension.walkTokens(token);
2411
+ if (walkTokens) {
2412
+ walkTokens(token);
2413
+ }
2414
+ };
2415
+ }
2416
+ marked.setOptions(opts);
2417
+ };
2418
+
2419
+ /**
2420
+ * Run callback for every token
2421
+ */
2422
+
2423
+ marked.walkTokens = function(tokens, callback) {
2424
+ for (const token of tokens) {
2425
+ callback(token);
2426
+ switch (token.type) {
2427
+ case 'table': {
2428
+ for (const cell of token.tokens.header) {
2429
+ marked.walkTokens(cell, callback);
2430
+ }
2431
+ for (const row of token.tokens.cells) {
2432
+ for (const cell of row) {
2433
+ marked.walkTokens(cell, callback);
2434
+ }
2435
+ }
2436
+ break;
2437
+ }
2438
+ case 'list': {
2439
+ marked.walkTokens(token.items, callback);
2440
+ break;
2441
+ }
2442
+ default: {
2443
+ if (token.tokens) {
2444
+ marked.walkTokens(token.tokens, callback);
2445
+ }
2446
+ }
2447
+ }
2448
+ }
2449
+ };
2450
+
1820
2451
  /**
1821
2452
  * Expose
1822
2453
  */
@@ -1830,8 +2461,7 @@ marked.TextRenderer = TextRenderer_1;
1830
2461
  marked.Lexer = Lexer_1;
1831
2462
  marked.lexer = Lexer_1.lex;
1832
2463
 
1833
- marked.InlineLexer = InlineLexer_1;
1834
- marked.inlineLexer = InlineLexer_1.output;
2464
+ marked.Tokenizer = Tokenizer_1;
1835
2465
 
1836
2466
  marked.Slugger = Slugger_1;
1837
2467