marked 1.0.0 → 1.2.0

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
@@ -32,6 +32,7 @@ function getDefaults() {
32
32
  smartLists: false,
33
33
  smartypants: false,
34
34
  tokenizer: null,
35
+ walkTokens: null,
35
36
  xhtml: false
36
37
  };
37
38
  }
@@ -305,6 +306,7 @@ const {
305
306
  function outputLink(cap, link, raw) {
306
307
  const href = link.href;
307
308
  const title = link.title ? escape$1(link.title) : null;
309
+ const text = cap[1].replace(/\\([\[\]])/g, '$1');
308
310
 
309
311
  if (cap[0].charAt(0) !== '!') {
310
312
  return {
@@ -312,19 +314,47 @@ function outputLink(cap, link, raw) {
312
314
  raw,
313
315
  href,
314
316
  title,
315
- text: cap[1]
317
+ text
316
318
  };
317
319
  } else {
318
320
  return {
319
321
  type: 'image',
320
322
  raw,
321
- text: escape$1(cap[1]),
322
323
  href,
323
- title
324
+ title,
325
+ text: escape$1(text)
324
326
  };
325
327
  }
326
328
  }
327
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
+
328
358
  /**
329
359
  * Tokenizer
330
360
  */
@@ -352,32 +382,35 @@ var Tokenizer_1 = class Tokenizer {
352
382
  const lastToken = tokens[tokens.length - 1];
353
383
  // An indented code block cannot interrupt a paragraph.
354
384
  if (lastToken && lastToken.type === 'paragraph') {
355
- tokens.pop();
356
- lastToken.text += '\n' + cap[0].trimRight();
357
- lastToken.raw += '\n' + cap[0];
358
- return lastToken;
359
- } else {
360
- const text = cap[0].replace(/^ {4}/gm, '');
361
385
  return {
362
- type: 'code',
363
386
  raw: cap[0],
364
- codeBlockStyle: 'indented',
365
- text: !this.options.pedantic
366
- ? rtrim$1(text, '\n')
367
- : text
387
+ text: cap[0].trimRight()
368
388
  };
369
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
+ };
370
400
  }
371
401
  }
372
402
 
373
403
  fences(src) {
374
404
  const cap = this.rules.block.fences.exec(src);
375
405
  if (cap) {
406
+ const raw = cap[0];
407
+ const text = indentCodeCompensation(raw, cap[3] || '');
408
+
376
409
  return {
377
410
  type: 'code',
378
- raw: cap[0],
411
+ raw,
379
412
  lang: cap[2] ? cap[2].trim() : cap[2],
380
- text: cap[3] || ''
413
+ text
381
414
  };
382
415
  }
383
416
  }
@@ -459,12 +492,13 @@ var Tokenizer_1 = class Tokenizer {
459
492
  let raw = cap[0];
460
493
  const bull = cap[2];
461
494
  const isordered = bull.length > 1;
495
+ const isparen = bull[bull.length - 1] === ')';
462
496
 
463
497
  const list = {
464
498
  type: 'list',
465
499
  raw,
466
500
  ordered: isordered,
467
- start: isordered ? +bull : '',
501
+ start: isordered ? +bull.slice(0, -1) : '',
468
502
  loose: false,
469
503
  items: []
470
504
  };
@@ -489,7 +523,7 @@ var Tokenizer_1 = class Tokenizer {
489
523
  // Remove the list item's bullet
490
524
  // so it is seen as the next token.
491
525
  space = item.length;
492
- item = item.replace(/^ *([*+-]|\d+\.) */, '');
526
+ item = item.replace(/^ *([*+-]|\d+[.)]) */, '');
493
527
 
494
528
  // Outdent whatever the
495
529
  // list item contains. Hacky.
@@ -504,7 +538,7 @@ var Tokenizer_1 = class Tokenizer {
504
538
  // Backpedal if it does not belong in this list.
505
539
  if (i !== l - 1) {
506
540
  b = this.rules.block.bullet.exec(itemMatch[i + 1])[0];
507
- if (bull.length > 1 ? b.length === 1
541
+ if (isordered ? b.length === 1 || (!isparen && b[b.length - 1] === ')')
508
542
  : (b.length > 1 || (this.options.smartLists && b !== bull))) {
509
543
  addBack = itemMatch.slice(i + 1).join('\n');
510
544
  list.raw = list.raw.substring(0, list.raw.length - addBack.length);
@@ -534,6 +568,7 @@ var Tokenizer_1 = class Tokenizer {
534
568
  }
535
569
 
536
570
  list.items.push({
571
+ type: 'list_item',
537
572
  raw,
538
573
  task: istask,
539
574
  checked: ischecked,
@@ -639,9 +674,17 @@ var Tokenizer_1 = class Tokenizer {
639
674
  }
640
675
  }
641
676
 
642
- text(src) {
677
+ text(src, tokens) {
643
678
  const cap = this.rules.block.text.exec(src);
644
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
+
645
688
  return {
646
689
  type: 'text',
647
690
  raw: cap[0],
@@ -744,35 +787,66 @@ var Tokenizer_1 = class Tokenizer {
744
787
  }
745
788
  }
746
789
 
747
- strong(src) {
748
- const cap = this.rules.inline.strong.exec(src);
749
- if (cap) {
750
- return {
751
- type: 'strong',
752
- raw: cap[0],
753
- text: cap[4] || cap[3] || cap[2] || cap[1]
754
- };
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
+ }
755
810
  }
756
811
  }
757
812
 
758
- em(src) {
759
- const cap = this.rules.inline.em.exec(src);
760
- if (cap) {
761
- return {
762
- type: 'em',
763
- raw: cap[0],
764
- text: cap[6] || cap[5] || cap[4] || cap[3] || cap[2] || cap[1]
765
- };
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
+ }
766
833
  }
767
834
  }
768
835
 
769
836
  codespan(src) {
770
837
  const cap = this.rules.inline.code.exec(src);
771
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);
772
846
  return {
773
847
  type: 'codespan',
774
848
  raw: cap[0],
775
- text: escape$1(cap[2].trim(), true)
849
+ text
776
850
  };
777
851
  }
778
852
  }
@@ -901,9 +975,9 @@ const block = {
901
975
  html: '^ {0,3}(?:' // optional indentation
902
976
  + '<(script|pre|style)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)' // (1)
903
977
  + '|comment[^\\n]*(\\n+|$)' // (2)
904
- + '|<\\?[\\s\\S]*?\\?>\\n*' // (3)
905
- + '|<![A-Z][\\s\\S]*?>\\n*' // (4)
906
- + '|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>\\n*' // (5)
978
+ + '|<\\?[\\s\\S]*?(?:\\?>\\n*|$)' // (3)
979
+ + '|<![A-Z][\\s\\S]*?(?:>\\n*|$)' // (4)
980
+ + '|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)' // (5)
907
981
  + '|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:\\n{2,}|$)' // (6)
908
982
  + '|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)' // (7) open tag
909
983
  + '|</(?!script|pre|style)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)' // (7) closing tag
@@ -925,7 +999,7 @@ block.def = edit$1(block.def)
925
999
  .replace('title', block._title)
926
1000
  .getRegex();
927
1001
 
928
- block.bullet = /(?:[*+-]|\d{1,9}\.)/;
1002
+ block.bullet = /(?:[*+-]|\d{1,9}[.)])/;
929
1003
  block.item = /^( *)(bull) ?[^\n]*(?:\n(?!\1bull ?)[^\n]*)*/;
930
1004
  block.item = edit$1(block.item, 'gm')
931
1005
  .replace(/bull/g, block.bullet)
@@ -943,7 +1017,7 @@ block._tag = 'address|article|aside|base|basefont|blockquote|body|caption'
943
1017
  + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option'
944
1018
  + '|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr'
945
1019
  + '|track|ul';
946
- block._comment = /<!--(?!-?>)[\s\S]*?-->/;
1020
+ block._comment = /<!--(?!-?>)[\s\S]*?(?:-->|$)/;
947
1021
  block.html = edit$1(block.html, 'i')
948
1022
  .replace('comment', block._comment)
949
1023
  .replace('tag', block._tag)
@@ -977,10 +1051,10 @@ block.normal = merge$1({}, block);
977
1051
 
978
1052
  block.gfm = merge$1({}, block.normal, {
979
1053
  nptable: '^ *([^|\\n ].*\\|.*)\\n' // Header
980
- + ' *([-:]+ *\\|[-| :]*)' // Align
1054
+ + ' {0,3}([-:]+ *\\|[-| :]*)' // Align
981
1055
  + '(?:\\n((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)', // Cells
982
1056
  table: '^ *\\|(.+)\\n' // Header
983
- + ' *\\|?( *[-:]+[-| :]*)' // Align
1057
+ + ' {0,3}\\|?( *[-:]+[-| :]*)' // Align
984
1058
  + '(?:\\n *((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)' // Cells
985
1059
  });
986
1060
 
@@ -1051,18 +1125,76 @@ const inline = {
1051
1125
  link: /^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,
1052
1126
  reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,
1053
1127
  nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,
1054
- strong: /^__([^\s_])__(?!_)|^\*\*([^\s*])\*\*(?!\*)|^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)/,
1055
- em: /^_([^\s_])_(?!_)|^_([^\s_<][\s\S]*?[^\s_])_(?!_|[^\spunctuation])|^_([^\s_<][\s\S]*?[^\s])_(?!_|[^\spunctuation])|^\*([^\s*<\[])\*(?!\*)|^\*([^\s<"][\s\S]*?[^\s\[\*])\*(?![\]`punctuation])|^\*([^\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
+ },
1056
1141
  code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,
1057
1142
  br: /^( {2,}|\\)\n(?!\s*$)/,
1058
1143
  del: noopTest$1,
1059
- text: /^(`+|[^`])(?:[\s\S]*?(?:(?=[\\<!\[`*]|\b_|$)|[^ ](?= {2,}\n))|(?= {2,}\n))/
1144
+ text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*]|\b_|$)|[^ ](?= {2,}\n)))/,
1145
+ punctuation: /^([\s*punctuation])/
1060
1146
  };
1061
1147
 
1062
1148
  // list of punctuation marks from common mark spec
1063
- // without ` and ] to workaround Rule 17 (inline code blocks/links)
1064
- inline._punctuation = '!"#$%&\'()*+\\-./:;<=>?@\\[^_{|}~';
1065
- 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._comment = edit$1(block._comment).replace('(?:-->|$)', '-->').getRegex();
1158
+
1159
+ inline.em.start = edit$1(inline.em.start)
1160
+ .replace(/punctuation/g, inline._punctuation)
1161
+ .getRegex();
1162
+
1163
+ inline.em.middle = edit$1(inline.em.middle)
1164
+ .replace(/punctuation/g, inline._punctuation)
1165
+ .replace(/overlapSkip/g, inline._overlapSkip)
1166
+ .getRegex();
1167
+
1168
+ inline.em.endAst = edit$1(inline.em.endAst, 'g')
1169
+ .replace(/punctuation/g, inline._punctuation)
1170
+ .getRegex();
1171
+
1172
+ inline.em.endUnd = edit$1(inline.em.endUnd, 'g')
1173
+ .replace(/punctuation/g, inline._punctuation)
1174
+ .getRegex();
1175
+
1176
+ inline.strong.start = edit$1(inline.strong.start)
1177
+ .replace(/punctuation/g, inline._punctuation)
1178
+ .getRegex();
1179
+
1180
+ inline.strong.middle = edit$1(inline.strong.middle)
1181
+ .replace(/punctuation/g, inline._punctuation)
1182
+ .replace(/overlapSkip/g, inline._overlapSkip)
1183
+ .getRegex();
1184
+
1185
+ inline.strong.endAst = edit$1(inline.strong.endAst, 'g')
1186
+ .replace(/punctuation/g, inline._punctuation)
1187
+ .getRegex();
1188
+
1189
+ inline.strong.endUnd = edit$1(inline.strong.endUnd, 'g')
1190
+ .replace(/punctuation/g, inline._punctuation)
1191
+ .getRegex();
1192
+
1193
+ inline.blockSkip = edit$1(inline._blockSkip, 'g')
1194
+ .getRegex();
1195
+
1196
+ inline.overlapSkip = edit$1(inline._overlapSkip, 'g')
1197
+ .getRegex();
1066
1198
 
1067
1199
  inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;
1068
1200
 
@@ -1076,11 +1208,11 @@ inline.autolink = edit$1(inline.autolink)
1076
1208
  inline._attribute = /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/;
1077
1209
 
1078
1210
  inline.tag = edit$1(inline.tag)
1079
- .replace('comment', block._comment)
1211
+ .replace('comment', inline._comment)
1080
1212
  .replace('attribute', inline._attribute)
1081
1213
  .getRegex();
1082
1214
 
1083
- inline._label = /(?:\[[^\[\]]*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
1215
+ inline._label = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
1084
1216
  inline._href = /<(?:\\[<>]?|[^\s<>\\])*>|[^\s\x00-\x1f]*/;
1085
1217
  inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/;
1086
1218
 
@@ -1094,6 +1226,11 @@ inline.reflink = edit$1(inline.reflink)
1094
1226
  .replace('label', inline._label)
1095
1227
  .getRegex();
1096
1228
 
1229
+ inline.reflinkSearch = edit$1(inline.reflinkSearch, 'g')
1230
+ .replace('reflink', inline.reflink)
1231
+ .replace('nolink', inline.nolink)
1232
+ .getRegex();
1233
+
1097
1234
  /**
1098
1235
  * Normal Inline Grammar
1099
1236
  */
@@ -1105,8 +1242,18 @@ inline.normal = merge$1({}, inline);
1105
1242
  */
1106
1243
 
1107
1244
  inline.pedantic = merge$1({}, inline.normal, {
1108
- strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
1109
- em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/,
1245
+ strong: {
1246
+ start: /^__|\*\*/,
1247
+ middle: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
1248
+ endAst: /\*\*(?!\*)/g,
1249
+ endUnd: /__(?!_)/g
1250
+ },
1251
+ em: {
1252
+ start: /^_|\*/,
1253
+ middle: /^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/,
1254
+ endAst: /\*(?!\*)/g,
1255
+ endUnd: /_(?!_)/g
1256
+ },
1110
1257
  link: edit$1(/^!?\[(label)\]\((.*?)\)/)
1111
1258
  .replace('label', inline._label)
1112
1259
  .getRegex(),
@@ -1125,7 +1272,7 @@ inline.gfm = merge$1({}, inline.normal, {
1125
1272
  url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,
1126
1273
  _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,
1127
1274
  del: /^~+(?=\S)([\s\S]*?\S)~+/,
1128
- text: /^(`+|[^`])(?:[\s\S]*?(?:(?=[\\<!\[`*~]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@))|(?= {2,}\n|[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@))/
1275
+ text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*~]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@))|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@))/
1129
1276
  });
1130
1277
 
1131
1278
  inline.gfm.url = edit$1(inline.gfm.url, 'i')
@@ -1241,6 +1388,14 @@ var Lexer_1 = class Lexer {
1241
1388
  return lexer.lex(src);
1242
1389
  }
1243
1390
 
1391
+ /**
1392
+ * Static Lex Inline Method
1393
+ */
1394
+ static lexInline(src, options) {
1395
+ const lexer = new Lexer(options);
1396
+ return lexer.inlineTokens(src);
1397
+ }
1398
+
1244
1399
  /**
1245
1400
  * Preprocessing
1246
1401
  */
@@ -1261,7 +1416,7 @@ var Lexer_1 = class Lexer {
1261
1416
  */
1262
1417
  blockTokens(src, tokens = [], top = true) {
1263
1418
  src = src.replace(/^ +$/gm, '');
1264
- let token, i, l;
1419
+ let token, i, l, lastToken;
1265
1420
 
1266
1421
  while (src) {
1267
1422
  // newline
@@ -1276,7 +1431,13 @@ var Lexer_1 = class Lexer {
1276
1431
  // code
1277
1432
  if (token = this.tokenizer.code(src, tokens)) {
1278
1433
  src = src.substring(token.raw.length);
1279
- tokens.push(token);
1434
+ if (token.type) {
1435
+ tokens.push(token);
1436
+ } else {
1437
+ lastToken = tokens[tokens.length - 1];
1438
+ lastToken.raw += '\n' + token.raw;
1439
+ lastToken.text += '\n' + token.text;
1440
+ }
1280
1441
  continue;
1281
1442
  }
1282
1443
 
@@ -1368,9 +1529,15 @@ var Lexer_1 = class Lexer {
1368
1529
  }
1369
1530
 
1370
1531
  // text
1371
- if (token = this.tokenizer.text(src)) {
1532
+ if (token = this.tokenizer.text(src, tokens)) {
1372
1533
  src = src.substring(token.raw.length);
1373
- tokens.push(token);
1534
+ if (token.type) {
1535
+ tokens.push(token);
1536
+ } else {
1537
+ lastToken = tokens[tokens.length - 1];
1538
+ lastToken.raw += '\n' + token.raw;
1539
+ lastToken.text += '\n' + token.text;
1540
+ }
1374
1541
  continue;
1375
1542
  }
1376
1543
 
@@ -1453,9 +1620,29 @@ var Lexer_1 = class Lexer {
1453
1620
  /**
1454
1621
  * Lexing/Compiling
1455
1622
  */
1456
- inlineTokens(src, tokens = [], inLink = false, inRawBlock = false) {
1623
+ inlineTokens(src, tokens = [], inLink = false, inRawBlock = false, prevChar = '') {
1457
1624
  let token;
1458
1625
 
1626
+ // String with links masked to avoid interference with em and strong
1627
+ let maskedSrc = src;
1628
+ let match;
1629
+
1630
+ // Mask out reflinks
1631
+ if (this.tokens.links) {
1632
+ const links = Object.keys(this.tokens.links);
1633
+ if (links.length > 0) {
1634
+ while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {
1635
+ if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) {
1636
+ maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);
1637
+ }
1638
+ }
1639
+ }
1640
+ }
1641
+ // Mask out other blocks
1642
+ while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {
1643
+ maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
1644
+ }
1645
+
1459
1646
  while (src) {
1460
1647
  // escape
1461
1648
  if (token = this.tokenizer.escape(src)) {
@@ -1494,7 +1681,7 @@ var Lexer_1 = class Lexer {
1494
1681
  }
1495
1682
 
1496
1683
  // strong
1497
- if (token = this.tokenizer.strong(src)) {
1684
+ if (token = this.tokenizer.strong(src, maskedSrc, prevChar)) {
1498
1685
  src = src.substring(token.raw.length);
1499
1686
  token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock);
1500
1687
  tokens.push(token);
@@ -1502,7 +1689,7 @@ var Lexer_1 = class Lexer {
1502
1689
  }
1503
1690
 
1504
1691
  // em
1505
- if (token = this.tokenizer.em(src)) {
1692
+ if (token = this.tokenizer.em(src, maskedSrc, prevChar)) {
1506
1693
  src = src.substring(token.raw.length);
1507
1694
  token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock);
1508
1695
  tokens.push(token);
@@ -1548,6 +1735,7 @@ var Lexer_1 = class Lexer {
1548
1735
  // text
1549
1736
  if (token = this.tokenizer.inlineText(src, inRawBlock, smartypants)) {
1550
1737
  src = src.substring(token.raw.length);
1738
+ prevChar = token.raw.slice(-1);
1551
1739
  tokens.push(token);
1552
1740
  continue;
1553
1741
  }
@@ -1594,7 +1782,7 @@ var Renderer_1 = class Renderer {
1594
1782
  if (!lang) {
1595
1783
  return '<pre><code>'
1596
1784
  + (escaped ? code : escape$2(code, true))
1597
- + '</code></pre>';
1785
+ + '</code></pre>\n';
1598
1786
  }
1599
1787
 
1600
1788
  return '<pre><code class="'
@@ -1783,11 +1971,8 @@ var Slugger_1 = class Slugger {
1783
1971
  this.seen = {};
1784
1972
  }
1785
1973
 
1786
- /**
1787
- * Convert string to unique id
1788
- */
1789
- slug(value) {
1790
- let slug = value
1974
+ serialize(value) {
1975
+ return value
1791
1976
  .toLowerCase()
1792
1977
  .trim()
1793
1978
  // remove html tags
@@ -1795,18 +1980,37 @@ var Slugger_1 = class Slugger {
1795
1980
  // remove unwanted chars
1796
1981
  .replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '')
1797
1982
  .replace(/\s/g, '-');
1983
+ }
1798
1984
 
1985
+ /**
1986
+ * Finds the next safe (unique) slug to use
1987
+ */
1988
+ getNextSafeSlug(originalSlug, isDryRun) {
1989
+ let slug = originalSlug;
1990
+ let occurenceAccumulator = 0;
1799
1991
  if (this.seen.hasOwnProperty(slug)) {
1800
- const originalSlug = slug;
1992
+ occurenceAccumulator = this.seen[originalSlug];
1801
1993
  do {
1802
- this.seen[originalSlug]++;
1803
- slug = originalSlug + '-' + this.seen[originalSlug];
1994
+ occurenceAccumulator++;
1995
+ slug = originalSlug + '-' + occurenceAccumulator;
1804
1996
  } while (this.seen.hasOwnProperty(slug));
1805
1997
  }
1806
- this.seen[slug] = 0;
1807
-
1998
+ if (!isDryRun) {
1999
+ this.seen[originalSlug] = occurenceAccumulator;
2000
+ this.seen[slug] = 0;
2001
+ }
1808
2002
  return slug;
1809
2003
  }
2004
+
2005
+ /**
2006
+ * Convert string to unique id
2007
+ * @param {object} options
2008
+ * @param {boolean} options.dryrun Generates the next unique slug without updating the internal accumulator.
2009
+ */
2010
+ slug(value, options = {}) {
2011
+ const slug = this.serialize(value);
2012
+ return this.getNextSafeSlug(slug, options.dryrun);
2013
+ }
1810
2014
  };
1811
2015
 
1812
2016
  const { defaults: defaults$4 } = defaults;
@@ -1835,6 +2039,14 @@ var Parser_1 = class Parser {
1835
2039
  return parser.parse(tokens);
1836
2040
  }
1837
2041
 
2042
+ /**
2043
+ * Static Parse Inline Method
2044
+ */
2045
+ static parseInline(tokens, options) {
2046
+ const parser = new Parser(options);
2047
+ return parser.parseInline(tokens);
2048
+ }
2049
+
1838
2050
  /**
1839
2051
  * Parse Loop
1840
2052
  */
@@ -1938,7 +2150,7 @@ var Parser_1 = class Parser {
1938
2150
  if (item.task) {
1939
2151
  checkbox = this.renderer.checkbox(checked);
1940
2152
  if (loose) {
1941
- if (item.tokens[0].type === 'text') {
2153
+ if (item.tokens.length > 0 && item.tokens[0].type === 'text') {
1942
2154
  item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
1943
2155
  if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {
1944
2156
  item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text;
@@ -2086,18 +2298,17 @@ function marked(src, opt, callback) {
2086
2298
  + Object.prototype.toString.call(src) + ', string expected');
2087
2299
  }
2088
2300
 
2089
- if (callback || typeof opt === 'function') {
2090
- if (!callback) {
2091
- callback = opt;
2092
- opt = null;
2093
- }
2301
+ if (typeof opt === 'function') {
2302
+ callback = opt;
2303
+ opt = null;
2304
+ }
2094
2305
 
2095
- opt = merge$2({}, marked.defaults, opt || {});
2096
- checkSanitizeDeprecation$1(opt);
2306
+ opt = merge$2({}, marked.defaults, opt || {});
2307
+ checkSanitizeDeprecation$1(opt);
2308
+
2309
+ if (callback) {
2097
2310
  const highlight = opt.highlight;
2098
- let tokens,
2099
- pending,
2100
- i = 0;
2311
+ let tokens;
2101
2312
 
2102
2313
  try {
2103
2314
  tokens = Lexer_1.lex(src, opt);
@@ -2105,20 +2316,15 @@ function marked(src, opt, callback) {
2105
2316
  return callback(e);
2106
2317
  }
2107
2318
 
2108
- pending = tokens.length;
2109
-
2110
2319
  const done = function(err) {
2111
- if (err) {
2112
- opt.highlight = highlight;
2113
- return callback(err);
2114
- }
2115
-
2116
2320
  let out;
2117
2321
 
2118
- try {
2119
- out = Parser_1.parse(tokens, opt);
2120
- } catch (e) {
2121
- err = e;
2322
+ if (!err) {
2323
+ try {
2324
+ out = Parser_1.parse(tokens, opt);
2325
+ } catch (e) {
2326
+ err = e;
2327
+ }
2122
2328
  }
2123
2329
 
2124
2330
  opt.highlight = highlight;
@@ -2134,34 +2340,47 @@ function marked(src, opt, callback) {
2134
2340
 
2135
2341
  delete opt.highlight;
2136
2342
 
2137
- if (!pending) return done();
2343
+ if (!tokens.length) return done();
2138
2344
 
2139
- for (; i < tokens.length; i++) {
2140
- (function(token) {
2141
- if (token.type !== 'code') {
2142
- return --pending || done();
2143
- }
2144
- return highlight(token.text, token.lang, function(err, code) {
2145
- if (err) return done(err);
2146
- if (code == null || code === token.text) {
2147
- return --pending || done();
2148
- }
2149
- token.text = code;
2150
- token.escaped = true;
2151
- --pending || done();
2152
- });
2153
- })(tokens[i]);
2345
+ let pending = 0;
2346
+ marked.walkTokens(tokens, function(token) {
2347
+ if (token.type === 'code') {
2348
+ pending++;
2349
+ setTimeout(() => {
2350
+ highlight(token.text, token.lang, function(err, code) {
2351
+ if (err) {
2352
+ return done(err);
2353
+ }
2354
+ if (code != null && code !== token.text) {
2355
+ token.text = code;
2356
+ token.escaped = true;
2357
+ }
2358
+
2359
+ pending--;
2360
+ if (pending === 0) {
2361
+ done();
2362
+ }
2363
+ });
2364
+ }, 0);
2365
+ }
2366
+ });
2367
+
2368
+ if (pending === 0) {
2369
+ done();
2154
2370
  }
2155
2371
 
2156
2372
  return;
2157
2373
  }
2374
+
2158
2375
  try {
2159
- opt = merge$2({}, marked.defaults, opt || {});
2160
- checkSanitizeDeprecation$1(opt);
2161
- return Parser_1.parse(Lexer_1.lex(src, opt), opt);
2376
+ const tokens = Lexer_1.lex(src, opt);
2377
+ if (opt.walkTokens) {
2378
+ marked.walkTokens(tokens, opt.walkTokens);
2379
+ }
2380
+ return Parser_1.parse(tokens, opt);
2162
2381
  } catch (e) {
2163
2382
  e.message += '\nPlease report this to https://github.com/markedjs/marked.';
2164
- if ((opt || marked.defaults).silent) {
2383
+ if (opt.silent) {
2165
2384
  return '<p>An error occurred:</p><pre>'
2166
2385
  + escape$3(e.message + '', true)
2167
2386
  + '</pre>';
@@ -2219,9 +2438,83 @@ marked.use = function(extension) {
2219
2438
  }
2220
2439
  opts.tokenizer = tokenizer;
2221
2440
  }
2441
+ if (extension.walkTokens) {
2442
+ const walkTokens = marked.defaults.walkTokens;
2443
+ opts.walkTokens = (token) => {
2444
+ extension.walkTokens(token);
2445
+ if (walkTokens) {
2446
+ walkTokens(token);
2447
+ }
2448
+ };
2449
+ }
2222
2450
  marked.setOptions(opts);
2223
2451
  };
2224
2452
 
2453
+ /**
2454
+ * Run callback for every token
2455
+ */
2456
+
2457
+ marked.walkTokens = function(tokens, callback) {
2458
+ for (const token of tokens) {
2459
+ callback(token);
2460
+ switch (token.type) {
2461
+ case 'table': {
2462
+ for (const cell of token.tokens.header) {
2463
+ marked.walkTokens(cell, callback);
2464
+ }
2465
+ for (const row of token.tokens.cells) {
2466
+ for (const cell of row) {
2467
+ marked.walkTokens(cell, callback);
2468
+ }
2469
+ }
2470
+ break;
2471
+ }
2472
+ case 'list': {
2473
+ marked.walkTokens(token.items, callback);
2474
+ break;
2475
+ }
2476
+ default: {
2477
+ if (token.tokens) {
2478
+ marked.walkTokens(token.tokens, callback);
2479
+ }
2480
+ }
2481
+ }
2482
+ }
2483
+ };
2484
+
2485
+ /**
2486
+ * Parse Inline
2487
+ */
2488
+ marked.parseInline = function(src, opt) {
2489
+ // throw error in case of non string input
2490
+ if (typeof src === 'undefined' || src === null) {
2491
+ throw new Error('marked.parseInline(): input parameter is undefined or null');
2492
+ }
2493
+ if (typeof src !== 'string') {
2494
+ throw new Error('marked.parseInline(): input parameter is of type '
2495
+ + Object.prototype.toString.call(src) + ', string expected');
2496
+ }
2497
+
2498
+ opt = merge$2({}, marked.defaults, opt || {});
2499
+ checkSanitizeDeprecation$1(opt);
2500
+
2501
+ try {
2502
+ const tokens = Lexer_1.lexInline(src, opt);
2503
+ if (opt.walkTokens) {
2504
+ marked.walkTokens(tokens, opt.walkTokens);
2505
+ }
2506
+ return Parser_1.parseInline(tokens, opt);
2507
+ } catch (e) {
2508
+ e.message += '\nPlease report this to https://github.com/markedjs/marked.';
2509
+ if (opt.silent) {
2510
+ return '<p>An error occurred:</p><pre>'
2511
+ + escape$3(e.message + '', true)
2512
+ + '</pre>';
2513
+ }
2514
+ throw e;
2515
+ }
2516
+ };
2517
+
2225
2518
  /**
2226
2519
  * Expose
2227
2520
  */