marked 5.0.5 → 5.1.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,5 +1,5 @@
1
1
  /**
2
- * marked v5.0.5 - a markdown parser
2
+ * marked v5.1.0 - a markdown parser
3
3
  * Copyright (c) 2011-2023, Christopher Jeffrey. (MIT Licensed)
4
4
  * https://github.com/markedjs/marked
5
5
  */
@@ -919,7 +919,7 @@ class Tokenizer {
919
919
 
920
920
  const nextChar = match[1] || match[2] || '';
921
921
 
922
- if (!nextChar || (nextChar && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar)))) {
922
+ if (!nextChar || !prevChar || this.rules.inline.punctuation.exec(prevChar)) {
923
923
  const lLength = match[0].length - 1;
924
924
  let rDelim, rLength, delimTotal = lLength, midDelimTotal = 0;
925
925
 
@@ -1270,48 +1270,49 @@ const inline = {
1270
1270
  nolink: /^!?\[(ref)\](?:\[\])?/,
1271
1271
  reflinkSearch: 'reflink|nolink(?!\\()',
1272
1272
  emStrong: {
1273
- lDelim: /^(?:\*+(?:([punct_])|[^\s*]))|^_+(?:([punct*])|([^\s_]))/,
1274
- // (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.
1275
- // () Skip orphan inside strong () Consume to delim (1) #*** (2) a***#, a*** (3) #***a, ***a (4) ***# (5) #***# (6) a***a
1276
- rDelimAst: /^[^_*]*?\_\_[^_*]*?\*[^_*]*?(?=\_\_)|[^*]+(?=[^*])|[punct_](\*+)(?=[\s]|$)|[^punct*_\s](\*+)(?=[punct_\s]|$)|[punct_\s](\*+)(?=[^punct*_\s])|[\s](\*+)(?=[punct_])|[punct_](\*+)(?=[punct_])|[^punct*_\s](\*+)(?=[^punct*_\s])/,
1277
- rDelimUnd: /^[^_*]*?\*\*[^_*]*?\_[^_*]*?(?=\*\*)|[^_]+(?=[^_])|[punct*](\_+)(?=[\s]|$)|[^punct*_\s](\_+)(?=[punct*\s]|$)|[punct*\s](\_+)(?=[^punct*_\s])|[\s](\_+)(?=[punct*])|[punct*](\_+)(?=[punct*])/ // ^- Not allowed for _
1273
+ lDelim: /^(?:\*+(?:((?!\*)[punct])|[^\s*]))|^_+(?:((?!_)[punct])|([^\s_]))/,
1274
+ // (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.
1275
+ // | Skip orphan inside strong | Consume to delim | (1) #*** | (2) a***#, a*** | (3) #***a, ***a | (4) ***# | (5) #***# | (6) a***a
1276
+ rDelimAst: /^[^_*]*?__[^_*]*?\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\*)[punct](\*+)(?=[\s]|$)|[^punct\s](\*+)(?!\*)(?=[punct\s]|$)|(?!\*)[punct\s](\*+)(?=[^punct\s])|[\s](\*+)(?!\*)(?=[punct])|(?!\*)[punct](\*+)(?!\*)(?=[punct])|[^punct\s](\*+)(?=[^punct\s])/,
1277
+ rDelimUnd: /^[^_*]*?\*\*[^_*]*?_[^_*]*?(?=\*\*)|[^_]+(?=[^_])|(?!_)[punct](_+)(?=[\s]|$)|[^punct\s](_+)(?!_)(?=[punct\s]|$)|(?!_)[punct\s](_+)(?=[^punct\s])|[\s](_+)(?!_)(?=[punct])|(?!_)[punct](_+)(?!_)(?=[punct])/ // ^- Not allowed for _
1278
1278
  },
1279
1279
  code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,
1280
1280
  br: /^( {2,}|\\)\n(?!\s*$)/,
1281
1281
  del: noopTest,
1282
1282
  text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,
1283
- punctuation: /^([\spunctuation])/
1283
+ punctuation: /^((?![*_])[\spunctuation])/
1284
1284
  };
1285
1285
 
1286
- // list of punctuation marks from CommonMark spec
1287
- // without * and _ to handle the different emphasis markers * and _
1288
- inline._uc_punctuation = '\\u00A1\\u00A7\\u00AB\\u00B6\\u00B7\\u00BB\\u00BF\\u037E\\u0387\\u055A-\\u055F\\u0589\\u058A\\u05BE\\u05C0\\u05C3\\u05C6\\u05F3\\u05F4\\u0609\\u060A\\u060C\\u060D\\u061B\\u061E\\u061F\\u066A-\\u066D\\u06D4\\u0700-\\u070D\\u07F7-\\u07F9\\u0830-\\u083E\\u085E\\u0964\\u0965\\u0970\\u0AF0\\u0DF4\\u0E4F\\u0E5A\\u0E5B\\u0F04-\\u0F12\\u0F14\\u0F3A-\\u0F3D\\u0F85\\u0FD0-\\u0FD4\\u0FD9\\u0FDA\\u104A-\\u104F\\u10FB\\u1360-\\u1368\\u1400\\u166D\\u166E\\u169B\\u169C\\u16EB-\\u16ED\\u1735\\u1736\\u17D4-\\u17D6\\u17D8-\\u17DA\\u1800-\\u180A\\u1944\\u1945\\u1A1E\\u1A1F\\u1AA0-\\u1AA6\\u1AA8-\\u1AAD\\u1B5A-\\u1B60\\u1BFC-\\u1BFF\\u1C3B-\\u1C3F\\u1C7E\\u1C7F\\u1CC0-\\u1CC7\\u1CD3\\u2010-\\u2027\\u2030-\\u2043\\u2045-\\u2051\\u2053-\\u205E\\u207D\\u207E\\u208D\\u208E\\u2308-\\u230B\\u2329\\u232A\\u2768-\\u2775\\u27C5\\u27C6\\u27E6-\\u27EF\\u2983-\\u2998\\u29D8-\\u29DB\\u29FC\\u29FD\\u2CF9-\\u2CFC\\u2CFE\\u2CFF\\u2D70\\u2E00-\\u2E2E\\u2E30-\\u2E42\\u3001-\\u3003\\u3008-\\u3011\\u3014-\\u301F\\u3030\\u303D\\u30A0\\u30FB\\uA4FE\\uA4FF\\uA60D-\\uA60F\\uA673\\uA67E\\uA6F2-\\uA6F7\\uA874-\\uA877\\uA8CE\\uA8CF\\uA8F8-\\uA8FA\\uA8FC\\uA92E\\uA92F\\uA95F\\uA9C1-\\uA9CD\\uA9DE\\uA9DF\\uAA5C-\\uAA5F\\uAADE\\uAADF\\uAAF0\\uAAF1\\uABEB\\uFD3E\\uFD3F\\uFE10-\\uFE19\\uFE30-\\uFE52\\uFE54-\\uFE61\\uFE63\\uFE68\\uFE6A\\uFE6B\\uFF01-\\uFF03\\uFF05-\\uFF0A\\uFF0C-\\uFF0F\\uFF1A\\uFF1B\\uFF1F\\uFF20\\uFF3B-\\uFF3D\\uFF3F\\uFF5B\\uFF5D\\uFF5F-\\uFF65';
1289
- inline._punctuation = '!"#$%&\'()+\\-.,/:;<=>?@\\[\\]`^{|}~\\\\' + inline._uc_punctuation;
1290
- inline.punctuation = edit(inline.punctuation).replace(/punctuation/g, inline._punctuation).getRegex();
1286
+ // list of unicode punctuation marks, plus any missing characters from CommonMark spec
1287
+ inline._punctuation = '\\p{P}$+<=>`^|~';
1288
+ inline.punctuation = edit(inline.punctuation, 'u').replace(/punctuation/g, inline._punctuation).getRegex();
1291
1289
 
1292
1290
  // sequences em should skip over [title](link), `code`, <html>
1293
1291
  inline.blockSkip = /\[[^[\]]*?\]\([^\(\)]*?\)|`[^`]*?`|<[^<>]*?>/g;
1294
- inline.escapedPunct = /\\[punct_*]/g;
1292
+ inline.anyPunctuation = /\\[punct]/g;
1293
+ inline._escapes = /\\([punct])/g;
1295
1294
 
1296
1295
  inline._comment = edit(block._comment).replace('(?:-->|$)', '-->').getRegex();
1297
1296
 
1298
- inline.emStrong.lDelim = edit(inline.emStrong.lDelim)
1297
+ inline.emStrong.lDelim = edit(inline.emStrong.lDelim, 'u')
1299
1298
  .replace(/punct/g, inline._punctuation)
1300
1299
  .getRegex();
1301
1300
 
1302
- inline.emStrong.rDelimAst = edit(inline.emStrong.rDelimAst, 'g')
1301
+ inline.emStrong.rDelimAst = edit(inline.emStrong.rDelimAst, 'gu')
1303
1302
  .replace(/punct/g, inline._punctuation)
1304
1303
  .getRegex();
1305
1304
 
1306
- inline.emStrong.rDelimUnd = edit(inline.emStrong.rDelimUnd, 'g')
1305
+ inline.emStrong.rDelimUnd = edit(inline.emStrong.rDelimUnd, 'gu')
1307
1306
  .replace(/punct/g, inline._punctuation)
1308
1307
  .getRegex();
1309
1308
 
1310
- inline.escapedPunct = edit(inline.escapedPunct, 'g')
1309
+ inline.anyPunctuation = edit(inline.anyPunctuation, 'gu')
1311
1310
  .replace(/punct/g, inline._punctuation)
1312
1311
  .getRegex();
1313
1312
 
1314
- inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;
1313
+ inline._escapes = edit(inline._escapes, 'gu')
1314
+ .replace(/punct/g, inline._punctuation)
1315
+ .getRegex();
1315
1316
 
1316
1317
  inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/;
1317
1318
  inline._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/;
@@ -1759,8 +1760,8 @@ class Lexer {
1759
1760
  }
1760
1761
 
1761
1762
  // Mask out escaped characters
1762
- while ((match = this.tokenizer.rules.inline.escapedPunct.exec(maskedSrc)) != null) {
1763
- maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.escapedPunct.lastIndex);
1763
+ while ((match = this.tokenizer.rules.inline.anyPunctuation.exec(maskedSrc)) != null) {
1764
+ maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);
1764
1765
  }
1765
1766
 
1766
1767
  while (src) {
@@ -2511,169 +2512,375 @@ class Hooks {
2511
2512
  }
2512
2513
  }
2513
2514
 
2514
- function onError(silent, async, callback) {
2515
- return (e) => {
2516
- e.message += '\nPlease report this to https://github.com/markedjs/marked.';
2515
+ class Marked {
2516
+ defaults = getDefaults();
2517
+ options = this.setOptions;
2517
2518
 
2518
- if (silent) {
2519
- const msg = '<p>An error occurred:</p><pre>'
2520
- + escape(e.message + '', true)
2521
- + '</pre>';
2522
- if (async) {
2523
- return Promise.resolve(msg);
2524
- }
2525
- if (callback) {
2526
- callback(null, msg);
2527
- return;
2528
- }
2529
- return msg;
2530
- }
2531
-
2532
- if (async) {
2533
- return Promise.reject(e);
2534
- }
2535
- if (callback) {
2536
- callback(e);
2537
- return;
2538
- }
2539
- throw e;
2540
- };
2541
- }
2519
+ parse = this.#parseMarkdown(Lexer.lex, Parser.parse);
2520
+ parseInline = this.#parseMarkdown(Lexer.lexInline, Parser.parseInline);
2542
2521
 
2543
- function parseMarkdown(lexer, parser) {
2544
- return (src, opt, callback) => {
2545
- if (typeof opt === 'function') {
2546
- callback = opt;
2547
- opt = null;
2548
- }
2522
+ Parser = Parser;
2523
+ parser = Parser.parse;
2524
+ Renderer = Renderer;
2525
+ TextRenderer = TextRenderer;
2526
+ Lexer = Lexer;
2527
+ lexer = Lexer.lex;
2528
+ Tokenizer = Tokenizer;
2529
+ Slugger = Slugger;
2530
+ Hooks = Hooks;
2549
2531
 
2550
- const origOpt = { ...opt };
2551
- opt = { ...marked.defaults, ...origOpt };
2552
- const throwError = onError(opt.silent, opt.async, callback);
2532
+ constructor(...args) {
2533
+ this.use(...args);
2534
+ }
2553
2535
 
2554
- // throw error in case of non string input
2555
- if (typeof src === 'undefined' || src === null) {
2556
- return throwError(new Error('marked(): input parameter is undefined or null'));
2557
- }
2558
- if (typeof src !== 'string') {
2559
- return throwError(new Error('marked(): input parameter is of type '
2560
- + Object.prototype.toString.call(src) + ', string expected'));
2536
+ walkTokens(tokens, callback) {
2537
+ let values = [];
2538
+ for (const token of tokens) {
2539
+ values = values.concat(callback.call(this, token));
2540
+ switch (token.type) {
2541
+ case 'table': {
2542
+ for (const cell of token.header) {
2543
+ values = values.concat(this.walkTokens(cell.tokens, callback));
2544
+ }
2545
+ for (const row of token.rows) {
2546
+ for (const cell of row) {
2547
+ values = values.concat(this.walkTokens(cell.tokens, callback));
2548
+ }
2549
+ }
2550
+ break;
2551
+ }
2552
+ case 'list': {
2553
+ values = values.concat(this.walkTokens(token.items, callback));
2554
+ break;
2555
+ }
2556
+ default: {
2557
+ if (this.defaults.extensions && this.defaults.extensions.childTokens && this.defaults.extensions.childTokens[token.type]) { // Walk any extensions
2558
+ this.defaults.extensions.childTokens[token.type].forEach((childTokens) => {
2559
+ values = values.concat(this.walkTokens(token[childTokens], callback));
2560
+ });
2561
+ } else if (token.tokens) {
2562
+ values = values.concat(this.walkTokens(token.tokens, callback));
2563
+ }
2564
+ }
2565
+ }
2561
2566
  }
2567
+ return values;
2568
+ }
2562
2569
 
2563
- checkDeprecations(opt, callback);
2570
+ use(...args) {
2571
+ const extensions = this.defaults.extensions || { renderers: {}, childTokens: {} };
2564
2572
 
2565
- if (opt.hooks) {
2566
- opt.hooks.options = opt;
2567
- }
2573
+ args.forEach((pack) => {
2574
+ // copy options to new object
2575
+ const opts = { ...pack };
2568
2576
 
2569
- if (callback) {
2570
- const highlight = opt.highlight;
2571
- let tokens;
2577
+ // set async to true if it was set to true before
2578
+ opts.async = this.defaults.async || opts.async || false;
2572
2579
 
2573
- try {
2574
- if (opt.hooks) {
2575
- src = opt.hooks.preprocess(src);
2576
- }
2577
- tokens = lexer(src, opt);
2578
- } catch (e) {
2579
- return throwError(e);
2580
+ // ==-- Parse "addon" extensions --== //
2581
+ if (pack.extensions) {
2582
+ pack.extensions.forEach((ext) => {
2583
+ if (!ext.name) {
2584
+ throw new Error('extension name required');
2585
+ }
2586
+ if (ext.renderer) { // Renderer extensions
2587
+ const prevRenderer = extensions.renderers[ext.name];
2588
+ if (prevRenderer) {
2589
+ // Replace extension with func to run new extension but fall back if false
2590
+ extensions.renderers[ext.name] = function(...args) {
2591
+ let ret = ext.renderer.apply(this, args);
2592
+ if (ret === false) {
2593
+ ret = prevRenderer.apply(this, args);
2594
+ }
2595
+ return ret;
2596
+ };
2597
+ } else {
2598
+ extensions.renderers[ext.name] = ext.renderer;
2599
+ }
2600
+ }
2601
+ if (ext.tokenizer) { // Tokenizer Extensions
2602
+ if (!ext.level || (ext.level !== 'block' && ext.level !== 'inline')) {
2603
+ throw new Error("extension level must be 'block' or 'inline'");
2604
+ }
2605
+ if (extensions[ext.level]) {
2606
+ extensions[ext.level].unshift(ext.tokenizer);
2607
+ } else {
2608
+ extensions[ext.level] = [ext.tokenizer];
2609
+ }
2610
+ if (ext.start) { // Function to check for start of token
2611
+ if (ext.level === 'block') {
2612
+ if (extensions.startBlock) {
2613
+ extensions.startBlock.push(ext.start);
2614
+ } else {
2615
+ extensions.startBlock = [ext.start];
2616
+ }
2617
+ } else if (ext.level === 'inline') {
2618
+ if (extensions.startInline) {
2619
+ extensions.startInline.push(ext.start);
2620
+ } else {
2621
+ extensions.startInline = [ext.start];
2622
+ }
2623
+ }
2624
+ }
2625
+ }
2626
+ if (ext.childTokens) { // Child tokens to be visited by walkTokens
2627
+ extensions.childTokens[ext.name] = ext.childTokens;
2628
+ }
2629
+ });
2630
+ opts.extensions = extensions;
2580
2631
  }
2581
2632
 
2582
- const done = function(err) {
2583
- let out;
2584
-
2585
- if (!err) {
2586
- try {
2587
- if (opt.walkTokens) {
2588
- marked.walkTokens(tokens, opt.walkTokens);
2633
+ // ==-- Parse "overwrite" extensions --== //
2634
+ if (pack.renderer) {
2635
+ const renderer = this.defaults.renderer || new Renderer(this.defaults);
2636
+ for (const prop in pack.renderer) {
2637
+ const prevRenderer = renderer[prop];
2638
+ // Replace renderer with func to run extension, but fall back if false
2639
+ renderer[prop] = (...args) => {
2640
+ let ret = pack.renderer[prop].apply(renderer, args);
2641
+ if (ret === false) {
2642
+ ret = prevRenderer.apply(renderer, args);
2589
2643
  }
2590
- out = parser(tokens, opt);
2591
- if (opt.hooks) {
2592
- out = opt.hooks.postprocess(out);
2644
+ return ret;
2645
+ };
2646
+ }
2647
+ opts.renderer = renderer;
2648
+ }
2649
+ if (pack.tokenizer) {
2650
+ const tokenizer = this.defaults.tokenizer || new Tokenizer(this.defaults);
2651
+ for (const prop in pack.tokenizer) {
2652
+ const prevTokenizer = tokenizer[prop];
2653
+ // Replace tokenizer with func to run extension, but fall back if false
2654
+ tokenizer[prop] = (...args) => {
2655
+ let ret = pack.tokenizer[prop].apply(tokenizer, args);
2656
+ if (ret === false) {
2657
+ ret = prevTokenizer.apply(tokenizer, args);
2593
2658
  }
2594
- } catch (e) {
2595
- err = e;
2659
+ return ret;
2660
+ };
2661
+ }
2662
+ opts.tokenizer = tokenizer;
2663
+ }
2664
+
2665
+ // ==-- Parse Hooks extensions --== //
2666
+ if (pack.hooks) {
2667
+ const hooks = this.defaults.hooks || new Hooks();
2668
+ for (const prop in pack.hooks) {
2669
+ const prevHook = hooks[prop];
2670
+ if (Hooks.passThroughHooks.has(prop)) {
2671
+ hooks[prop] = (arg) => {
2672
+ if (this.defaults.async) {
2673
+ return Promise.resolve(pack.hooks[prop].call(hooks, arg)).then(ret => {
2674
+ return prevHook.call(hooks, ret);
2675
+ });
2676
+ }
2677
+
2678
+ const ret = pack.hooks[prop].call(hooks, arg);
2679
+ return prevHook.call(hooks, ret);
2680
+ };
2681
+ } else {
2682
+ hooks[prop] = (...args) => {
2683
+ let ret = pack.hooks[prop].apply(hooks, args);
2684
+ if (ret === false) {
2685
+ ret = prevHook.apply(hooks, args);
2686
+ }
2687
+ return ret;
2688
+ };
2596
2689
  }
2597
2690
  }
2691
+ opts.hooks = hooks;
2692
+ }
2693
+
2694
+ // ==-- Parse WalkTokens extensions --== //
2695
+ if (pack.walkTokens) {
2696
+ const walkTokens = this.defaults.walkTokens;
2697
+ opts.walkTokens = function(token) {
2698
+ let values = [];
2699
+ values.push(pack.walkTokens.call(this, token));
2700
+ if (walkTokens) {
2701
+ values = values.concat(walkTokens.call(this, token));
2702
+ }
2703
+ return values;
2704
+ };
2705
+ }
2598
2706
 
2599
- opt.highlight = highlight;
2707
+ this.defaults = { ...this.defaults, ...opts };
2708
+ });
2600
2709
 
2601
- return err
2602
- ? throwError(err)
2603
- : callback(null, out);
2604
- };
2710
+ return this;
2711
+ }
2712
+
2713
+ setOptions(opt) {
2714
+ this.defaults = { ...this.defaults, ...opt };
2715
+ return this;
2716
+ }
2717
+
2718
+ #parseMarkdown(lexer, parser) {
2719
+ return (src, opt, callback) => {
2720
+ if (typeof opt === 'function') {
2721
+ callback = opt;
2722
+ opt = null;
2723
+ }
2724
+
2725
+ const origOpt = { ...opt };
2726
+ opt = { ...this.defaults, ...origOpt };
2727
+ const throwError = this.#onError(opt.silent, opt.async, callback);
2728
+
2729
+ // throw error in case of non string input
2730
+ if (typeof src === 'undefined' || src === null) {
2731
+ return throwError(new Error('marked(): input parameter is undefined or null'));
2732
+ }
2733
+ if (typeof src !== 'string') {
2734
+ return throwError(new Error('marked(): input parameter is of type '
2735
+ + Object.prototype.toString.call(src) + ', string expected'));
2736
+ }
2605
2737
 
2606
- if (!highlight || highlight.length < 3) {
2607
- return done();
2738
+ checkDeprecations(opt, callback);
2739
+
2740
+ if (opt.hooks) {
2741
+ opt.hooks.options = opt;
2608
2742
  }
2609
2743
 
2610
- delete opt.highlight;
2744
+ if (callback) {
2745
+ const highlight = opt.highlight;
2746
+ let tokens;
2611
2747
 
2612
- if (!tokens.length) return done();
2748
+ try {
2749
+ if (opt.hooks) {
2750
+ src = opt.hooks.preprocess(src);
2751
+ }
2752
+ tokens = lexer(src, opt);
2753
+ } catch (e) {
2754
+ return throwError(e);
2755
+ }
2756
+
2757
+ const done = (err) => {
2758
+ let out;
2613
2759
 
2614
- let pending = 0;
2615
- marked.walkTokens(tokens, function(token) {
2616
- if (token.type === 'code') {
2617
- pending++;
2618
- setTimeout(() => {
2619
- highlight(token.text, token.lang, function(err, code) {
2620
- if (err) {
2621
- return done(err);
2760
+ if (!err) {
2761
+ try {
2762
+ if (opt.walkTokens) {
2763
+ this.walkTokens(tokens, opt.walkTokens);
2622
2764
  }
2623
- if (code != null && code !== token.text) {
2624
- token.text = code;
2625
- token.escaped = true;
2765
+ out = parser(tokens, opt);
2766
+ if (opt.hooks) {
2767
+ out = opt.hooks.postprocess(out);
2626
2768
  }
2769
+ } catch (e) {
2770
+ err = e;
2771
+ }
2772
+ }
2627
2773
 
2628
- pending--;
2629
- if (pending === 0) {
2630
- done();
2631
- }
2632
- });
2633
- }, 0);
2774
+ opt.highlight = highlight;
2775
+
2776
+ return err
2777
+ ? throwError(err)
2778
+ : callback(null, out);
2779
+ };
2780
+
2781
+ if (!highlight || highlight.length < 3) {
2782
+ return done();
2783
+ }
2784
+
2785
+ delete opt.highlight;
2786
+
2787
+ if (!tokens.length) return done();
2788
+
2789
+ let pending = 0;
2790
+ this.walkTokens(tokens, (token) => {
2791
+ if (token.type === 'code') {
2792
+ pending++;
2793
+ setTimeout(() => {
2794
+ highlight(token.text, token.lang, (err, code) => {
2795
+ if (err) {
2796
+ return done(err);
2797
+ }
2798
+ if (code != null && code !== token.text) {
2799
+ token.text = code;
2800
+ token.escaped = true;
2801
+ }
2802
+
2803
+ pending--;
2804
+ if (pending === 0) {
2805
+ done();
2806
+ }
2807
+ });
2808
+ }, 0);
2809
+ }
2810
+ });
2811
+
2812
+ if (pending === 0) {
2813
+ done();
2634
2814
  }
2635
- });
2636
2815
 
2637
- if (pending === 0) {
2638
- done();
2816
+ return;
2639
2817
  }
2640
2818
 
2641
- return;
2642
- }
2819
+ if (opt.async) {
2820
+ return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src)
2821
+ .then(src => lexer(src, opt))
2822
+ .then(tokens => opt.walkTokens ? Promise.all(this.walkTokens(tokens, opt.walkTokens)).then(() => tokens) : tokens)
2823
+ .then(tokens => parser(tokens, opt))
2824
+ .then(html => opt.hooks ? opt.hooks.postprocess(html) : html)
2825
+ .catch(throwError);
2826
+ }
2643
2827
 
2644
- if (opt.async) {
2645
- return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src)
2646
- .then(src => lexer(src, opt))
2647
- .then(tokens => opt.walkTokens ? Promise.all(marked.walkTokens(tokens, opt.walkTokens)).then(() => tokens) : tokens)
2648
- .then(tokens => parser(tokens, opt))
2649
- .then(html => opt.hooks ? opt.hooks.postprocess(html) : html)
2650
- .catch(throwError);
2651
- }
2828
+ try {
2829
+ if (opt.hooks) {
2830
+ src = opt.hooks.preprocess(src);
2831
+ }
2832
+ const tokens = lexer(src, opt);
2833
+ if (opt.walkTokens) {
2834
+ this.walkTokens(tokens, opt.walkTokens);
2835
+ }
2836
+ let html = parser(tokens, opt);
2837
+ if (opt.hooks) {
2838
+ html = opt.hooks.postprocess(html);
2839
+ }
2840
+ return html;
2841
+ } catch (e) {
2842
+ return throwError(e);
2843
+ }
2844
+ };
2845
+ }
2652
2846
 
2653
- try {
2654
- if (opt.hooks) {
2655
- src = opt.hooks.preprocess(src);
2847
+ #onError(silent, async, callback) {
2848
+ return (e) => {
2849
+ e.message += '\nPlease report this to https://github.com/markedjs/this.';
2850
+
2851
+ if (silent) {
2852
+ const msg = '<p>An error occurred:</p><pre>'
2853
+ + escape(e.message + '', true)
2854
+ + '</pre>';
2855
+ if (async) {
2856
+ return Promise.resolve(msg);
2857
+ }
2858
+ if (callback) {
2859
+ callback(null, msg);
2860
+ return;
2861
+ }
2862
+ return msg;
2656
2863
  }
2657
- const tokens = lexer(src, opt);
2658
- if (opt.walkTokens) {
2659
- marked.walkTokens(tokens, opt.walkTokens);
2864
+
2865
+ if (async) {
2866
+ return Promise.reject(e);
2660
2867
  }
2661
- let html = parser(tokens, opt);
2662
- if (opt.hooks) {
2663
- html = opt.hooks.postprocess(html);
2868
+ if (callback) {
2869
+ callback(e);
2870
+ return;
2664
2871
  }
2665
- return html;
2666
- } catch (e) {
2667
- return throwError(e);
2668
- }
2669
- };
2872
+ throw e;
2873
+ };
2874
+ }
2670
2875
  }
2671
2876
 
2877
+ const markedInstance = new Marked(defaults);
2878
+
2672
2879
  /**
2673
2880
  * Marked
2674
2881
  */
2675
2882
  function marked(src, opt, callback) {
2676
- return parseMarkdown(Lexer.lex, Parser.parse)(src, opt, callback);
2883
+ return markedInstance.parse(src, opt, callback);
2677
2884
  }
2678
2885
 
2679
2886
  /**
@@ -2682,7 +2889,8 @@ function marked(src, opt, callback) {
2682
2889
 
2683
2890
  marked.options =
2684
2891
  marked.setOptions = function(opt) {
2685
- marked.defaults = { ...marked.defaults, ...opt };
2892
+ markedInstance.setOptions(opt);
2893
+ marked.defaults = markedInstance.defaults;
2686
2894
  changeDefaults(marked.defaults);
2687
2895
  return marked;
2688
2896
  };
@@ -2696,144 +2904,10 @@ marked.defaults = defaults;
2696
2904
  */
2697
2905
 
2698
2906
  marked.use = function(...args) {
2699
- const extensions = marked.defaults.extensions || { renderers: {}, childTokens: {} };
2700
-
2701
- args.forEach((pack) => {
2702
- // copy options to new object
2703
- const opts = { ...pack };
2704
-
2705
- // set async to true if it was set to true before
2706
- opts.async = marked.defaults.async || opts.async || false;
2707
-
2708
- // ==-- Parse "addon" extensions --== //
2709
- if (pack.extensions) {
2710
- pack.extensions.forEach((ext) => {
2711
- if (!ext.name) {
2712
- throw new Error('extension name required');
2713
- }
2714
- if (ext.renderer) { // Renderer extensions
2715
- const prevRenderer = extensions.renderers[ext.name];
2716
- if (prevRenderer) {
2717
- // Replace extension with func to run new extension but fall back if false
2718
- extensions.renderers[ext.name] = function(...args) {
2719
- let ret = ext.renderer.apply(this, args);
2720
- if (ret === false) {
2721
- ret = prevRenderer.apply(this, args);
2722
- }
2723
- return ret;
2724
- };
2725
- } else {
2726
- extensions.renderers[ext.name] = ext.renderer;
2727
- }
2728
- }
2729
- if (ext.tokenizer) { // Tokenizer Extensions
2730
- if (!ext.level || (ext.level !== 'block' && ext.level !== 'inline')) {
2731
- throw new Error("extension level must be 'block' or 'inline'");
2732
- }
2733
- if (extensions[ext.level]) {
2734
- extensions[ext.level].unshift(ext.tokenizer);
2735
- } else {
2736
- extensions[ext.level] = [ext.tokenizer];
2737
- }
2738
- if (ext.start) { // Function to check for start of token
2739
- if (ext.level === 'block') {
2740
- if (extensions.startBlock) {
2741
- extensions.startBlock.push(ext.start);
2742
- } else {
2743
- extensions.startBlock = [ext.start];
2744
- }
2745
- } else if (ext.level === 'inline') {
2746
- if (extensions.startInline) {
2747
- extensions.startInline.push(ext.start);
2748
- } else {
2749
- extensions.startInline = [ext.start];
2750
- }
2751
- }
2752
- }
2753
- }
2754
- if (ext.childTokens) { // Child tokens to be visited by walkTokens
2755
- extensions.childTokens[ext.name] = ext.childTokens;
2756
- }
2757
- });
2758
- opts.extensions = extensions;
2759
- }
2760
-
2761
- // ==-- Parse "overwrite" extensions --== //
2762
- if (pack.renderer) {
2763
- const renderer = marked.defaults.renderer || new Renderer();
2764
- for (const prop in pack.renderer) {
2765
- const prevRenderer = renderer[prop];
2766
- // Replace renderer with func to run extension, but fall back if false
2767
- renderer[prop] = (...args) => {
2768
- let ret = pack.renderer[prop].apply(renderer, args);
2769
- if (ret === false) {
2770
- ret = prevRenderer.apply(renderer, args);
2771
- }
2772
- return ret;
2773
- };
2774
- }
2775
- opts.renderer = renderer;
2776
- }
2777
- if (pack.tokenizer) {
2778
- const tokenizer = marked.defaults.tokenizer || new Tokenizer();
2779
- for (const prop in pack.tokenizer) {
2780
- const prevTokenizer = tokenizer[prop];
2781
- // Replace tokenizer with func to run extension, but fall back if false
2782
- tokenizer[prop] = (...args) => {
2783
- let ret = pack.tokenizer[prop].apply(tokenizer, args);
2784
- if (ret === false) {
2785
- ret = prevTokenizer.apply(tokenizer, args);
2786
- }
2787
- return ret;
2788
- };
2789
- }
2790
- opts.tokenizer = tokenizer;
2791
- }
2792
-
2793
- // ==-- Parse Hooks extensions --== //
2794
- if (pack.hooks) {
2795
- const hooks = marked.defaults.hooks || new Hooks();
2796
- for (const prop in pack.hooks) {
2797
- const prevHook = hooks[prop];
2798
- if (Hooks.passThroughHooks.has(prop)) {
2799
- hooks[prop] = (arg) => {
2800
- if (marked.defaults.async) {
2801
- return Promise.resolve(pack.hooks[prop].call(hooks, arg)).then(ret => {
2802
- return prevHook.call(hooks, ret);
2803
- });
2804
- }
2805
-
2806
- const ret = pack.hooks[prop].call(hooks, arg);
2807
- return prevHook.call(hooks, ret);
2808
- };
2809
- } else {
2810
- hooks[prop] = (...args) => {
2811
- let ret = pack.hooks[prop].apply(hooks, args);
2812
- if (ret === false) {
2813
- ret = prevHook.apply(hooks, args);
2814
- }
2815
- return ret;
2816
- };
2817
- }
2818
- }
2819
- opts.hooks = hooks;
2820
- }
2821
-
2822
- // ==-- Parse WalkTokens extensions --== //
2823
- if (pack.walkTokens) {
2824
- const walkTokens = marked.defaults.walkTokens;
2825
- opts.walkTokens = function(token) {
2826
- let values = [];
2827
- values.push(pack.walkTokens.call(this, token));
2828
- if (walkTokens) {
2829
- values = values.concat(walkTokens.call(this, token));
2830
- }
2831
- return values;
2832
- };
2833
- }
2834
-
2835
- marked.setOptions(opts);
2836
- });
2907
+ markedInstance.use(...args);
2908
+ marked.defaults = markedInstance.defaults;
2909
+ changeDefaults(marked.defaults);
2910
+ return marked;
2837
2911
  };
2838
2912
 
2839
2913
  /**
@@ -2841,44 +2915,14 @@ marked.use = function(...args) {
2841
2915
  */
2842
2916
 
2843
2917
  marked.walkTokens = function(tokens, callback) {
2844
- let values = [];
2845
- for (const token of tokens) {
2846
- values = values.concat(callback.call(marked, token));
2847
- switch (token.type) {
2848
- case 'table': {
2849
- for (const cell of token.header) {
2850
- values = values.concat(marked.walkTokens(cell.tokens, callback));
2851
- }
2852
- for (const row of token.rows) {
2853
- for (const cell of row) {
2854
- values = values.concat(marked.walkTokens(cell.tokens, callback));
2855
- }
2856
- }
2857
- break;
2858
- }
2859
- case 'list': {
2860
- values = values.concat(marked.walkTokens(token.items, callback));
2861
- break;
2862
- }
2863
- default: {
2864
- if (marked.defaults.extensions && marked.defaults.extensions.childTokens && marked.defaults.extensions.childTokens[token.type]) { // Walk any extensions
2865
- marked.defaults.extensions.childTokens[token.type].forEach(function(childTokens) {
2866
- values = values.concat(marked.walkTokens(token[childTokens], callback));
2867
- });
2868
- } else if (token.tokens) {
2869
- values = values.concat(marked.walkTokens(token.tokens, callback));
2870
- }
2871
- }
2872
- }
2873
- }
2874
- return values;
2918
+ return markedInstance.walkTokens(tokens, callback);
2875
2919
  };
2876
2920
 
2877
2921
  /**
2878
2922
  * Parse Inline
2879
2923
  * @param {string} src
2880
2924
  */
2881
- marked.parseInline = parseMarkdown(Lexer.lexInline, Parser.parseInline);
2925
+ marked.parseInline = markedInstance.parseInline;
2882
2926
 
2883
2927
  /**
2884
2928
  * Expose
@@ -2903,4 +2947,4 @@ const parse = marked;
2903
2947
  const parser = Parser.parse;
2904
2948
  const lexer = Lexer.lex;
2905
2949
 
2906
- export { Hooks, Lexer, Parser, Renderer, Slugger, TextRenderer, Tokenizer, defaults, getDefaults, lexer, marked, options, parse, parseInline, parser, setOptions, use, walkTokens };
2950
+ export { Hooks, Lexer, Marked, Parser, Renderer, Slugger, TextRenderer, Tokenizer, defaults, getDefaults, lexer, marked, options, parse, parseInline, parser, setOptions, use, walkTokens };