marked 1.2.9 → 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
@@ -391,18 +391,9 @@ var Tokenizer_1 = class Tokenizer {
391
391
  }
392
392
  }
393
393
 
394
- code(src, tokens) {
394
+ code(src) {
395
395
  const cap = this.rules.block.code.exec(src);
396
396
  if (cap) {
397
- const lastToken = tokens[tokens.length - 1];
398
- // An indented code block cannot interrupt a paragraph.
399
- if (lastToken && lastToken.type === 'paragraph') {
400
- return {
401
- raw: cap[0],
402
- text: cap[0].trimRight()
403
- };
404
- }
405
-
406
397
  const text = cap[0].replace(/^ {1,4}/gm, '');
407
398
  return {
408
399
  type: 'code',
@@ -722,17 +713,9 @@ var Tokenizer_1 = class Tokenizer {
722
713
  }
723
714
  }
724
715
 
725
- text(src, tokens) {
716
+ text(src) {
726
717
  const cap = this.rules.block.text.exec(src);
727
718
  if (cap) {
728
- const lastToken = tokens[tokens.length - 1];
729
- if (lastToken && lastToken.type === 'text') {
730
- return {
731
- raw: cap[0],
732
- text: cap[0]
733
- };
734
- }
735
-
736
719
  return {
737
720
  type: 'text',
738
721
  raw: cap[0],
@@ -856,46 +839,61 @@ var Tokenizer_1 = class Tokenizer {
856
839
  }
857
840
  }
858
841
 
859
- strong(src, maskedSrc, prevChar = '') {
860
- 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] || '';
861
849
 
862
- if (match && (!match[1] || (match[1] && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar))))) {
863
- maskedSrc = maskedSrc.slice(-1 * src.length);
864
- 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;
865
853
 
854
+ const endReg = match[0][0] === '*' ? this.rules.inline.emStrong.rDelimAst : this.rules.inline.emStrong.rDelimUnd;
866
855
  endReg.lastIndex = 0;
867
856
 
868
- let cap;
857
+ maskedSrc = maskedSrc.slice(-1 * src.length + lLength); // Bump maskedSrc to same section of string as src (move to lexer?)
858
+
869
859
  while ((match = endReg.exec(maskedSrc)) != null) {
870
- cap = this.rules.inline.strong.middle.exec(maskedSrc.slice(0, match.index + 3));
871
- if (cap) {
872
- return {
873
- type: 'strong',
874
- raw: src.slice(0, cap[0].length),
875
- text: src.slice(2, cap[0].length - 2)
876
- };
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
+ }
877
874
  }
878
- }
879
- }
880
- }
881
875
 
882
- em(src, maskedSrc, prevChar = '') {
883
- let match = this.rules.inline.em.start.exec(src);
876
+ delimTotal -= rLength;
884
877
 
885
- if (match && (!match[1] || (match[1] && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar))))) {
886
- maskedSrc = maskedSrc.slice(-1 * src.length);
887
- 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
888
879
 
889
- 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
+ }
890
884
 
891
- let cap;
892
- while ((match = endReg.exec(maskedSrc)) != null) {
893
- cap = this.rules.inline.em.middle.exec(maskedSrc.slice(0, match.index + 2));
894
- if (cap) {
885
+ if (Math.min(lLength, rLength) % 2) {
895
886
  return {
896
887
  type: 'em',
897
- raw: src.slice(0, cap[0].length),
898
- 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)
899
897
  };
900
898
  }
901
899
  }
@@ -1199,74 +1197,41 @@ const inline = {
1199
1197
  reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,
1200
1198
  nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,
1201
1199
  reflinkSearch: 'reflink|nolink(?!\\()',
1202
- strong: {
1203
- start: /^(?:(\*\*(?=[*punctuation]))|\*\*)(?![\s])|__/, // (1) returns if starts w/ punctuation
1204
- middle: /^\*\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*\*$|^__(?![\s])((?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?)__$/,
1205
- endAst: /[^punctuation\s]\*\*(?!\*)|[punctuation]\*\*(?!\*)(?:(?=[punctuation_\s]|$))/, // last char can't be punct, or final * must also be followed by punct (or endline)
1206
- endUnd: /[^\s]__(?!_)(?:(?=[punctuation*\s])|$)/ // last char can't be a space, and final _ must preceed punct or \s (or endline)
1207
- },
1208
- em: {
1209
- start: /^(?:(\*(?=[punctuation]))|\*)(?![*\s])|_/, // (1) returns if starts w/ punctuation
1210
- middle: /^\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*$|^_(?![_\s])(?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?_$/,
1211
- endAst: /[^punctuation\s]\*(?!\*)|[punctuation]\*(?!\*)(?:(?=[punctuation_\s]|$))/, // last char can't be punct, or final * must also be followed by punct (or endline)
1212
- 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 _
1213
1206
  },
1214
1207
  code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,
1215
1208
  br: /^( {2,}|\\)\n(?!\s*$)/,
1216
1209
  del: noopTest$1,
1217
- text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*]|\b_|$)|[^ ](?= {2,}\n)))/,
1218
- punctuation: /^([\s*punctuation])/
1210
+ text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,
1211
+ punctuation: /^([\spunctuation])/
1219
1212
  };
1220
1213
 
1221
- // list of punctuation marks from common mark spec
1222
- // 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 _
1223
1216
  inline._punctuation = '!"#$%&\'()+\\-.,/:;<=>?@\\[\\]`^{|}~';
1224
1217
  inline.punctuation = edit$1(inline.punctuation).replace(/punctuation/g, inline._punctuation).getRegex();
1225
1218
 
1226
1219
  // sequences em should skip over [title](link), `code`, <html>
1227
- inline._blockSkip = '\\[[^\\]]*?\\]\\([^\\)]*?\\)|`[^`]*?`|<[^>]*?>';
1228
- inline._overlapSkip = '__[^_]*?__|\\*\\*\\[^\\*\\]*?\\*\\*';
1220
+ inline.blockSkip = /\[[^\]]*?\]\([^\)]*?\)|`[^`]*?`|<[^>]*?>/g;
1221
+ inline.escapedEmSt = /\\\*|\\_/g;
1229
1222
 
1230
1223
  inline._comment = edit$1(block._comment).replace('(?:-->|$)', '-->').getRegex();
1231
1224
 
1232
- inline.em.start = edit$1(inline.em.start)
1233
- .replace(/punctuation/g, inline._punctuation)
1234
- .getRegex();
1235
-
1236
- inline.em.middle = edit$1(inline.em.middle)
1237
- .replace(/punctuation/g, inline._punctuation)
1238
- .replace(/overlapSkip/g, inline._overlapSkip)
1239
- .getRegex();
1240
-
1241
- inline.em.endAst = edit$1(inline.em.endAst, 'g')
1242
- .replace(/punctuation/g, inline._punctuation)
1243
- .getRegex();
1244
-
1245
- inline.em.endUnd = edit$1(inline.em.endUnd, 'g')
1246
- .replace(/punctuation/g, inline._punctuation)
1247
- .getRegex();
1248
-
1249
- inline.strong.start = edit$1(inline.strong.start)
1250
- .replace(/punctuation/g, inline._punctuation)
1251
- .getRegex();
1252
-
1253
- inline.strong.middle = edit$1(inline.strong.middle)
1254
- .replace(/punctuation/g, inline._punctuation)
1255
- .replace(/overlapSkip/g, inline._overlapSkip)
1256
- .getRegex();
1257
-
1258
- inline.strong.endAst = edit$1(inline.strong.endAst, 'g')
1259
- .replace(/punctuation/g, inline._punctuation)
1225
+ inline.emStrong.lDelim = edit$1(inline.emStrong.lDelim)
1226
+ .replace(/punct/g, inline._punctuation)
1260
1227
  .getRegex();
1261
1228
 
1262
- inline.strong.endUnd = edit$1(inline.strong.endUnd, 'g')
1263
- .replace(/punctuation/g, inline._punctuation)
1229
+ inline.emStrong.rDelimAst = edit$1(inline.emStrong.rDelimAst, 'g')
1230
+ .replace(/punct/g, inline._punctuation)
1264
1231
  .getRegex();
1265
1232
 
1266
- inline.blockSkip = edit$1(inline._blockSkip, 'g')
1267
- .getRegex();
1268
-
1269
- inline.overlapSkip = edit$1(inline._overlapSkip, 'g')
1233
+ inline.emStrong.rDelimUnd = edit$1(inline.emStrong.rDelimUnd, 'g')
1234
+ .replace(/punct/g, inline._punctuation)
1270
1235
  .getRegex();
1271
1236
 
1272
1237
  inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;
@@ -1345,7 +1310,7 @@ inline.gfm = merge$1({}, inline.normal, {
1345
1310
  url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,
1346
1311
  _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,
1347
1312
  del: /^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/,
1348
- 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.!#$%&'*+\/=?_`{\|}~-]+@))/
1349
1314
  });
1350
1315
 
1351
1316
  inline.gfm.url = edit$1(inline.gfm.url, 'i')
@@ -1505,14 +1470,15 @@ var Lexer_1 = class Lexer {
1505
1470
  }
1506
1471
 
1507
1472
  // code
1508
- if (token = this.tokenizer.code(src, tokens)) {
1473
+ if (token = this.tokenizer.code(src)) {
1509
1474
  src = src.substring(token.raw.length);
1510
- if (token.type) {
1511
- tokens.push(token);
1512
- } else {
1513
- 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') {
1514
1478
  lastToken.raw += '\n' + token.raw;
1515
1479
  lastToken.text += '\n' + token.text;
1480
+ } else {
1481
+ tokens.push(token);
1516
1482
  }
1517
1483
  continue;
1518
1484
  }
@@ -1605,14 +1571,14 @@ var Lexer_1 = class Lexer {
1605
1571
  }
1606
1572
 
1607
1573
  // text
1608
- if (token = this.tokenizer.text(src, tokens)) {
1574
+ if (token = this.tokenizer.text(src)) {
1609
1575
  src = src.substring(token.raw.length);
1610
- if (token.type) {
1611
- tokens.push(token);
1612
- } else {
1613
- lastToken = tokens[tokens.length - 1];
1576
+ lastToken = tokens[tokens.length - 1];
1577
+ if (lastToken && lastToken.type === 'text') {
1614
1578
  lastToken.raw += '\n' + token.raw;
1615
1579
  lastToken.text += '\n' + token.text;
1580
+ } else {
1581
+ tokens.push(token);
1616
1582
  }
1617
1583
  continue;
1618
1584
  }
@@ -1697,7 +1663,7 @@ var Lexer_1 = class Lexer {
1697
1663
  * Lexing/Compiling
1698
1664
  */
1699
1665
  inlineTokens(src, tokens = [], inLink = false, inRawBlock = false) {
1700
- let token;
1666
+ let token, lastToken;
1701
1667
 
1702
1668
  // String with links masked to avoid interference with em and strong
1703
1669
  let maskedSrc = src;
@@ -1720,11 +1686,17 @@ var Lexer_1 = class Lexer {
1720
1686
  maskedSrc = maskedSrc.slice(0, match.index) + '[' + repeatString$1('a', match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
1721
1687
  }
1722
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
+
1723
1694
  while (src) {
1724
1695
  if (!keepPrevChar) {
1725
1696
  prevChar = '';
1726
1697
  }
1727
1698
  keepPrevChar = false;
1699
+
1728
1700
  // escape
1729
1701
  if (token = this.tokenizer.escape(src)) {
1730
1702
  src = src.substring(token.raw.length);
@@ -1737,7 +1709,13 @@ var Lexer_1 = class Lexer {
1737
1709
  src = src.substring(token.raw.length);
1738
1710
  inLink = token.inLink;
1739
1711
  inRawBlock = token.inRawBlock;
1740
- 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
+ }
1741
1719
  continue;
1742
1720
  }
1743
1721
 
@@ -1754,23 +1732,21 @@ var Lexer_1 = class Lexer {
1754
1732
  // reflink, nolink
1755
1733
  if (token = this.tokenizer.reflink(src, this.tokens.links)) {
1756
1734
  src = src.substring(token.raw.length);
1735
+ const lastToken = tokens[tokens.length - 1];
1757
1736
  if (token.type === 'link') {
1758
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);
1759
1744
  }
1760
- tokens.push(token);
1761
1745
  continue;
1762
1746
  }
1763
1747
 
1764
- // strong
1765
- if (token = this.tokenizer.strong(src, maskedSrc, prevChar)) {
1766
- src = src.substring(token.raw.length);
1767
- token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock);
1768
- tokens.push(token);
1769
- continue;
1770
- }
1771
-
1772
- // em
1773
- if (token = this.tokenizer.em(src, maskedSrc, prevChar)) {
1748
+ // em & strong
1749
+ if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) {
1774
1750
  src = src.substring(token.raw.length);
1775
1751
  token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock);
1776
1752
  tokens.push(token);
@@ -1816,9 +1792,17 @@ var Lexer_1 = class Lexer {
1816
1792
  // text
1817
1793
  if (token = this.tokenizer.inlineText(src, inRawBlock, smartypants)) {
1818
1794
  src = src.substring(token.raw.length);
1819
- prevChar = token.raw.slice(-1);
1795
+ if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started
1796
+ prevChar = token.raw.slice(-1);
1797
+ }
1820
1798
  keepPrevChar = true;
1821
- 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
+ }
1822
1806
  continue;
1823
1807
  }
1824
1808