marked 1.2.6 → 2.0.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
@@ -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],
@@ -438,11 +427,11 @@ var Tokenizer_1 = class Tokenizer {
438
427
  let text = cap[2].trim();
439
428
 
440
429
  // remove trailing #s
441
- if (text.endsWith('#')) {
430
+ if (/#$/.test(text)) {
442
431
  const trimmed = rtrim$1(text, '#');
443
432
  if (this.options.pedantic) {
444
433
  text = trimmed.trim();
445
- } else if (!trimmed || trimmed.endsWith(' ')) {
434
+ } else if (!trimmed || / $/.test(trimmed)) {
446
435
  // CommonMark requires space before trailing #s
447
436
  text = trimmed.trim();
448
437
  }
@@ -555,8 +544,11 @@ var Tokenizer_1 = class Tokenizer {
555
544
  // Backpedal if it does not belong in this list.
556
545
  if (i !== l - 1) {
557
546
  bnext = this.rules.block.listItemStart.exec(itemMatch[i + 1]);
558
-
559
- if (bnext[1].length > bcurr[0].length || bnext[1].length > 3) {
547
+ if (
548
+ !this.options.pedantic
549
+ ? bnext[1].length > bcurr[0].length || bnext[1].length > 3
550
+ : bnext[1].length > bcurr[1].length
551
+ ) {
560
552
  // nested list
561
553
  itemMatch.splice(i, 2, itemMatch[i] + '\n' + itemMatch[i + 1]);
562
554
  i--;
@@ -721,17 +713,9 @@ var Tokenizer_1 = class Tokenizer {
721
713
  }
722
714
  }
723
715
 
724
- text(src, tokens) {
716
+ text(src) {
725
717
  const cap = this.rules.block.text.exec(src);
726
718
  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
719
  return {
736
720
  type: 'text',
737
721
  raw: cap[0],
@@ -785,9 +769,9 @@ var Tokenizer_1 = class Tokenizer {
785
769
  const cap = this.rules.inline.link.exec(src);
786
770
  if (cap) {
787
771
  const trimmedUrl = cap[2].trim();
788
- if (!this.options.pedantic && trimmedUrl.startsWith('<')) {
772
+ if (!this.options.pedantic && /^</.test(trimmedUrl)) {
789
773
  // commonmark requires matching angle brackets
790
- if (!trimmedUrl.endsWith('>')) {
774
+ if (!(/>$/.test(trimmedUrl))) {
791
775
  return;
792
776
  }
793
777
 
@@ -822,8 +806,8 @@ var Tokenizer_1 = class Tokenizer {
822
806
  }
823
807
 
824
808
  href = href.trim();
825
- if (href.startsWith('<')) {
826
- if (this.options.pedantic && !trimmedUrl.endsWith('>')) {
809
+ if (/^</.test(href)) {
810
+ if (this.options.pedantic && !(/>$/.test(trimmedUrl))) {
827
811
  // pedantic allows starting angle bracket without ending angle bracket
828
812
  href = href.slice(1);
829
813
  } else {
@@ -855,46 +839,61 @@ var Tokenizer_1 = class Tokenizer {
855
839
  }
856
840
  }
857
841
 
858
- strong(src, maskedSrc, prevChar = '') {
859
- let match = this.rules.inline.strong.start.exec(src);
842
+ emStrong(src, maskedSrc, prevChar = '') {
843
+ let match = this.rules.inline.emStrong.lDelim.exec(src);
844
+ if (!match) return;
845
+
846
+ 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
847
+
848
+ const nextChar = match[1] || match[2] || '';
860
849
 
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;
850
+ if (!nextChar || (nextChar && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar)))) {
851
+ const lLength = match[0].length - 1;
852
+ let rDelim, rLength, delimTotal = lLength, midDelimTotal = 0;
864
853
 
854
+ const endReg = match[0][0] === '*' ? this.rules.inline.emStrong.rDelimAst : this.rules.inline.emStrong.rDelimUnd;
865
855
  endReg.lastIndex = 0;
866
856
 
867
- let cap;
857
+ maskedSrc = maskedSrc.slice(-1 * src.length + lLength); // Bump maskedSrc to same section of string as src (move to lexer?)
858
+
868
859
  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
- };
860
+ rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6];
861
+
862
+ if (!rDelim) continue; // matched the first alternative in rules.js (skip the * in __abc*abc__)
863
+
864
+ rLength = rDelim.length;
865
+
866
+ if (match[3] || match[4]) { // found another Left Delim
867
+ delimTotal += rLength;
868
+ continue;
869
+ } else if (match[5] || match[6]) { // either Left or Right Delim
870
+ if (lLength % 3 && !((lLength + rLength) % 3)) {
871
+ midDelimTotal += rLength;
872
+ continue; // CommonMark Emphasis Rules 9-10
873
+ }
876
874
  }
877
- }
878
- }
879
- }
880
875
 
881
- em(src, maskedSrc, prevChar = '') {
882
- let match = this.rules.inline.em.start.exec(src);
876
+ delimTotal -= rLength;
883
877
 
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;
878
+ if (delimTotal > 0) continue; // Haven't found enough closing delimiters
887
879
 
888
- endReg.lastIndex = 0;
880
+ // If this is the last rDelimiter, remove extra characters. *a*** -> *a*
881
+ if (delimTotal + midDelimTotal - rLength <= 0 && !maskedSrc.slice(endReg.lastIndex).match(endReg)) {
882
+ rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal);
883
+ }
889
884
 
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) {
885
+ if (Math.min(lLength, rLength) % 2) {
894
886
  return {
895
887
  type: 'em',
896
- raw: src.slice(0, cap[0].length),
897
- text: src.slice(1, cap[0].length - 1)
888
+ raw: src.slice(0, lLength + match.index + rLength + 1),
889
+ text: src.slice(1, lLength + match.index + rLength)
890
+ };
891
+ }
892
+ if (Math.min(lLength, rLength) % 2 === 0) {
893
+ return {
894
+ type: 'strong',
895
+ raw: src.slice(0, lLength + match.index + rLength + 1),
896
+ text: src.slice(2, lLength + match.index + rLength - 1)
898
897
  };
899
898
  }
900
899
  }
@@ -906,7 +905,7 @@ var Tokenizer_1 = class Tokenizer {
906
905
  if (cap) {
907
906
  let text = cap[2].replace(/\n/g, ' ');
908
907
  const hasNonSpaceChars = /[^ ]/.test(text);
909
- const hasSpaceCharsOnBothEnds = text.startsWith(' ') && text.endsWith(' ');
908
+ const hasSpaceCharsOnBothEnds = /^ /.test(text) && / $/.test(text);
910
909
  if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {
911
910
  text = text.substring(1, text.length - 1);
912
911
  }
@@ -1033,8 +1032,8 @@ const {
1033
1032
  * Block-Level Grammar
1034
1033
  */
1035
1034
  const block = {
1036
- newline: /^\n+/,
1037
- code: /^( {4}[^\n]+\n*)+/,
1035
+ newline: /^(?: *(?:\n|$))+/,
1036
+ code: /^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,
1038
1037
  fences: /^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/,
1039
1038
  hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,
1040
1039
  heading: /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,
@@ -1056,7 +1055,7 @@ const block = {
1056
1055
  lheading: /^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,
1057
1056
  // regex template, placeholders will be replaced according to different paragraph
1058
1057
  // interruption rules of commonmark and the original markdown spec:
1059
- _paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html)[^\n]+)*)/,
1058
+ _paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html| +\n)[^\n]+)*)/,
1060
1059
  text: /^[^\n]+/
1061
1060
  };
1062
1061
 
@@ -1198,74 +1197,41 @@ const inline = {
1198
1197
  reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,
1199
1198
  nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,
1200
1199
  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)
1200
+ emStrong: {
1201
+ lDelim: /^(?:\*+(?:([punct_])|[^\s*]))|^_+(?:([punct*])|([^\s_]))/,
1202
+ // (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.
1203
+ // () Skip other delimiter (1) #*** (2) a***#, a*** (3) #***a, ***a (4) ***# (5) #***# (6) a***a
1204
+ rDelimAst: /\_\_[^_]*?\*[^_]*?\_\_|[punct_](\*+)(?=[\s]|$)|[^punct*_\s](\*+)(?=[punct_\s]|$)|[punct_\s](\*+)(?=[^punct*_\s])|[\s](\*+)(?=[punct_])|[punct_](\*+)(?=[punct_])|[^punct*_\s](\*+)(?=[^punct*_\s])/,
1205
+ rDelimUnd: /\*\*[^*]*?\_[^*]*?\*\*|[punct*](\_+)(?=[\s]|$)|[^punct*_\s](\_+)(?=[punct*\s]|$)|[punct*\s](\_+)(?=[^punct*_\s])|[\s](\_+)(?=[punct*])|[punct*](\_+)(?=[punct*])/ // ^- Not allowed for _
1212
1206
  },
1213
1207
  code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,
1214
1208
  br: /^( {2,}|\\)\n(?!\s*$)/,
1215
1209
  del: noopTest$1,
1216
- text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*]|\b_|$)|[^ ](?= {2,}\n)))/,
1217
- punctuation: /^([\s*punctuation])/
1210
+ text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,
1211
+ punctuation: /^([\spunctuation])/
1218
1212
  };
1219
1213
 
1220
- // list of punctuation marks from common mark spec
1221
- // without * and _ to workaround cases with double emphasis
1214
+ // list of punctuation marks from CommonMark spec
1215
+ // without * and _ to handle the different emphasis markers * and _
1222
1216
  inline._punctuation = '!"#$%&\'()+\\-.,/:;<=>?@\\[\\]`^{|}~';
1223
1217
  inline.punctuation = edit$1(inline.punctuation).replace(/punctuation/g, inline._punctuation).getRegex();
1224
1218
 
1225
1219
  // sequences em should skip over [title](link), `code`, <html>
1226
- inline._blockSkip = '\\[[^\\]]*?\\]\\([^\\)]*?\\)|`[^`]*?`|<[^>]*?>';
1227
- inline._overlapSkip = '__[^_]*?__|\\*\\*\\[^\\*\\]*?\\*\\*';
1220
+ inline.blockSkip = /\[[^\]]*?\]\([^\)]*?\)|`[^`]*?`|<[^>]*?>/g;
1221
+ inline.escapedEmSt = /\\\*|\\_/g;
1228
1222
 
1229
1223
  inline._comment = edit$1(block._comment).replace('(?:-->|$)', '-->').getRegex();
1230
1224
 
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)
1242
- .getRegex();
1243
-
1244
- inline.em.endUnd = edit$1(inline.em.endUnd, 'g')
1245
- .replace(/punctuation/g, inline._punctuation)
1246
- .getRegex();
1247
-
1248
- inline.strong.start = edit$1(inline.strong.start)
1249
- .replace(/punctuation/g, inline._punctuation)
1225
+ inline.emStrong.lDelim = edit$1(inline.emStrong.lDelim)
1226
+ .replace(/punct/g, inline._punctuation)
1250
1227
  .getRegex();
1251
1228
 
1252
- inline.strong.middle = edit$1(inline.strong.middle)
1253
- .replace(/punctuation/g, inline._punctuation)
1254
- .replace(/overlapSkip/g, inline._overlapSkip)
1229
+ inline.emStrong.rDelimAst = edit$1(inline.emStrong.rDelimAst, 'g')
1230
+ .replace(/punct/g, inline._punctuation)
1255
1231
  .getRegex();
1256
1232
 
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')
1233
+ inline.emStrong.rDelimUnd = edit$1(inline.emStrong.rDelimUnd, 'g')
1234
+ .replace(/punct/g, inline._punctuation)
1269
1235
  .getRegex();
1270
1236
 
1271
1237
  inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;
@@ -1344,7 +1310,7 @@ inline.gfm = merge$1({}, inline.normal, {
1344
1310
  url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,
1345
1311
  _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,
1346
1312
  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.!#$%&'*+\/=?_`{\|}~-]+@))/
1313
+ text: /^([`~]+|[^`~])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@))|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@))/
1348
1314
  });
1349
1315
 
1350
1316
  inline.gfm.url = edit$1(inline.gfm.url, 'i')
@@ -1488,7 +1454,9 @@ var Lexer_1 = class Lexer {
1488
1454
  * Lexing
1489
1455
  */
1490
1456
  blockTokens(src, tokens = [], top = true) {
1491
- src = src.replace(/^ +$/gm, '');
1457
+ if (this.options.pedantic) {
1458
+ src = src.replace(/^ +$/gm, '');
1459
+ }
1492
1460
  let token, i, l, lastToken;
1493
1461
 
1494
1462
  while (src) {
@@ -1502,14 +1470,15 @@ var Lexer_1 = class Lexer {
1502
1470
  }
1503
1471
 
1504
1472
  // code
1505
- if (token = this.tokenizer.code(src, tokens)) {
1473
+ if (token = this.tokenizer.code(src)) {
1506
1474
  src = src.substring(token.raw.length);
1507
- if (token.type) {
1508
- tokens.push(token);
1509
- } else {
1510
- lastToken = tokens[tokens.length - 1];
1475
+ lastToken = tokens[tokens.length - 1];
1476
+ // An indented code block cannot interrupt a paragraph.
1477
+ if (lastToken && lastToken.type === 'paragraph') {
1511
1478
  lastToken.raw += '\n' + token.raw;
1512
1479
  lastToken.text += '\n' + token.text;
1480
+ } else {
1481
+ tokens.push(token);
1513
1482
  }
1514
1483
  continue;
1515
1484
  }
@@ -1602,14 +1571,14 @@ var Lexer_1 = class Lexer {
1602
1571
  }
1603
1572
 
1604
1573
  // text
1605
- if (token = this.tokenizer.text(src, tokens)) {
1574
+ if (token = this.tokenizer.text(src)) {
1606
1575
  src = src.substring(token.raw.length);
1607
- if (token.type) {
1608
- tokens.push(token);
1609
- } else {
1610
- lastToken = tokens[tokens.length - 1];
1576
+ lastToken = tokens[tokens.length - 1];
1577
+ if (lastToken && lastToken.type === 'text') {
1611
1578
  lastToken.raw += '\n' + token.raw;
1612
1579
  lastToken.text += '\n' + token.text;
1580
+ } else {
1581
+ tokens.push(token);
1613
1582
  }
1614
1583
  continue;
1615
1584
  }
@@ -1694,7 +1663,7 @@ var Lexer_1 = class Lexer {
1694
1663
  * Lexing/Compiling
1695
1664
  */
1696
1665
  inlineTokens(src, tokens = [], inLink = false, inRawBlock = false) {
1697
- let token;
1666
+ let token, lastToken;
1698
1667
 
1699
1668
  // String with links masked to avoid interference with em and strong
1700
1669
  let maskedSrc = src;
@@ -1717,11 +1686,17 @@ var Lexer_1 = class Lexer {
1717
1686
  maskedSrc = maskedSrc.slice(0, match.index) + '[' + repeatString$1('a', match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
1718
1687
  }
1719
1688
 
1689
+ // Mask out escaped em & strong delimiters
1690
+ while ((match = this.tokenizer.rules.inline.escapedEmSt.exec(maskedSrc)) != null) {
1691
+ maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.escapedEmSt.lastIndex);
1692
+ }
1693
+
1720
1694
  while (src) {
1721
1695
  if (!keepPrevChar) {
1722
1696
  prevChar = '';
1723
1697
  }
1724
1698
  keepPrevChar = false;
1699
+
1725
1700
  // escape
1726
1701
  if (token = this.tokenizer.escape(src)) {
1727
1702
  src = src.substring(token.raw.length);
@@ -1734,7 +1709,13 @@ var Lexer_1 = class Lexer {
1734
1709
  src = src.substring(token.raw.length);
1735
1710
  inLink = token.inLink;
1736
1711
  inRawBlock = token.inRawBlock;
1737
- tokens.push(token);
1712
+ const lastToken = tokens[tokens.length - 1];
1713
+ if (lastToken && token.type === 'text' && lastToken.type === 'text') {
1714
+ lastToken.raw += token.raw;
1715
+ lastToken.text += token.text;
1716
+ } else {
1717
+ tokens.push(token);
1718
+ }
1738
1719
  continue;
1739
1720
  }
1740
1721
 
@@ -1751,23 +1732,21 @@ var Lexer_1 = class Lexer {
1751
1732
  // reflink, nolink
1752
1733
  if (token = this.tokenizer.reflink(src, this.tokens.links)) {
1753
1734
  src = src.substring(token.raw.length);
1735
+ const lastToken = tokens[tokens.length - 1];
1754
1736
  if (token.type === 'link') {
1755
1737
  token.tokens = this.inlineTokens(token.text, [], true, inRawBlock);
1738
+ tokens.push(token);
1739
+ } else if (lastToken && token.type === 'text' && lastToken.type === 'text') {
1740
+ lastToken.raw += token.raw;
1741
+ lastToken.text += token.text;
1742
+ } else {
1743
+ tokens.push(token);
1756
1744
  }
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
1745
  continue;
1767
1746
  }
1768
1747
 
1769
- // em
1770
- if (token = this.tokenizer.em(src, maskedSrc, prevChar)) {
1748
+ // em & strong
1749
+ if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) {
1771
1750
  src = src.substring(token.raw.length);
1772
1751
  token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock);
1773
1752
  tokens.push(token);
@@ -1813,9 +1792,17 @@ var Lexer_1 = class Lexer {
1813
1792
  // text
1814
1793
  if (token = this.tokenizer.inlineText(src, inRawBlock, smartypants)) {
1815
1794
  src = src.substring(token.raw.length);
1816
- prevChar = token.raw.slice(-1);
1795
+ if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started
1796
+ prevChar = token.raw.slice(-1);
1797
+ }
1817
1798
  keepPrevChar = true;
1818
- tokens.push(token);
1799
+ lastToken = tokens[tokens.length - 1];
1800
+ if (lastToken && lastToken.type === 'text') {
1801
+ lastToken.raw += token.raw;
1802
+ lastToken.text += token.text;
1803
+ } else {
1804
+ tokens.push(token);
1805
+ }
1819
1806
  continue;
1820
1807
  }
1821
1808
 
@@ -1858,6 +1845,8 @@ var Renderer_1 = class Renderer {
1858
1845
  }
1859
1846
  }
1860
1847
 
1848
+ code = code.replace(/\n$/, '') + '\n';
1849
+
1861
1850
  if (!lang) {
1862
1851
  return '<pre><code>'
1863
1852
  + (escaped ? code : escape$2(code, true))