marked 2.0.7 → 2.1.3

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
@@ -15,6 +15,7 @@ function getDefaults$1() {
15
15
  return {
16
16
  baseUrl: null,
17
17
  breaks: false,
18
+ extensions: null,
18
19
  gfm: true,
19
20
  headerIds: true,
20
21
  headerPrefix: '',
@@ -1056,14 +1057,14 @@ const block$1 = {
1056
1057
  blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,
1057
1058
  list: /^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?! {0,3}bull )\n*|\s*$)/,
1058
1059
  html: '^ {0,3}(?:' // optional indentation
1059
- + '<(script|pre|style)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)' // (1)
1060
+ + '<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)' // (1)
1060
1061
  + '|comment[^\\n]*(\\n+|$)' // (2)
1061
1062
  + '|<\\?[\\s\\S]*?(?:\\?>\\n*|$)' // (3)
1062
1063
  + '|<![A-Z][\\s\\S]*?(?:>\\n*|$)' // (4)
1063
1064
  + '|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)' // (5)
1064
1065
  + '|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (6)
1065
- + '|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (7) open tag
1066
- + '|</(?!script|pre|style)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (7) closing tag
1066
+ + '|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (7) open tag
1067
+ + '|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (7) closing tag
1067
1068
  + ')',
1068
1069
  def: /^ {0,3}\[(label)\]: *\n? *<?([^\s>]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,
1069
1070
  nptable: noopTest,
@@ -1118,7 +1119,7 @@ block$1.paragraph = edit(block$1._paragraph)
1118
1119
  .replace('blockquote', ' {0,3}>')
1119
1120
  .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n')
1120
1121
  .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
1121
- .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)')
1122
+ .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)')
1122
1123
  .replace('tag', block$1._tag) // pars can be interrupted by type (6) html blocks
1123
1124
  .getRegex();
1124
1125
 
@@ -1152,7 +1153,7 @@ block$1.gfm.nptable = edit(block$1.gfm.nptable)
1152
1153
  .replace('code', ' {4}[^\\n]')
1153
1154
  .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n')
1154
1155
  .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
1155
- .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)')
1156
+ .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)')
1156
1157
  .replace('tag', block$1._tag) // tables can be interrupted by type (6) html blocks
1157
1158
  .getRegex();
1158
1159
 
@@ -1163,7 +1164,7 @@ block$1.gfm.table = edit(block$1.gfm.table)
1163
1164
  .replace('code', ' {4}[^\\n]')
1164
1165
  .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n')
1165
1166
  .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
1166
- .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)')
1167
+ .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)')
1167
1168
  .replace('tag', block$1._tag) // tables can be interrupted by type (6) html blocks
1168
1169
  .getRegex();
1169
1170
 
@@ -1474,9 +1475,22 @@ var Lexer_1 = class Lexer {
1474
1475
  if (this.options.pedantic) {
1475
1476
  src = src.replace(/^ +$/gm, '');
1476
1477
  }
1477
- let token, i, l, lastToken;
1478
+ let token, i, l, lastToken, cutSrc, lastParagraphClipped;
1478
1479
 
1479
1480
  while (src) {
1481
+ if (this.options.extensions
1482
+ && this.options.extensions.block
1483
+ && this.options.extensions.block.some((extTokenizer) => {
1484
+ if (token = extTokenizer.call(this, src, tokens)) {
1485
+ src = src.substring(token.raw.length);
1486
+ tokens.push(token);
1487
+ return true;
1488
+ }
1489
+ return false;
1490
+ })) {
1491
+ continue;
1492
+ }
1493
+
1480
1494
  // newline
1481
1495
  if (token = this.tokenizer.space(src)) {
1482
1496
  src = src.substring(token.raw.length);
@@ -1581,9 +1595,30 @@ var Lexer_1 = class Lexer {
1581
1595
  }
1582
1596
 
1583
1597
  // top-level paragraph
1584
- if (top && (token = this.tokenizer.paragraph(src))) {
1598
+ // prevent paragraph consuming extensions by clipping 'src' to extension start
1599
+ cutSrc = src;
1600
+ if (this.options.extensions && this.options.extensions.startBlock) {
1601
+ let startIndex = Infinity;
1602
+ const tempSrc = src.slice(1);
1603
+ let tempStart;
1604
+ this.options.extensions.startBlock.forEach(function(getStartIndex) {
1605
+ tempStart = getStartIndex.call(this, tempSrc);
1606
+ if (typeof tempStart === 'number' && tempStart >= 0) { startIndex = Math.min(startIndex, tempStart); }
1607
+ });
1608
+ if (startIndex < Infinity && startIndex >= 0) {
1609
+ cutSrc = src.substring(0, startIndex + 1);
1610
+ }
1611
+ }
1612
+ if (top && (token = this.tokenizer.paragraph(cutSrc))) {
1613
+ lastToken = tokens[tokens.length - 1];
1614
+ if (lastParagraphClipped && lastToken.type === 'paragraph') {
1615
+ lastToken.raw += '\n' + token.raw;
1616
+ lastToken.text += '\n' + token.text;
1617
+ } else {
1618
+ tokens.push(token);
1619
+ }
1620
+ lastParagraphClipped = (cutSrc.length !== src.length);
1585
1621
  src = src.substring(token.raw.length);
1586
- tokens.push(token);
1587
1622
  continue;
1588
1623
  }
1589
1624
 
@@ -1680,7 +1715,7 @@ var Lexer_1 = class Lexer {
1680
1715
  * Lexing/Compiling
1681
1716
  */
1682
1717
  inlineTokens(src, tokens = [], inLink = false, inRawBlock = false) {
1683
- let token, lastToken;
1718
+ let token, lastToken, cutSrc;
1684
1719
 
1685
1720
  // String with links masked to avoid interference with em and strong
1686
1721
  let maskedSrc = src;
@@ -1714,6 +1749,20 @@ var Lexer_1 = class Lexer {
1714
1749
  }
1715
1750
  keepPrevChar = false;
1716
1751
 
1752
+ // extensions
1753
+ if (this.options.extensions
1754
+ && this.options.extensions.inline
1755
+ && this.options.extensions.inline.some((extTokenizer) => {
1756
+ if (token = extTokenizer.call(this, src, tokens)) {
1757
+ src = src.substring(token.raw.length);
1758
+ tokens.push(token);
1759
+ return true;
1760
+ }
1761
+ return false;
1762
+ })) {
1763
+ continue;
1764
+ }
1765
+
1717
1766
  // escape
1718
1767
  if (token = this.tokenizer.escape(src)) {
1719
1768
  src = src.substring(token.raw.length);
@@ -1726,7 +1775,7 @@ var Lexer_1 = class Lexer {
1726
1775
  src = src.substring(token.raw.length);
1727
1776
  inLink = token.inLink;
1728
1777
  inRawBlock = token.inRawBlock;
1729
- const lastToken = tokens[tokens.length - 1];
1778
+ lastToken = tokens[tokens.length - 1];
1730
1779
  if (lastToken && token.type === 'text' && lastToken.type === 'text') {
1731
1780
  lastToken.raw += token.raw;
1732
1781
  lastToken.text += token.text;
@@ -1749,7 +1798,7 @@ var Lexer_1 = class Lexer {
1749
1798
  // reflink, nolink
1750
1799
  if (token = this.tokenizer.reflink(src, this.tokens.links)) {
1751
1800
  src = src.substring(token.raw.length);
1752
- const lastToken = tokens[tokens.length - 1];
1801
+ lastToken = tokens[tokens.length - 1];
1753
1802
  if (token.type === 'link') {
1754
1803
  token.tokens = this.inlineTokens(token.text, [], true, inRawBlock);
1755
1804
  tokens.push(token);
@@ -1807,7 +1856,21 @@ var Lexer_1 = class Lexer {
1807
1856
  }
1808
1857
 
1809
1858
  // text
1810
- if (token = this.tokenizer.inlineText(src, inRawBlock, smartypants)) {
1859
+ // prevent inlineText consuming extensions by clipping 'src' to extension start
1860
+ cutSrc = src;
1861
+ if (this.options.extensions && this.options.extensions.startInline) {
1862
+ let startIndex = Infinity;
1863
+ const tempSrc = src.slice(1);
1864
+ let tempStart;
1865
+ this.options.extensions.startInline.forEach(function(getStartIndex) {
1866
+ tempStart = getStartIndex.call(this, tempSrc);
1867
+ if (typeof tempStart === 'number' && tempStart >= 0) { startIndex = Math.min(startIndex, tempStart); }
1868
+ });
1869
+ if (startIndex < Infinity && startIndex >= 0) {
1870
+ cutSrc = src.substring(0, startIndex + 1);
1871
+ }
1872
+ }
1873
+ if (token = this.tokenizer.inlineText(cutSrc, inRawBlock, smartypants)) {
1811
1874
  src = src.substring(token.raw.length);
1812
1875
  if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started
1813
1876
  prevChar = token.raw.slice(-1);
@@ -2159,11 +2222,22 @@ var Parser_1 = class Parser {
2159
2222
  item,
2160
2223
  checked,
2161
2224
  task,
2162
- checkbox;
2225
+ checkbox,
2226
+ ret;
2163
2227
 
2164
2228
  const l = tokens.length;
2165
2229
  for (i = 0; i < l; i++) {
2166
2230
  token = tokens[i];
2231
+
2232
+ // Run any renderer extensions
2233
+ if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {
2234
+ ret = this.options.extensions.renderers[token.type].call(this, token);
2235
+ if (ret !== false || !['space', 'hr', 'heading', 'code', 'table', 'blockquote', 'list', 'html', 'paragraph', 'text'].includes(token.type)) {
2236
+ out += ret || '';
2237
+ continue;
2238
+ }
2239
+ }
2240
+
2167
2241
  switch (token.type) {
2168
2242
  case 'space': {
2169
2243
  continue;
@@ -2281,6 +2355,7 @@ var Parser_1 = class Parser {
2281
2355
  out += top ? this.renderer.paragraph(body) : body;
2282
2356
  continue;
2283
2357
  }
2358
+
2284
2359
  default: {
2285
2360
  const errMsg = 'Token with "' + token.type + '" type was not found.';
2286
2361
  if (this.options.silent) {
@@ -2303,11 +2378,22 @@ var Parser_1 = class Parser {
2303
2378
  renderer = renderer || this.renderer;
2304
2379
  let out = '',
2305
2380
  i,
2306
- token;
2381
+ token,
2382
+ ret;
2307
2383
 
2308
2384
  const l = tokens.length;
2309
2385
  for (i = 0; i < l; i++) {
2310
2386
  token = tokens[i];
2387
+
2388
+ // Run any renderer extensions
2389
+ if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {
2390
+ ret = this.options.extensions.renderers[token.type].call(this, token);
2391
+ if (ret !== false || !['escape', 'html', 'link', 'image', 'strong', 'em', 'codespan', 'br', 'del', 'text'].includes(token.type)) {
2392
+ out += ret || '';
2393
+ continue;
2394
+ }
2395
+ }
2396
+
2311
2397
  switch (token.type) {
2312
2398
  case 'escape': {
2313
2399
  out += renderer.text(token.text);
@@ -2507,46 +2593,114 @@ marked.defaults = defaults;
2507
2593
  * Use Extension
2508
2594
  */
2509
2595
 
2510
- marked.use = function(extension) {
2511
- const opts = merge({}, extension);
2512
- if (extension.renderer) {
2513
- const renderer = marked.defaults.renderer || new Renderer();
2514
- for (const prop in extension.renderer) {
2515
- const prevRenderer = renderer[prop];
2516
- renderer[prop] = (...args) => {
2517
- let ret = extension.renderer[prop].apply(renderer, args);
2518
- if (ret === false) {
2519
- ret = prevRenderer.apply(renderer, args);
2520
- }
2521
- return ret;
2522
- };
2596
+ marked.use = function(...args) {
2597
+ const opts = merge({}, ...args);
2598
+ const extensions = marked.defaults.extensions || { renderers: {}, childTokens: {} };
2599
+ let hasExtensions;
2600
+
2601
+ args.forEach((pack) => {
2602
+ // ==-- Parse "addon" extensions --== //
2603
+ if (pack.extensions) {
2604
+ hasExtensions = true;
2605
+ pack.extensions.forEach((ext) => {
2606
+ if (!ext.name) {
2607
+ throw new Error('extension name required');
2608
+ }
2609
+ if (ext.renderer) { // Renderer extensions
2610
+ const prevRenderer = extensions.renderers ? extensions.renderers[ext.name] : null;
2611
+ if (prevRenderer) {
2612
+ // Replace extension with func to run new extension but fall back if false
2613
+ extensions.renderers[ext.name] = function(...args) {
2614
+ let ret = ext.renderer.apply(this, args);
2615
+ if (ret === false) {
2616
+ ret = prevRenderer.apply(this, args);
2617
+ }
2618
+ return ret;
2619
+ };
2620
+ } else {
2621
+ extensions.renderers[ext.name] = ext.renderer;
2622
+ }
2623
+ }
2624
+ if (ext.tokenizer) { // Tokenizer Extensions
2625
+ if (!ext.level || (ext.level !== 'block' && ext.level !== 'inline')) {
2626
+ throw new Error("extension level must be 'block' or 'inline'");
2627
+ }
2628
+ if (extensions[ext.level]) {
2629
+ extensions[ext.level].unshift(ext.tokenizer);
2630
+ } else {
2631
+ extensions[ext.level] = [ext.tokenizer];
2632
+ }
2633
+ if (ext.start) { // Function to check for start of token
2634
+ if (ext.level === 'block') {
2635
+ if (extensions.startBlock) {
2636
+ extensions.startBlock.push(ext.start);
2637
+ } else {
2638
+ extensions.startBlock = [ext.start];
2639
+ }
2640
+ } else if (ext.level === 'inline') {
2641
+ if (extensions.startInline) {
2642
+ extensions.startInline.push(ext.start);
2643
+ } else {
2644
+ extensions.startInline = [ext.start];
2645
+ }
2646
+ }
2647
+ }
2648
+ }
2649
+ if (ext.childTokens) { // Child tokens to be visited by walkTokens
2650
+ extensions.childTokens[ext.name] = ext.childTokens;
2651
+ }
2652
+ });
2523
2653
  }
2524
- opts.renderer = renderer;
2525
- }
2526
- if (extension.tokenizer) {
2527
- const tokenizer = marked.defaults.tokenizer || new Tokenizer();
2528
- for (const prop in extension.tokenizer) {
2529
- const prevTokenizer = tokenizer[prop];
2530
- tokenizer[prop] = (...args) => {
2531
- let ret = extension.tokenizer[prop].apply(tokenizer, args);
2532
- if (ret === false) {
2533
- ret = prevTokenizer.apply(tokenizer, args);
2654
+
2655
+ // ==-- Parse "overwrite" extensions --== //
2656
+ if (pack.renderer) {
2657
+ const renderer = marked.defaults.renderer || new Renderer();
2658
+ for (const prop in pack.renderer) {
2659
+ const prevRenderer = renderer[prop];
2660
+ // Replace renderer with func to run extension, but fall back if false
2661
+ renderer[prop] = (...args) => {
2662
+ let ret = pack.renderer[prop].apply(renderer, args);
2663
+ if (ret === false) {
2664
+ ret = prevRenderer.apply(renderer, args);
2665
+ }
2666
+ return ret;
2667
+ };
2668
+ }
2669
+ opts.renderer = renderer;
2670
+ }
2671
+ if (pack.tokenizer) {
2672
+ const tokenizer = marked.defaults.tokenizer || new Tokenizer();
2673
+ for (const prop in pack.tokenizer) {
2674
+ const prevTokenizer = tokenizer[prop];
2675
+ // Replace tokenizer with func to run extension, but fall back if false
2676
+ tokenizer[prop] = (...args) => {
2677
+ let ret = pack.tokenizer[prop].apply(tokenizer, args);
2678
+ if (ret === false) {
2679
+ ret = prevTokenizer.apply(tokenizer, args);
2680
+ }
2681
+ return ret;
2682
+ };
2683
+ }
2684
+ opts.tokenizer = tokenizer;
2685
+ }
2686
+
2687
+ // ==-- Parse WalkTokens extensions --== //
2688
+ if (pack.walkTokens) {
2689
+ const walkTokens = marked.defaults.walkTokens;
2690
+ opts.walkTokens = (token) => {
2691
+ pack.walkTokens.call(this, token);
2692
+ if (walkTokens) {
2693
+ walkTokens(token);
2534
2694
  }
2535
- return ret;
2536
2695
  };
2537
2696
  }
2538
- opts.tokenizer = tokenizer;
2539
- }
2540
- if (extension.walkTokens) {
2541
- const walkTokens = marked.defaults.walkTokens;
2542
- opts.walkTokens = (token) => {
2543
- extension.walkTokens(token);
2544
- if (walkTokens) {
2545
- walkTokens(token);
2546
- }
2547
- };
2548
- }
2549
- marked.setOptions(opts);
2697
+
2698
+ if (hasExtensions) {
2699
+ opts.extensions = extensions;
2700
+ }
2701
+
2702
+ marked.setOptions(opts);
2703
+ });
2550
2704
  };
2551
2705
 
2552
2706
  /**
@@ -2573,7 +2727,11 @@ marked.walkTokens = function(tokens, callback) {
2573
2727
  break;
2574
2728
  }
2575
2729
  default: {
2576
- if (token.tokens) {
2730
+ if (marked.defaults.extensions && marked.defaults.extensions.childTokens && marked.defaults.extensions.childTokens[token.type]) { // Walk any extensions
2731
+ marked.defaults.extensions.childTokens[token.type].forEach(function(childTokens) {
2732
+ marked.walkTokens(token[childTokens], callback);
2733
+ });
2734
+ } else if (token.tokens) {
2577
2735
  marked.walkTokens(token.tokens, callback);
2578
2736
  }
2579
2737
  }