marked 4.2.11 → 4.3.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 v4.2.11 - a markdown parser
2
+ * marked v4.3.0 - a markdown parser
3
3
  * Copyright (c) 2011-2023, Christopher Jeffrey. (MIT Licensed)
4
4
  * https://github.com/markedjs/marked
5
5
  */
@@ -19,6 +19,7 @@ function getDefaults() {
19
19
  headerIds: true,
20
20
  headerPrefix: '',
21
21
  highlight: null,
22
+ hooks: null,
22
23
  langPrefix: 'language-',
23
24
  mangle: true,
24
25
  pedantic: false,
@@ -183,23 +184,6 @@ function resolveUrl(base, href) {
183
184
 
184
185
  const noopTest = { exec: function noopTest() {} };
185
186
 
186
- function merge(obj) {
187
- let i = 1,
188
- target,
189
- key;
190
-
191
- for (; i < arguments.length; i++) {
192
- target = arguments[i];
193
- for (key in target) {
194
- if (Object.prototype.hasOwnProperty.call(target, key)) {
195
- obj[key] = target[key];
196
- }
197
- }
198
- }
199
-
200
- return obj;
201
- }
202
-
203
187
  function splitCells(tableRow, count) {
204
188
  // ensure that every cell-delimiting pipe has a space
205
189
  // before it to distinguish it from an escaped pipe
@@ -1109,7 +1093,7 @@ class Tokenizer {
1109
1093
  const block = {
1110
1094
  newline: /^(?: *(?:\n|$))+/,
1111
1095
  code: /^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,
1112
- fences: /^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?=\n|$)|$)/,
1096
+ fences: /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,
1113
1097
  hr: /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,
1114
1098
  heading: /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,
1115
1099
  blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,
@@ -1184,17 +1168,18 @@ block.blockquote = edit(block.blockquote)
1184
1168
  * Normal Block Grammar
1185
1169
  */
1186
1170
 
1187
- block.normal = merge({}, block);
1171
+ block.normal = { ...block };
1188
1172
 
1189
1173
  /**
1190
1174
  * GFM Block Grammar
1191
1175
  */
1192
1176
 
1193
- block.gfm = merge({}, block.normal, {
1177
+ block.gfm = {
1178
+ ...block.normal,
1194
1179
  table: '^ *([^\\n ].*\\|.*)\\n' // Header
1195
1180
  + ' {0,3}(?:\\| *)?(:?-+:? *(?:\\| *:?-+:? *)*)(?:\\| *)?' // Align
1196
1181
  + '(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)' // Cells
1197
- });
1182
+ };
1198
1183
 
1199
1184
  block.gfm.table = edit(block.gfm.table)
1200
1185
  .replace('hr', block.hr)
@@ -1222,7 +1207,8 @@ block.gfm.paragraph = edit(block._paragraph)
1222
1207
  * Pedantic grammar (original John Gruber's loose markdown specification)
1223
1208
  */
1224
1209
 
1225
- block.pedantic = merge({}, block.normal, {
1210
+ block.pedantic = {
1211
+ ...block.normal,
1226
1212
  html: edit(
1227
1213
  '^ *(?:comment *(?:\\n|\\s*$)'
1228
1214
  + '|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)' // closed tag
@@ -1246,7 +1232,7 @@ block.pedantic = merge({}, block.normal, {
1246
1232
  .replace('|list', '')
1247
1233
  .replace('|html', '')
1248
1234
  .getRegex()
1249
- });
1235
+ };
1250
1236
 
1251
1237
  /**
1252
1238
  * Inline-Level Grammar
@@ -1348,13 +1334,14 @@ inline.reflinkSearch = edit(inline.reflinkSearch, 'g')
1348
1334
  * Normal Inline Grammar
1349
1335
  */
1350
1336
 
1351
- inline.normal = merge({}, inline);
1337
+ inline.normal = { ...inline };
1352
1338
 
1353
1339
  /**
1354
1340
  * Pedantic Inline Grammar
1355
1341
  */
1356
1342
 
1357
- inline.pedantic = merge({}, inline.normal, {
1343
+ inline.pedantic = {
1344
+ ...inline.normal,
1358
1345
  strong: {
1359
1346
  start: /^__|\*\*/,
1360
1347
  middle: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
@@ -1373,20 +1360,21 @@ inline.pedantic = merge({}, inline.normal, {
1373
1360
  reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/)
1374
1361
  .replace('label', inline._label)
1375
1362
  .getRegex()
1376
- });
1363
+ };
1377
1364
 
1378
1365
  /**
1379
1366
  * GFM Inline Grammar
1380
1367
  */
1381
1368
 
1382
- inline.gfm = merge({}, inline.normal, {
1369
+ inline.gfm = {
1370
+ ...inline.normal,
1383
1371
  escape: edit(inline.escape).replace('])', '~|])').getRegex(),
1384
1372
  _extended_email: /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,
1385
1373
  url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,
1386
1374
  _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,
1387
1375
  del: /^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/,
1388
1376
  text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/
1389
- });
1377
+ };
1390
1378
 
1391
1379
  inline.gfm.url = edit(inline.gfm.url, 'i')
1392
1380
  .replace('email', inline.gfm._extended_email)
@@ -1395,13 +1383,14 @@ inline.gfm.url = edit(inline.gfm.url, 'i')
1395
1383
  * GFM + Line Breaks Inline Grammar
1396
1384
  */
1397
1385
 
1398
- inline.breaks = merge({}, inline.gfm, {
1386
+ inline.breaks = {
1387
+ ...inline.gfm,
1399
1388
  br: edit(inline.br).replace('{2,}', '*').getRegex(),
1400
1389
  text: edit(inline.gfm.text)
1401
1390
  .replace('\\b_', '\\b_| {2,}\\n')
1402
1391
  .replace(/\{2,\}/g, '*')
1403
1392
  .getRegex()
1404
- });
1393
+ };
1405
1394
 
1406
1395
  /**
1407
1396
  * smartypants text replacement
@@ -2478,122 +2467,194 @@ class Parser {
2478
2467
  }
2479
2468
  }
2480
2469
 
2481
- /**
2482
- * Marked
2483
- */
2484
- function marked(src, opt, callback) {
2485
- // throw error in case of non string input
2486
- if (typeof src === 'undefined' || src === null) {
2487
- throw new Error('marked(): input parameter is undefined or null');
2470
+ class Hooks {
2471
+ constructor(options) {
2472
+ this.options = options || defaults;
2488
2473
  }
2489
- if (typeof src !== 'string') {
2490
- throw new Error('marked(): input parameter is of type '
2491
- + Object.prototype.toString.call(src) + ', string expected');
2474
+
2475
+ static passThroughHooks = new Set([
2476
+ 'preprocess',
2477
+ 'postprocess'
2478
+ ]);
2479
+
2480
+ /**
2481
+ * Process markdown before marked
2482
+ */
2483
+ preprocess(markdown) {
2484
+ return markdown;
2492
2485
  }
2493
2486
 
2494
- if (typeof opt === 'function') {
2495
- callback = opt;
2496
- opt = null;
2487
+ /**
2488
+ * Process HTML after marked is finished
2489
+ */
2490
+ postprocess(html) {
2491
+ return html;
2497
2492
  }
2493
+ }
2498
2494
 
2499
- opt = merge({}, marked.defaults, opt || {});
2500
- checkSanitizeDeprecation(opt);
2495
+ function onError(silent, async, callback) {
2496
+ return (e) => {
2497
+ e.message += '\nPlease report this to https://github.com/markedjs/marked.';
2501
2498
 
2502
- if (callback) {
2503
- const highlight = opt.highlight;
2504
- let tokens;
2499
+ if (silent) {
2500
+ const msg = '<p>An error occurred:</p><pre>'
2501
+ + escape(e.message + '', true)
2502
+ + '</pre>';
2503
+ if (async) {
2504
+ return Promise.resolve(msg);
2505
+ }
2506
+ if (callback) {
2507
+ callback(null, msg);
2508
+ return;
2509
+ }
2510
+ return msg;
2511
+ }
2505
2512
 
2506
- try {
2507
- tokens = Lexer.lex(src, opt);
2508
- } catch (e) {
2509
- return callback(e);
2513
+ if (async) {
2514
+ return Promise.reject(e);
2510
2515
  }
2516
+ if (callback) {
2517
+ callback(e);
2518
+ return;
2519
+ }
2520
+ throw e;
2521
+ };
2522
+ }
2511
2523
 
2512
- const done = function(err) {
2513
- let out;
2524
+ function parseMarkdown(lexer, parser) {
2525
+ return (src, opt, callback) => {
2526
+ if (typeof opt === 'function') {
2527
+ callback = opt;
2528
+ opt = null;
2529
+ }
2514
2530
 
2515
- if (!err) {
2516
- try {
2517
- if (opt.walkTokens) {
2518
- marked.walkTokens(tokens, opt.walkTokens);
2519
- }
2520
- out = Parser.parse(tokens, opt);
2521
- } catch (e) {
2522
- err = e;
2523
- }
2524
- }
2531
+ const origOpt = { ...opt };
2532
+ opt = { ...marked.defaults, ...origOpt };
2533
+ const throwError = onError(opt.silent, opt.async, callback);
2525
2534
 
2526
- opt.highlight = highlight;
2535
+ // throw error in case of non string input
2536
+ if (typeof src === 'undefined' || src === null) {
2537
+ return throwError(new Error('marked(): input parameter is undefined or null'));
2538
+ }
2539
+ if (typeof src !== 'string') {
2540
+ return throwError(new Error('marked(): input parameter is of type '
2541
+ + Object.prototype.toString.call(src) + ', string expected'));
2542
+ }
2527
2543
 
2528
- return err
2529
- ? callback(err)
2530
- : callback(null, out);
2531
- };
2544
+ checkSanitizeDeprecation(opt);
2532
2545
 
2533
- if (!highlight || highlight.length < 3) {
2534
- return done();
2546
+ if (opt.hooks) {
2547
+ opt.hooks.options = opt;
2535
2548
  }
2536
2549
 
2537
- delete opt.highlight;
2550
+ if (callback) {
2551
+ const highlight = opt.highlight;
2552
+ let tokens;
2553
+
2554
+ try {
2555
+ if (opt.hooks) {
2556
+ src = opt.hooks.preprocess(src);
2557
+ }
2558
+ tokens = lexer(src, opt);
2559
+ } catch (e) {
2560
+ return throwError(e);
2561
+ }
2538
2562
 
2539
- if (!tokens.length) return done();
2563
+ const done = function(err) {
2564
+ let out;
2540
2565
 
2541
- let pending = 0;
2542
- marked.walkTokens(tokens, function(token) {
2543
- if (token.type === 'code') {
2544
- pending++;
2545
- setTimeout(() => {
2546
- highlight(token.text, token.lang, function(err, code) {
2547
- if (err) {
2548
- return done(err);
2566
+ if (!err) {
2567
+ try {
2568
+ if (opt.walkTokens) {
2569
+ marked.walkTokens(tokens, opt.walkTokens);
2549
2570
  }
2550
- if (code != null && code !== token.text) {
2551
- token.text = code;
2552
- token.escaped = true;
2571
+ out = parser(tokens, opt);
2572
+ if (opt.hooks) {
2573
+ out = opt.hooks.postprocess(out);
2553
2574
  }
2575
+ } catch (e) {
2576
+ err = e;
2577
+ }
2578
+ }
2554
2579
 
2555
- pending--;
2556
- if (pending === 0) {
2557
- done();
2558
- }
2559
- });
2560
- }, 0);
2580
+ opt.highlight = highlight;
2581
+
2582
+ return err
2583
+ ? throwError(err)
2584
+ : callback(null, out);
2585
+ };
2586
+
2587
+ if (!highlight || highlight.length < 3) {
2588
+ return done();
2561
2589
  }
2562
- });
2563
2590
 
2564
- if (pending === 0) {
2565
- done();
2591
+ delete opt.highlight;
2592
+
2593
+ if (!tokens.length) return done();
2594
+
2595
+ let pending = 0;
2596
+ marked.walkTokens(tokens, function(token) {
2597
+ if (token.type === 'code') {
2598
+ pending++;
2599
+ setTimeout(() => {
2600
+ highlight(token.text, token.lang, function(err, code) {
2601
+ if (err) {
2602
+ return done(err);
2603
+ }
2604
+ if (code != null && code !== token.text) {
2605
+ token.text = code;
2606
+ token.escaped = true;
2607
+ }
2608
+
2609
+ pending--;
2610
+ if (pending === 0) {
2611
+ done();
2612
+ }
2613
+ });
2614
+ }, 0);
2615
+ }
2616
+ });
2617
+
2618
+ if (pending === 0) {
2619
+ done();
2620
+ }
2621
+
2622
+ return;
2566
2623
  }
2567
2624
 
2568
- return;
2569
- }
2625
+ if (opt.async) {
2626
+ return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src)
2627
+ .then(src => lexer(src, opt))
2628
+ .then(tokens => opt.walkTokens ? Promise.all(marked.walkTokens(tokens, opt.walkTokens)).then(() => tokens) : tokens)
2629
+ .then(tokens => parser(tokens, opt))
2630
+ .then(html => opt.hooks ? opt.hooks.postprocess(html) : html)
2631
+ .catch(throwError);
2632
+ }
2570
2633
 
2571
- function onError(e) {
2572
- e.message += '\nPlease report this to https://github.com/markedjs/marked.';
2573
- if (opt.silent) {
2574
- return '<p>An error occurred:</p><pre>'
2575
- + escape(e.message + '', true)
2576
- + '</pre>';
2634
+ try {
2635
+ if (opt.hooks) {
2636
+ src = opt.hooks.preprocess(src);
2637
+ }
2638
+ const tokens = lexer(src, opt);
2639
+ if (opt.walkTokens) {
2640
+ marked.walkTokens(tokens, opt.walkTokens);
2641
+ }
2642
+ let html = parser(tokens, opt);
2643
+ if (opt.hooks) {
2644
+ html = opt.hooks.postprocess(html);
2645
+ }
2646
+ return html;
2647
+ } catch (e) {
2648
+ return throwError(e);
2577
2649
  }
2578
- throw e;
2579
- }
2650
+ };
2651
+ }
2580
2652
 
2581
- try {
2582
- const tokens = Lexer.lex(src, opt);
2583
- if (opt.walkTokens) {
2584
- if (opt.async) {
2585
- return Promise.all(marked.walkTokens(tokens, opt.walkTokens))
2586
- .then(() => {
2587
- return Parser.parse(tokens, opt);
2588
- })
2589
- .catch(onError);
2590
- }
2591
- marked.walkTokens(tokens, opt.walkTokens);
2592
- }
2593
- return Parser.parse(tokens, opt);
2594
- } catch (e) {
2595
- onError(e);
2596
- }
2653
+ /**
2654
+ * Marked
2655
+ */
2656
+ function marked(src, opt, callback) {
2657
+ return parseMarkdown(Lexer.lex, Parser.parse)(src, opt, callback);
2597
2658
  }
2598
2659
 
2599
2660
  /**
@@ -2602,7 +2663,7 @@ function marked(src, opt, callback) {
2602
2663
 
2603
2664
  marked.options =
2604
2665
  marked.setOptions = function(opt) {
2605
- merge(marked.defaults, opt);
2666
+ marked.defaults = { ...marked.defaults, ...opt };
2606
2667
  changeDefaults(marked.defaults);
2607
2668
  return marked;
2608
2669
  };
@@ -2620,10 +2681,10 @@ marked.use = function(...args) {
2620
2681
 
2621
2682
  args.forEach((pack) => {
2622
2683
  // copy options to new object
2623
- const opts = merge({}, pack);
2684
+ const opts = { ...pack };
2624
2685
 
2625
2686
  // set async to true if it was set to true before
2626
- opts.async = marked.defaults.async || opts.async;
2687
+ opts.async = marked.defaults.async || opts.async || false;
2627
2688
 
2628
2689
  // ==-- Parse "addon" extensions --== //
2629
2690
  if (pack.extensions) {
@@ -2710,6 +2771,35 @@ marked.use = function(...args) {
2710
2771
  opts.tokenizer = tokenizer;
2711
2772
  }
2712
2773
 
2774
+ // ==-- Parse Hooks extensions --== //
2775
+ if (pack.hooks) {
2776
+ const hooks = marked.defaults.hooks || new Hooks();
2777
+ for (const prop in pack.hooks) {
2778
+ const prevHook = hooks[prop];
2779
+ if (Hooks.passThroughHooks.has(prop)) {
2780
+ hooks[prop] = (arg) => {
2781
+ if (marked.defaults.async) {
2782
+ return Promise.resolve(pack.hooks[prop].call(hooks, arg)).then(ret => {
2783
+ return prevHook.call(hooks, ret);
2784
+ });
2785
+ }
2786
+
2787
+ const ret = pack.hooks[prop].call(hooks, arg);
2788
+ return prevHook.call(hooks, ret);
2789
+ };
2790
+ } else {
2791
+ hooks[prop] = (...args) => {
2792
+ let ret = pack.hooks[prop].apply(hooks, args);
2793
+ if (ret === false) {
2794
+ ret = prevHook.apply(hooks, args);
2795
+ }
2796
+ return ret;
2797
+ };
2798
+ }
2799
+ }
2800
+ opts.hooks = hooks;
2801
+ }
2802
+
2713
2803
  // ==-- Parse WalkTokens extensions --== //
2714
2804
  if (pack.walkTokens) {
2715
2805
  const walkTokens = marked.defaults.walkTokens;
@@ -2769,35 +2859,7 @@ marked.walkTokens = function(tokens, callback) {
2769
2859
  * Parse Inline
2770
2860
  * @param {string} src
2771
2861
  */
2772
- marked.parseInline = function(src, opt) {
2773
- // throw error in case of non string input
2774
- if (typeof src === 'undefined' || src === null) {
2775
- throw new Error('marked.parseInline(): input parameter is undefined or null');
2776
- }
2777
- if (typeof src !== 'string') {
2778
- throw new Error('marked.parseInline(): input parameter is of type '
2779
- + Object.prototype.toString.call(src) + ', string expected');
2780
- }
2781
-
2782
- opt = merge({}, marked.defaults, opt || {});
2783
- checkSanitizeDeprecation(opt);
2784
-
2785
- try {
2786
- const tokens = Lexer.lexInline(src, opt);
2787
- if (opt.walkTokens) {
2788
- marked.walkTokens(tokens, opt.walkTokens);
2789
- }
2790
- return Parser.parseInline(tokens, opt);
2791
- } catch (e) {
2792
- e.message += '\nPlease report this to https://github.com/markedjs/marked.';
2793
- if (opt.silent) {
2794
- return '<p>An error occurred:</p><pre>'
2795
- + escape(e.message + '', true)
2796
- + '</pre>';
2797
- }
2798
- throw e;
2799
- }
2800
- };
2862
+ marked.parseInline = parseMarkdown(Lexer.lexInline, Parser.parseInline);
2801
2863
 
2802
2864
  /**
2803
2865
  * Expose
@@ -2810,6 +2872,7 @@ marked.Lexer = Lexer;
2810
2872
  marked.lexer = Lexer.lex;
2811
2873
  marked.Tokenizer = Tokenizer;
2812
2874
  marked.Slugger = Slugger;
2875
+ marked.Hooks = Hooks;
2813
2876
  marked.parse = marked;
2814
2877
 
2815
2878
  const options = marked.options;
@@ -2821,4 +2884,4 @@ const parse = marked;
2821
2884
  const parser = Parser.parse;
2822
2885
  const lexer = Lexer.lex;
2823
2886
 
2824
- export { Lexer, Parser, Renderer, Slugger, TextRenderer, Tokenizer, defaults, getDefaults, lexer, marked, options, parse, parseInline, parser, setOptions, use, walkTokens };
2887
+ export { Hooks, Lexer, Parser, Renderer, Slugger, TextRenderer, Tokenizer, defaults, getDefaults, lexer, marked, options, parse, parseInline, parser, setOptions, use, walkTokens };