marked 1.2.7 → 2.0.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
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * marked - a markdown parser
3
- * Copyright (c) 2011-2020, Christopher Jeffrey. (MIT Licensed)
3
+ * Copyright (c) 2011-2021, Christopher Jeffrey. (MIT Licensed)
4
4
  * https://github.com/markedjs/marked
5
5
  */
6
6
 
@@ -9,8 +9,9 @@
9
9
  * The code in this file is generated from files in ./src/
10
10
  */
11
11
 
12
- function createCommonjsModule(fn, module) {
13
- return module = { exports: {} }, fn(module, module.exports), module.exports;
12
+ function createCommonjsModule(fn) {
13
+ var module = { exports: {} };
14
+ return fn(module, module.exports), module.exports;
14
15
  }
15
16
 
16
17
  var defaults = createCommonjsModule(function (module) {
@@ -47,9 +48,6 @@ module.exports = {
47
48
  changeDefaults
48
49
  };
49
50
  });
50
- var defaults_1 = defaults.defaults;
51
- var defaults_2 = defaults.getDefaults;
52
- var defaults_3 = defaults.changeDefaults;
53
51
 
54
52
  /**
55
53
  * Helpers
@@ -393,19 +391,10 @@ var Tokenizer_1 = class Tokenizer {
393
391
  }
394
392
  }
395
393
 
396
- code(src, tokens) {
394
+ code(src) {
397
395
  const cap = this.rules.block.code.exec(src);
398
396
  if (cap) {
399
- const lastToken = tokens[tokens.length - 1];
400
- // An indented code block cannot interrupt a paragraph.
401
- if (lastToken && lastToken.type === 'paragraph') {
402
- return {
403
- raw: cap[0],
404
- text: cap[0].trimRight()
405
- };
406
- }
407
-
408
- const text = cap[0].replace(/^ {4}/gm, '');
397
+ const text = cap[0].replace(/^ {1,4}/gm, '');
409
398
  return {
410
399
  type: 'code',
411
400
  raw: cap[0],
@@ -543,7 +532,8 @@ var Tokenizer_1 = class Tokenizer {
543
532
  addBack,
544
533
  loose,
545
534
  istask,
546
- ischecked;
535
+ ischecked,
536
+ endMatch;
547
537
 
548
538
  let l = itemMatch.length;
549
539
  bcurr = this.rules.block.listItemStart.exec(itemMatch[0]);
@@ -551,28 +541,42 @@ var Tokenizer_1 = class Tokenizer {
551
541
  item = itemMatch[i];
552
542
  raw = item;
553
543
 
544
+ if (!this.options.pedantic) {
545
+ // Determine if current item contains the end of the list
546
+ endMatch = item.match(new RegExp('\\n\\s*\\n {0,' + (bcurr[0].length - 1) + '}\\S'));
547
+ if (endMatch) {
548
+ addBack = item.length - endMatch.index + itemMatch.slice(i + 1).join('\n').length;
549
+ list.raw = list.raw.substring(0, list.raw.length - addBack);
550
+
551
+ item = item.substring(0, endMatch.index);
552
+ raw = item;
553
+ l = i + 1;
554
+ }
555
+ }
556
+
554
557
  // Determine whether the next list item belongs here.
555
558
  // Backpedal if it does not belong in this list.
556
559
  if (i !== l - 1) {
557
560
  bnext = this.rules.block.listItemStart.exec(itemMatch[i + 1]);
558
-
559
- if (bnext[1].length > bcurr[0].length || bnext[1].length > 3) {
560
- // nested list
561
- itemMatch.splice(i, 2, itemMatch[i] + '\n' + itemMatch[i + 1]);
561
+ if (
562
+ !this.options.pedantic
563
+ ? bnext[1].length >= bcurr[0].length || bnext[1].length > 3
564
+ : bnext[1].length > bcurr[1].length
565
+ ) {
566
+ // nested list or continuation
567
+ itemMatch.splice(i, 2, itemMatch[i] + (!this.options.pedantic && bnext[1].length < bcurr[0].length && !itemMatch[i].match(/\n$/) ? '' : '\n') + itemMatch[i + 1]);
562
568
  i--;
563
569
  l--;
564
570
  continue;
565
- } else {
566
- if (
567
- // different bullet style
568
- !this.options.pedantic || this.options.smartLists
569
- ? bnext[2][bnext[2].length - 1] !== bull[bull.length - 1]
570
- : isordered === (bnext[2].length === 1)
571
- ) {
572
- addBack = itemMatch.slice(i + 1).join('\n');
573
- list.raw = list.raw.substring(0, list.raw.length - addBack.length);
574
- i = l - 1;
575
- }
571
+ } else if (
572
+ // different bullet style
573
+ !this.options.pedantic || this.options.smartLists
574
+ ? bnext[2][bnext[2].length - 1] !== bull[bull.length - 1]
575
+ : isordered === (bnext[2].length === 1)
576
+ ) {
577
+ addBack = itemMatch.slice(i + 1).join('\n').length;
578
+ list.raw = list.raw.substring(0, list.raw.length - addBack);
579
+ i = l - 1;
576
580
  }
577
581
  bcurr = bnext;
578
582
  }
@@ -591,12 +595,18 @@ var Tokenizer_1 = class Tokenizer {
591
595
  : item.replace(/^ {1,4}/gm, '');
592
596
  }
593
597
 
598
+ // trim item newlines at end
599
+ item = rtrim$1(item, '\n');
600
+ if (i !== l - 1) {
601
+ raw = raw + '\n';
602
+ }
603
+
594
604
  // Determine whether item is loose or not.
595
605
  // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
596
606
  // for discount behavior.
597
- loose = next || /\n\n(?!\s*$)/.test(item);
607
+ loose = next || /\n\n(?!\s*$)/.test(raw);
598
608
  if (i !== l - 1) {
599
- next = item.charAt(item.length - 1) === '\n';
609
+ next = raw.slice(-2) === '\n\n';
600
610
  if (!loose) loose = next;
601
611
  }
602
612
 
@@ -721,17 +731,9 @@ var Tokenizer_1 = class Tokenizer {
721
731
  }
722
732
  }
723
733
 
724
- text(src, tokens) {
734
+ text(src) {
725
735
  const cap = this.rules.block.text.exec(src);
726
736
  if (cap) {
727
- const lastToken = tokens[tokens.length - 1];
728
- if (lastToken && lastToken.type === 'text') {
729
- return {
730
- raw: cap[0],
731
- text: cap[0]
732
- };
733
- }
734
-
735
737
  return {
736
738
  type: 'text',
737
739
  raw: cap[0],
@@ -855,46 +857,61 @@ var Tokenizer_1 = class Tokenizer {
855
857
  }
856
858
  }
857
859
 
858
- strong(src, maskedSrc, prevChar = '') {
859
- let match = this.rules.inline.strong.start.exec(src);
860
+ emStrong(src, maskedSrc, prevChar = '') {
861
+ let match = this.rules.inline.emStrong.lDelim.exec(src);
862
+ if (!match) return;
860
863
 
861
- if (match && (!match[1] || (match[1] && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar))))) {
862
- maskedSrc = maskedSrc.slice(-1 * src.length);
863
- const endReg = match[0] === '**' ? this.rules.inline.strong.endAst : this.rules.inline.strong.endUnd;
864
+ if (match[3] && prevChar.match(/[\p{L}\p{N}]/u)) return; // _ can't be between two alphanumerics. \p{L}\p{N} includes non-english alphabet/numbers as well
864
865
 
866
+ const nextChar = match[1] || match[2] || '';
867
+
868
+ if (!nextChar || (nextChar && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar)))) {
869
+ const lLength = match[0].length - 1;
870
+ let rDelim, rLength, delimTotal = lLength, midDelimTotal = 0;
871
+
872
+ const endReg = match[0][0] === '*' ? this.rules.inline.emStrong.rDelimAst : this.rules.inline.emStrong.rDelimUnd;
865
873
  endReg.lastIndex = 0;
866
874
 
867
- let cap;
875
+ maskedSrc = maskedSrc.slice(-1 * src.length + lLength); // Bump maskedSrc to same section of string as src (move to lexer?)
876
+
868
877
  while ((match = endReg.exec(maskedSrc)) != null) {
869
- cap = this.rules.inline.strong.middle.exec(maskedSrc.slice(0, match.index + 3));
870
- if (cap) {
871
- return {
872
- type: 'strong',
873
- raw: src.slice(0, cap[0].length),
874
- text: src.slice(2, cap[0].length - 2)
875
- };
878
+ rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6];
879
+
880
+ if (!rDelim) continue; // matched the first alternative in rules.js (skip the * in __abc*abc__)
881
+
882
+ rLength = rDelim.length;
883
+
884
+ if (match[3] || match[4]) { // found another Left Delim
885
+ delimTotal += rLength;
886
+ continue;
887
+ } else if (match[5] || match[6]) { // either Left or Right Delim
888
+ if (lLength % 3 && !((lLength + rLength) % 3)) {
889
+ midDelimTotal += rLength;
890
+ continue; // CommonMark Emphasis Rules 9-10
891
+ }
876
892
  }
877
- }
878
- }
879
- }
880
893
 
881
- em(src, maskedSrc, prevChar = '') {
882
- let match = this.rules.inline.em.start.exec(src);
894
+ delimTotal -= rLength;
883
895
 
884
- if (match && (!match[1] || (match[1] && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar))))) {
885
- maskedSrc = maskedSrc.slice(-1 * src.length);
886
- const endReg = match[0] === '*' ? this.rules.inline.em.endAst : this.rules.inline.em.endUnd;
896
+ if (delimTotal > 0) continue; // Haven't found enough closing delimiters
887
897
 
888
- endReg.lastIndex = 0;
898
+ // If this is the last rDelimiter, remove extra characters. *a*** -> *a*
899
+ if (delimTotal + midDelimTotal - rLength <= 0 && !maskedSrc.slice(endReg.lastIndex).match(endReg)) {
900
+ rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal);
901
+ }
889
902
 
890
- let cap;
891
- while ((match = endReg.exec(maskedSrc)) != null) {
892
- cap = this.rules.inline.em.middle.exec(maskedSrc.slice(0, match.index + 2));
893
- if (cap) {
903
+ if (Math.min(lLength, rLength) % 2) {
894
904
  return {
895
905
  type: 'em',
896
- raw: src.slice(0, cap[0].length),
897
- text: src.slice(1, cap[0].length - 1)
906
+ raw: src.slice(0, lLength + match.index + rLength + 1),
907
+ text: src.slice(1, lLength + match.index + rLength)
908
+ };
909
+ }
910
+ if (Math.min(lLength, rLength) % 2 === 0) {
911
+ return {
912
+ type: 'strong',
913
+ raw: src.slice(0, lLength + match.index + rLength + 1),
914
+ text: src.slice(2, lLength + match.index + rLength - 1)
898
915
  };
899
916
  }
900
917
  }
@@ -1033,8 +1050,8 @@ const {
1033
1050
  * Block-Level Grammar
1034
1051
  */
1035
1052
  const block = {
1036
- newline: /^\n+/,
1037
- code: /^( {4}[^\n]+\n*)+/,
1053
+ newline: /^(?: *(?:\n|$))+/,
1054
+ code: /^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,
1038
1055
  fences: /^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/,
1039
1056
  hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,
1040
1057
  heading: /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,
@@ -1056,7 +1073,7 @@ const block = {
1056
1073
  lheading: /^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,
1057
1074
  // regex template, placeholders will be replaced according to different paragraph
1058
1075
  // interruption rules of commonmark and the original markdown spec:
1059
- _paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html)[^\n]+)*)/,
1076
+ _paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html| +\n)[^\n]+)*)/,
1060
1077
  text: /^[^\n]+/
1061
1078
  };
1062
1079
 
@@ -1073,7 +1090,7 @@ block.item = edit$1(block.item, 'gm')
1073
1090
  .replace(/bull/g, block.bullet)
1074
1091
  .getRegex();
1075
1092
 
1076
- block.listItemStart = edit$1(/^( *)(bull)/)
1093
+ block.listItemStart = edit$1(/^( *)(bull) */)
1077
1094
  .replace('bull', block.bullet)
1078
1095
  .getRegex();
1079
1096
 
@@ -1198,74 +1215,41 @@ const inline = {
1198
1215
  reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,
1199
1216
  nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,
1200
1217
  reflinkSearch: 'reflink|nolink(?!\\()',
1201
- strong: {
1202
- start: /^(?:(\*\*(?=[*punctuation]))|\*\*)(?![\s])|__/, // (1) returns if starts w/ punctuation
1203
- middle: /^\*\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*\*$|^__(?![\s])((?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?)__$/,
1204
- endAst: /[^punctuation\s]\*\*(?!\*)|[punctuation]\*\*(?!\*)(?:(?=[punctuation_\s]|$))/, // last char can't be punct, or final * must also be followed by punct (or endline)
1205
- endUnd: /[^\s]__(?!_)(?:(?=[punctuation*\s])|$)/ // last char can't be a space, and final _ must preceed punct or \s (or endline)
1206
- },
1207
- em: {
1208
- start: /^(?:(\*(?=[punctuation]))|\*)(?![*\s])|_/, // (1) returns if starts w/ punctuation
1209
- middle: /^\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*$|^_(?![_\s])(?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?_$/,
1210
- endAst: /[^punctuation\s]\*(?!\*)|[punctuation]\*(?!\*)(?:(?=[punctuation_\s]|$))/, // last char can't be punct, or final * must also be followed by punct (or endline)
1211
- endUnd: /[^\s]_(?!_)(?:(?=[punctuation*\s])|$)/ // last char can't be a space, and final _ must preceed punct or \s (or endline)
1218
+ emStrong: {
1219
+ lDelim: /^(?:\*+(?:([punct_])|[^\s*]))|^_+(?:([punct*])|([^\s_]))/,
1220
+ // (1) and (2) can only be a Right Delimiter. (3) and (4) can only be Left. (5) and (6) can be either Left or Right.
1221
+ // () Skip other delimiter (1) #*** (2) a***#, a*** (3) #***a, ***a (4) ***# (5) #***# (6) a***a
1222
+ rDelimAst: /\_\_[^_]*?\*[^_]*?\_\_|[punct_](\*+)(?=[\s]|$)|[^punct*_\s](\*+)(?=[punct_\s]|$)|[punct_\s](\*+)(?=[^punct*_\s])|[\s](\*+)(?=[punct_])|[punct_](\*+)(?=[punct_])|[^punct*_\s](\*+)(?=[^punct*_\s])/,
1223
+ rDelimUnd: /\*\*[^*]*?\_[^*]*?\*\*|[punct*](\_+)(?=[\s]|$)|[^punct*_\s](\_+)(?=[punct*\s]|$)|[punct*\s](\_+)(?=[^punct*_\s])|[\s](\_+)(?=[punct*])|[punct*](\_+)(?=[punct*])/ // ^- Not allowed for _
1212
1224
  },
1213
1225
  code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,
1214
1226
  br: /^( {2,}|\\)\n(?!\s*$)/,
1215
1227
  del: noopTest$1,
1216
- text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*]|\b_|$)|[^ ](?= {2,}\n)))/,
1217
- punctuation: /^([\s*punctuation])/
1228
+ text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,
1229
+ punctuation: /^([\spunctuation])/
1218
1230
  };
1219
1231
 
1220
- // list of punctuation marks from common mark spec
1221
- // without * and _ to workaround cases with double emphasis
1232
+ // list of punctuation marks from CommonMark spec
1233
+ // without * and _ to handle the different emphasis markers * and _
1222
1234
  inline._punctuation = '!"#$%&\'()+\\-.,/:;<=>?@\\[\\]`^{|}~';
1223
1235
  inline.punctuation = edit$1(inline.punctuation).replace(/punctuation/g, inline._punctuation).getRegex();
1224
1236
 
1225
1237
  // sequences em should skip over [title](link), `code`, <html>
1226
- inline._blockSkip = '\\[[^\\]]*?\\]\\([^\\)]*?\\)|`[^`]*?`|<[^>]*?>';
1227
- inline._overlapSkip = '__[^_]*?__|\\*\\*\\[^\\*\\]*?\\*\\*';
1238
+ inline.blockSkip = /\[[^\]]*?\]\([^\)]*?\)|`[^`]*?`|<[^>]*?>/g;
1239
+ inline.escapedEmSt = /\\\*|\\_/g;
1228
1240
 
1229
1241
  inline._comment = edit$1(block._comment).replace('(?:-->|$)', '-->').getRegex();
1230
1242
 
1231
- inline.em.start = edit$1(inline.em.start)
1232
- .replace(/punctuation/g, inline._punctuation)
1233
- .getRegex();
1234
-
1235
- inline.em.middle = edit$1(inline.em.middle)
1236
- .replace(/punctuation/g, inline._punctuation)
1237
- .replace(/overlapSkip/g, inline._overlapSkip)
1238
- .getRegex();
1239
-
1240
- inline.em.endAst = edit$1(inline.em.endAst, 'g')
1241
- .replace(/punctuation/g, inline._punctuation)
1243
+ inline.emStrong.lDelim = edit$1(inline.emStrong.lDelim)
1244
+ .replace(/punct/g, inline._punctuation)
1242
1245
  .getRegex();
1243
1246
 
1244
- inline.em.endUnd = edit$1(inline.em.endUnd, 'g')
1245
- .replace(/punctuation/g, inline._punctuation)
1247
+ inline.emStrong.rDelimAst = edit$1(inline.emStrong.rDelimAst, 'g')
1248
+ .replace(/punct/g, inline._punctuation)
1246
1249
  .getRegex();
1247
1250
 
1248
- inline.strong.start = edit$1(inline.strong.start)
1249
- .replace(/punctuation/g, inline._punctuation)
1250
- .getRegex();
1251
-
1252
- inline.strong.middle = edit$1(inline.strong.middle)
1253
- .replace(/punctuation/g, inline._punctuation)
1254
- .replace(/overlapSkip/g, inline._overlapSkip)
1255
- .getRegex();
1256
-
1257
- inline.strong.endAst = edit$1(inline.strong.endAst, 'g')
1258
- .replace(/punctuation/g, inline._punctuation)
1259
- .getRegex();
1260
-
1261
- inline.strong.endUnd = edit$1(inline.strong.endUnd, 'g')
1262
- .replace(/punctuation/g, inline._punctuation)
1263
- .getRegex();
1264
-
1265
- inline.blockSkip = edit$1(inline._blockSkip, 'g')
1266
- .getRegex();
1267
-
1268
- inline.overlapSkip = edit$1(inline._overlapSkip, 'g')
1251
+ inline.emStrong.rDelimUnd = edit$1(inline.emStrong.rDelimUnd, 'g')
1252
+ .replace(/punct/g, inline._punctuation)
1269
1253
  .getRegex();
1270
1254
 
1271
1255
  inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;
@@ -1344,7 +1328,7 @@ inline.gfm = merge$1({}, inline.normal, {
1344
1328
  url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,
1345
1329
  _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,
1346
1330
  del: /^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/,
1347
- text: /^([`~]+|[^`~])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*~]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@))|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@))/
1331
+ text: /^([`~]+|[^`~])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@))|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@))/
1348
1332
  });
1349
1333
 
1350
1334
  inline.gfm.url = edit$1(inline.gfm.url, 'i')
@@ -1488,7 +1472,9 @@ var Lexer_1 = class Lexer {
1488
1472
  * Lexing
1489
1473
  */
1490
1474
  blockTokens(src, tokens = [], top = true) {
1491
- src = src.replace(/^ +$/gm, '');
1475
+ if (this.options.pedantic) {
1476
+ src = src.replace(/^ +$/gm, '');
1477
+ }
1492
1478
  let token, i, l, lastToken;
1493
1479
 
1494
1480
  while (src) {
@@ -1502,14 +1488,15 @@ var Lexer_1 = class Lexer {
1502
1488
  }
1503
1489
 
1504
1490
  // code
1505
- if (token = this.tokenizer.code(src, tokens)) {
1491
+ if (token = this.tokenizer.code(src)) {
1506
1492
  src = src.substring(token.raw.length);
1507
- if (token.type) {
1508
- tokens.push(token);
1509
- } else {
1510
- lastToken = tokens[tokens.length - 1];
1493
+ lastToken = tokens[tokens.length - 1];
1494
+ // An indented code block cannot interrupt a paragraph.
1495
+ if (lastToken && lastToken.type === 'paragraph') {
1511
1496
  lastToken.raw += '\n' + token.raw;
1512
1497
  lastToken.text += '\n' + token.text;
1498
+ } else {
1499
+ tokens.push(token);
1513
1500
  }
1514
1501
  continue;
1515
1502
  }
@@ -1602,14 +1589,14 @@ var Lexer_1 = class Lexer {
1602
1589
  }
1603
1590
 
1604
1591
  // text
1605
- if (token = this.tokenizer.text(src, tokens)) {
1592
+ if (token = this.tokenizer.text(src)) {
1606
1593
  src = src.substring(token.raw.length);
1607
- if (token.type) {
1608
- tokens.push(token);
1609
- } else {
1610
- lastToken = tokens[tokens.length - 1];
1594
+ lastToken = tokens[tokens.length - 1];
1595
+ if (lastToken && lastToken.type === 'text') {
1611
1596
  lastToken.raw += '\n' + token.raw;
1612
1597
  lastToken.text += '\n' + token.text;
1598
+ } else {
1599
+ tokens.push(token);
1613
1600
  }
1614
1601
  continue;
1615
1602
  }
@@ -1694,7 +1681,7 @@ var Lexer_1 = class Lexer {
1694
1681
  * Lexing/Compiling
1695
1682
  */
1696
1683
  inlineTokens(src, tokens = [], inLink = false, inRawBlock = false) {
1697
- let token;
1684
+ let token, lastToken;
1698
1685
 
1699
1686
  // String with links masked to avoid interference with em and strong
1700
1687
  let maskedSrc = src;
@@ -1717,11 +1704,17 @@ var Lexer_1 = class Lexer {
1717
1704
  maskedSrc = maskedSrc.slice(0, match.index) + '[' + repeatString$1('a', match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
1718
1705
  }
1719
1706
 
1707
+ // Mask out escaped em & strong delimiters
1708
+ while ((match = this.tokenizer.rules.inline.escapedEmSt.exec(maskedSrc)) != null) {
1709
+ maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.escapedEmSt.lastIndex);
1710
+ }
1711
+
1720
1712
  while (src) {
1721
1713
  if (!keepPrevChar) {
1722
1714
  prevChar = '';
1723
1715
  }
1724
1716
  keepPrevChar = false;
1717
+
1725
1718
  // escape
1726
1719
  if (token = this.tokenizer.escape(src)) {
1727
1720
  src = src.substring(token.raw.length);
@@ -1734,7 +1727,13 @@ var Lexer_1 = class Lexer {
1734
1727
  src = src.substring(token.raw.length);
1735
1728
  inLink = token.inLink;
1736
1729
  inRawBlock = token.inRawBlock;
1737
- tokens.push(token);
1730
+ const lastToken = tokens[tokens.length - 1];
1731
+ if (lastToken && token.type === 'text' && lastToken.type === 'text') {
1732
+ lastToken.raw += token.raw;
1733
+ lastToken.text += token.text;
1734
+ } else {
1735
+ tokens.push(token);
1736
+ }
1738
1737
  continue;
1739
1738
  }
1740
1739
 
@@ -1751,23 +1750,21 @@ var Lexer_1 = class Lexer {
1751
1750
  // reflink, nolink
1752
1751
  if (token = this.tokenizer.reflink(src, this.tokens.links)) {
1753
1752
  src = src.substring(token.raw.length);
1753
+ const lastToken = tokens[tokens.length - 1];
1754
1754
  if (token.type === 'link') {
1755
1755
  token.tokens = this.inlineTokens(token.text, [], true, inRawBlock);
1756
+ tokens.push(token);
1757
+ } else if (lastToken && token.type === 'text' && lastToken.type === 'text') {
1758
+ lastToken.raw += token.raw;
1759
+ lastToken.text += token.text;
1760
+ } else {
1761
+ tokens.push(token);
1756
1762
  }
1757
- tokens.push(token);
1758
- continue;
1759
- }
1760
-
1761
- // strong
1762
- if (token = this.tokenizer.strong(src, maskedSrc, prevChar)) {
1763
- src = src.substring(token.raw.length);
1764
- token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock);
1765
- tokens.push(token);
1766
1763
  continue;
1767
1764
  }
1768
1765
 
1769
- // em
1770
- if (token = this.tokenizer.em(src, maskedSrc, prevChar)) {
1766
+ // em & strong
1767
+ if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) {
1771
1768
  src = src.substring(token.raw.length);
1772
1769
  token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock);
1773
1770
  tokens.push(token);
@@ -1813,9 +1810,17 @@ var Lexer_1 = class Lexer {
1813
1810
  // text
1814
1811
  if (token = this.tokenizer.inlineText(src, inRawBlock, smartypants)) {
1815
1812
  src = src.substring(token.raw.length);
1816
- prevChar = token.raw.slice(-1);
1813
+ if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started
1814
+ prevChar = token.raw.slice(-1);
1815
+ }
1817
1816
  keepPrevChar = true;
1818
- tokens.push(token);
1817
+ lastToken = tokens[tokens.length - 1];
1818
+ if (lastToken && lastToken.type === 'text') {
1819
+ lastToken.raw += token.raw;
1820
+ lastToken.text += token.text;
1821
+ } else {
1822
+ tokens.push(token);
1823
+ }
1819
1824
  continue;
1820
1825
  }
1821
1826
 
@@ -1858,6 +1863,8 @@ var Renderer_1 = class Renderer {
1858
1863
  }
1859
1864
  }
1860
1865
 
1866
+ code = code.replace(/\n$/, '') + '\n';
1867
+
1861
1868
  if (!lang) {
1862
1869
  return '<pre><code>'
1863
1870
  + (escaped ? code : escape$2(code, true))