marked 7.0.2 → 7.0.4

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.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * marked v7.0.2 - a markdown parser
2
+ * marked v7.0.4 - a markdown parser
3
3
  * Copyright (c) 2011-2023, Christopher Jeffrey. (MIT Licensed)
4
4
  * https://github.com/markedjs/marked
5
5
  */
@@ -170,7 +170,8 @@ function splitCells(tableRow, count) {
170
170
  // ensure that every cell-delimiting pipe has a space
171
171
  // before it to distinguish it from an escaped pipe
172
172
  const row = tableRow.replace(/\|/g, (match, offset, str) => {
173
- let escaped = false, curr = offset;
173
+ let escaped = false;
174
+ let curr = offset;
174
175
  while (--curr >= 0 && str[curr] === '\\')
175
176
  escaped = !escaped;
176
177
  if (escaped) {
@@ -240,9 +241,8 @@ function findClosingBracket(str, b) {
240
241
  if (str.indexOf(b[1]) === -1) {
241
242
  return -1;
242
243
  }
243
- const l = str.length;
244
- let level = 0, i = 0;
245
- for (; i < l; i++) {
244
+ let level = 0;
245
+ for (let i = 0; i < str.length; i++) {
246
246
  if (str[i] === '\\') {
247
247
  i++;
248
248
  }
@@ -339,6 +339,7 @@ function indentCodeCompensation(raw, text) {
339
339
  */
340
340
  class _Tokenizer {
341
341
  options;
342
+ // TODO: Fix this rules type
342
343
  rules;
343
344
  lexer;
344
345
  constructor(options) {
@@ -432,7 +433,6 @@ class _Tokenizer {
432
433
  list(src) {
433
434
  let cap = this.rules.block.list.exec(src);
434
435
  if (cap) {
435
- let raw, istask, ischecked, indent, i, blankLine, endsWithBlankLine, line, nextLine, rawLine, itemContents, endEarly;
436
436
  let bull = cap[1].trim();
437
437
  const isordered = bull.length > 1;
438
438
  const list = {
@@ -449,9 +449,12 @@ class _Tokenizer {
449
449
  }
450
450
  // Get next list item
451
451
  const itemRegex = new RegExp(`^( {0,3}${bull})((?:[\t ][^\\n]*)?(?:\\n|$))`);
452
+ let raw = '';
453
+ let itemContents = '';
454
+ let endsWithBlankLine = false;
452
455
  // Check if current bullet point can start a new List Item
453
456
  while (src) {
454
- endEarly = false;
457
+ let endEarly = false;
455
458
  if (!(cap = itemRegex.exec(src))) {
456
459
  break;
457
460
  }
@@ -460,8 +463,9 @@ class _Tokenizer {
460
463
  }
461
464
  raw = cap[0];
462
465
  src = src.substring(raw.length);
463
- line = cap[2].split('\n', 1)[0].replace(/^\t+/, (t) => ' '.repeat(3 * t.length));
464
- nextLine = src.split('\n', 1)[0];
466
+ let line = cap[2].split('\n', 1)[0].replace(/^\t+/, (t) => ' '.repeat(3 * t.length));
467
+ let nextLine = src.split('\n', 1)[0];
468
+ let indent = 0;
465
469
  if (this.options.pedantic) {
466
470
  indent = 2;
467
471
  itemContents = line.trimLeft();
@@ -472,7 +476,7 @@ class _Tokenizer {
472
476
  itemContents = line.slice(indent);
473
477
  indent += cap[1].length;
474
478
  }
475
- blankLine = false;
479
+ let blankLine = false;
476
480
  if (!line && /^ *$/.test(nextLine)) { // Items begin with at most one blank line
477
481
  raw += nextLine + '\n';
478
482
  src = src.substring(nextLine.length + 1);
@@ -485,7 +489,7 @@ class _Tokenizer {
485
489
  const headingBeginRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`);
486
490
  // Check if following lines should be included in List Item
487
491
  while (src) {
488
- rawLine = src.split('\n', 1)[0];
492
+ const rawLine = src.split('\n', 1)[0];
489
493
  nextLine = rawLine;
490
494
  // Re-align to follow commonmark nesting rules
491
495
  if (this.options.pedantic) {
@@ -547,6 +551,8 @@ class _Tokenizer {
547
551
  endsWithBlankLine = true;
548
552
  }
549
553
  }
554
+ let istask = null;
555
+ let ischecked;
550
556
  // Check for task list items
551
557
  if (this.options.gfm) {
552
558
  istask = /^\[[ xX]\] /.exec(itemContents);
@@ -561,7 +567,8 @@ class _Tokenizer {
561
567
  task: !!istask,
562
568
  checked: ischecked,
563
569
  loose: false,
564
- text: itemContents
570
+ text: itemContents,
571
+ tokens: []
565
572
  });
566
573
  list.raw += raw;
567
574
  }
@@ -569,9 +576,8 @@ class _Tokenizer {
569
576
  list.items[list.items.length - 1].raw = raw.trimRight();
570
577
  list.items[list.items.length - 1].text = itemContents.trimRight();
571
578
  list.raw = list.raw.trimRight();
572
- const l = list.items.length;
573
579
  // Item child tokens handled here at end because we needed to have the final item to trim it first
574
- for (i = 0; i < l; i++) {
580
+ for (let i = 0; i < list.items.length; i++) {
575
581
  this.lexer.state.top = false;
576
582
  list.items[i].tokens = this.lexer.blockTokens(list.items[i].text, []);
577
583
  if (!list.loose) {
@@ -583,7 +589,7 @@ class _Tokenizer {
583
589
  }
584
590
  // Set all items to loose if list is loose
585
591
  if (list.loose) {
586
- for (i = 0; i < l; i++) {
592
+ for (let i = 0; i < list.items.length; i++) {
587
593
  list.items[i].loose = true;
588
594
  }
589
595
  }
@@ -633,7 +639,7 @@ class _Tokenizer {
633
639
  type: 'table',
634
640
  raw: cap[0],
635
641
  header: splitCells(cap[1]).map(c => {
636
- return { text: c };
642
+ return { text: c, tokens: [] };
637
643
  }),
638
644
  align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
639
645
  rows: cap[3] && cap[3].trim() ? cap[3].replace(/\n[ \t]*$/, '').split('\n') : []
@@ -642,23 +648,26 @@ class _Tokenizer {
642
648
  let l = item.align.length;
643
649
  let i, j, k, row;
644
650
  for (i = 0; i < l; i++) {
645
- if (/^ *-+: *$/.test(item.align[i])) {
646
- item.align[i] = 'right';
647
- }
648
- else if (/^ *:-+: *$/.test(item.align[i])) {
649
- item.align[i] = 'center';
650
- }
651
- else if (/^ *:-+ *$/.test(item.align[i])) {
652
- item.align[i] = 'left';
653
- }
654
- else {
655
- item.align[i] = null;
651
+ const align = item.align[i];
652
+ if (align) {
653
+ if (/^ *-+: *$/.test(align)) {
654
+ item.align[i] = 'right';
655
+ }
656
+ else if (/^ *:-+: *$/.test(align)) {
657
+ item.align[i] = 'center';
658
+ }
659
+ else if (/^ *:-+ *$/.test(align)) {
660
+ item.align[i] = 'left';
661
+ }
662
+ else {
663
+ item.align[i] = null;
664
+ }
656
665
  }
657
666
  }
658
667
  l = item.rows.length;
659
668
  for (i = 0; i < l; i++) {
660
669
  item.rows[i] = splitCells(item.rows[i], item.header.length).map(c => {
661
- return { text: c };
670
+ return { text: c, tokens: [] };
662
671
  });
663
672
  }
664
673
  // parse child tokens inside headers and cells
@@ -838,7 +847,8 @@ class _Tokenizer {
838
847
  return;
839
848
  const nextChar = match[1] || match[2] || '';
840
849
  if (!nextChar || !prevChar || this.rules.inline.punctuation.exec(prevChar)) {
841
- const lLength = match[0].length - 1;
850
+ // unicode Regex counts emoji as 1 char; spread into array for proper count (used multiple times below)
851
+ const lLength = [...match[0]].length - 1;
842
852
  let rDelim, rLength, delimTotal = lLength, midDelimTotal = 0;
843
853
  const endReg = match[0][0] === '*' ? this.rules.inline.emStrong.rDelimAst : this.rules.inline.emStrong.rDelimUnd;
844
854
  endReg.lastIndex = 0;
@@ -848,7 +858,7 @@ class _Tokenizer {
848
858
  rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6];
849
859
  if (!rDelim)
850
860
  continue; // skip single * in __abc*abc__
851
- rLength = rDelim.length;
861
+ rLength = [...rDelim].length;
852
862
  if (match[3] || match[4]) { // found another Left Delim
853
863
  delimTotal += rLength;
854
864
  continue;
@@ -864,7 +874,7 @@ class _Tokenizer {
864
874
  continue; // Haven't found enough closing delimiters
865
875
  // Remove extra characters. *a*** -> *a*
866
876
  rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal);
867
- const raw = src.slice(0, lLength + match.index + rLength + 1);
877
+ const raw = [...src].slice(0, lLength + match.index + rLength + 1).join('');
868
878
  // Create `em` if smallest delimiter has odd char count. *a***
869
879
  if (Math.min(lLength, rLength) % 2) {
870
880
  const text = raw.slice(1, -1);
@@ -1308,13 +1318,11 @@ function smartypants(text) {
1308
1318
  * mangle email addresses
1309
1319
  */
1310
1320
  function mangle(text) {
1311
- let out = '', i, ch;
1312
- const l = text.length;
1313
- for (i = 0; i < l; i++) {
1314
- ch = text.charCodeAt(i);
1315
- if (Math.random() > 0.5) {
1316
- ch = 'x' + ch.toString(16);
1317
- }
1321
+ let out = '';
1322
+ for (let i = 0; i < text.length; i++) {
1323
+ const ch = Math.random() > 0.5
1324
+ ? 'x' + text.charCodeAt(i).toString(16)
1325
+ : text.charCodeAt(i).toString();
1318
1326
  out += '&#' + ch + ';';
1319
1327
  }
1320
1328
  return out;
@@ -1760,7 +1768,7 @@ class _Renderer {
1760
1768
  this.options = options || exports.defaults;
1761
1769
  }
1762
1770
  code(code, infostring, escaped) {
1763
- const lang = (infostring || '').match(/\S*/)[0];
1771
+ const lang = (infostring || '').match(/^\S*/)?.[0];
1764
1772
  if (this.options.highlight) {
1765
1773
  const out = this.options.highlight(code, lang);
1766
1774
  if (out != null && out !== code) {
@@ -1799,7 +1807,8 @@ class _Renderer {
1799
1807
  return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
1800
1808
  }
1801
1809
  list(body, ordered, start) {
1802
- const type = ordered ? 'ol' : 'ul', startatt = (ordered && start !== 1) ? (' start="' + start + '"') : '';
1810
+ const type = ordered ? 'ol' : 'ul';
1811
+ const startatt = (ordered && start !== 1) ? (' start="' + start + '"') : '';
1803
1812
  return '<' + type + startatt + '>\n' + body + '</' + type + '>\n';
1804
1813
  }
1805
1814
  listitem(text, task, checked) {
@@ -1854,10 +1863,11 @@ class _Renderer {
1854
1863
  return `<del>${text}</del>`;
1855
1864
  }
1856
1865
  link(href, title, text) {
1857
- href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
1858
- if (href === null) {
1866
+ const cleanHref = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
1867
+ if (cleanHref === null) {
1859
1868
  return text;
1860
1869
  }
1870
+ href = cleanHref;
1861
1871
  let out = '<a href="' + href + '"';
1862
1872
  if (title) {
1863
1873
  out += ' title="' + title + '"';
@@ -1866,10 +1876,11 @@ class _Renderer {
1866
1876
  return out;
1867
1877
  }
1868
1878
  image(href, title, text) {
1869
- href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
1870
- if (href === null) {
1879
+ const cleanHref = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
1880
+ if (cleanHref === null) {
1871
1881
  return text;
1872
1882
  }
1883
+ href = cleanHref;
1873
1884
  let out = `<img src="${href}" alt="${text}"`;
1874
1885
  if (title) {
1875
1886
  out += ` title="${title}"`;
@@ -1997,14 +2008,14 @@ class _Parser {
1997
2008
  * Parse Loop
1998
2009
  */
1999
2010
  parse(tokens, top = true) {
2000
- let out = '', i, j, k, l2, l3, row, cell, header, body, token, ordered, start, loose, itemBody, item, checked, task, checkbox, ret;
2001
- const l = tokens.length;
2002
- for (i = 0; i < l; i++) {
2003
- token = tokens[i];
2011
+ let out = '';
2012
+ for (let i = 0; i < tokens.length; i++) {
2013
+ const token = tokens[i];
2004
2014
  // Run any renderer extensions
2005
2015
  if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {
2006
- ret = this.options.extensions.renderers[token.type].call({ parser: this }, token);
2007
- if (ret !== false || !['space', 'hr', 'heading', 'code', 'table', 'blockquote', 'list', 'html', 'paragraph', 'text'].includes(token.type)) {
2016
+ const genericToken = token;
2017
+ const ret = this.options.extensions.renderers[genericToken.type].call({ parser: this }, genericToken);
2018
+ if (ret !== false || !['space', 'hr', 'heading', 'code', 'table', 'blockquote', 'list', 'html', 'paragraph', 'text'].includes(genericToken.type)) {
2008
2019
  out += ret || '';
2009
2020
  continue;
2010
2021
  }
@@ -2018,30 +2029,30 @@ class _Parser {
2018
2029
  continue;
2019
2030
  }
2020
2031
  case 'heading': {
2021
- out += this.renderer.heading(this.parseInline(token.tokens), token.depth, unescape(this.parseInline(token.tokens, this.textRenderer)), this.slugger);
2032
+ const headingToken = token;
2033
+ out += this.renderer.heading(this.parseInline(headingToken.tokens), headingToken.depth, unescape(this.parseInline(headingToken.tokens, this.textRenderer)), this.slugger);
2022
2034
  continue;
2023
2035
  }
2024
2036
  case 'code': {
2025
- out += this.renderer.code(token.text, token.lang, !!token.escaped);
2037
+ const codeToken = token;
2038
+ out += this.renderer.code(codeToken.text, codeToken.lang, !!codeToken.escaped);
2026
2039
  continue;
2027
2040
  }
2028
2041
  case 'table': {
2029
- header = '';
2042
+ const tableToken = token;
2043
+ let header = '';
2030
2044
  // header
2031
- cell = '';
2032
- l2 = token.header.length;
2033
- for (j = 0; j < l2; j++) {
2034
- cell += this.renderer.tablecell(this.parseInline(token.header[j].tokens), { header: true, align: token.align[j] });
2045
+ let cell = '';
2046
+ for (let j = 0; j < tableToken.header.length; j++) {
2047
+ cell += this.renderer.tablecell(this.parseInline(tableToken.header[j].tokens), { header: true, align: tableToken.align[j] });
2035
2048
  }
2036
2049
  header += this.renderer.tablerow(cell);
2037
- body = '';
2038
- l2 = token.rows.length;
2039
- for (j = 0; j < l2; j++) {
2040
- row = token.rows[j];
2050
+ let body = '';
2051
+ for (let j = 0; j < tableToken.rows.length; j++) {
2052
+ const row = tableToken.rows[j];
2041
2053
  cell = '';
2042
- l3 = row.length;
2043
- for (k = 0; k < l3; k++) {
2044
- cell += this.renderer.tablecell(this.parseInline(row[k].tokens), { header: false, align: token.align[k] });
2054
+ for (let k = 0; k < row.length; k++) {
2055
+ cell += this.renderer.tablecell(this.parseInline(row[k].tokens), { header: false, align: tableToken.align[k] });
2045
2056
  }
2046
2057
  body += this.renderer.tablerow(cell);
2047
2058
  }
@@ -2049,23 +2060,24 @@ class _Parser {
2049
2060
  continue;
2050
2061
  }
2051
2062
  case 'blockquote': {
2052
- body = this.parse(token.tokens);
2063
+ const blockquoteToken = token;
2064
+ const body = this.parse(blockquoteToken.tokens);
2053
2065
  out += this.renderer.blockquote(body);
2054
2066
  continue;
2055
2067
  }
2056
2068
  case 'list': {
2057
- ordered = token.ordered;
2058
- start = token.start;
2059
- loose = token.loose;
2060
- l2 = token.items.length;
2061
- body = '';
2062
- for (j = 0; j < l2; j++) {
2063
- item = token.items[j];
2064
- checked = item.checked;
2065
- task = item.task;
2066
- itemBody = '';
2069
+ const listToken = token;
2070
+ const ordered = listToken.ordered;
2071
+ const start = listToken.start;
2072
+ const loose = listToken.loose;
2073
+ let body = '';
2074
+ for (let j = 0; j < listToken.items.length; j++) {
2075
+ const item = listToken.items[j];
2076
+ const checked = item.checked;
2077
+ const task = item.task;
2078
+ let itemBody = '';
2067
2079
  if (item.task) {
2068
- checkbox = this.renderer.checkbox(!!checked);
2080
+ const checkbox = this.renderer.checkbox(!!checked);
2069
2081
  if (loose) {
2070
2082
  if (item.tokens.length > 0 && item.tokens[0].type === 'paragraph') {
2071
2083
  item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
@@ -2091,18 +2103,21 @@ class _Parser {
2091
2103
  continue;
2092
2104
  }
2093
2105
  case 'html': {
2094
- out += this.renderer.html(token.text, token.block);
2106
+ const htmlToken = token;
2107
+ out += this.renderer.html(htmlToken.text, htmlToken.block);
2095
2108
  continue;
2096
2109
  }
2097
2110
  case 'paragraph': {
2098
- out += this.renderer.paragraph(this.parseInline(token.tokens));
2111
+ const paragraphToken = token;
2112
+ out += this.renderer.paragraph(this.parseInline(paragraphToken.tokens));
2099
2113
  continue;
2100
2114
  }
2101
2115
  case 'text': {
2102
- body = token.tokens ? this.parseInline(token.tokens) : token.text;
2103
- while (i + 1 < l && tokens[i + 1].type === 'text') {
2104
- token = tokens[++i];
2105
- body += '\n' + (token.tokens ? this.parseInline(token.tokens) : token.text);
2116
+ let textToken = token;
2117
+ let body = textToken.tokens ? this.parseInline(textToken.tokens) : textToken.text;
2118
+ while (i + 1 < tokens.length && tokens[i + 1].type === 'text') {
2119
+ textToken = tokens[++i];
2120
+ body += '\n' + (textToken.tokens ? this.parseInline(textToken.tokens) : textToken.text);
2106
2121
  }
2107
2122
  out += top ? this.renderer.paragraph(body) : body;
2108
2123
  continue;
@@ -2126,13 +2141,12 @@ class _Parser {
2126
2141
  */
2127
2142
  parseInline(tokens, renderer) {
2128
2143
  renderer = renderer || this.renderer;
2129
- let out = '', i, token, ret;
2130
- const l = tokens.length;
2131
- for (i = 0; i < l; i++) {
2132
- token = tokens[i];
2144
+ let out = '';
2145
+ for (let i = 0; i < tokens.length; i++) {
2146
+ const token = tokens[i];
2133
2147
  // Run any renderer extensions
2134
2148
  if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {
2135
- ret = this.options.extensions.renderers[token.type].call({ parser: this }, token);
2149
+ const ret = this.options.extensions.renderers[token.type].call({ parser: this }, token);
2136
2150
  if (ret !== false || !['escape', 'html', 'link', 'image', 'strong', 'em', 'codespan', 'br', 'del', 'text'].includes(token.type)) {
2137
2151
  out += ret || '';
2138
2152
  continue;
@@ -2140,31 +2154,38 @@ class _Parser {
2140
2154
  }
2141
2155
  switch (token.type) {
2142
2156
  case 'escape': {
2143
- out += renderer.text(token.text);
2157
+ const escapeToken = token;
2158
+ out += renderer.text(escapeToken.text);
2144
2159
  break;
2145
2160
  }
2146
2161
  case 'html': {
2147
- out += renderer.html(token.text);
2162
+ const tagToken = token;
2163
+ out += renderer.html(tagToken.text);
2148
2164
  break;
2149
2165
  }
2150
2166
  case 'link': {
2151
- out += renderer.link(token.href, token.title, this.parseInline(token.tokens, renderer));
2167
+ const linkToken = token;
2168
+ out += renderer.link(linkToken.href, linkToken.title, this.parseInline(linkToken.tokens, renderer));
2152
2169
  break;
2153
2170
  }
2154
2171
  case 'image': {
2155
- out += renderer.image(token.href, token.title, token.text);
2172
+ const imageToken = token;
2173
+ out += renderer.image(imageToken.href, imageToken.title, imageToken.text);
2156
2174
  break;
2157
2175
  }
2158
2176
  case 'strong': {
2159
- out += renderer.strong(this.parseInline(token.tokens, renderer));
2177
+ const strongToken = token;
2178
+ out += renderer.strong(this.parseInline(strongToken.tokens, renderer));
2160
2179
  break;
2161
2180
  }
2162
2181
  case 'em': {
2163
- out += renderer.em(this.parseInline(token.tokens, renderer));
2182
+ const emToken = token;
2183
+ out += renderer.em(this.parseInline(emToken.tokens, renderer));
2164
2184
  break;
2165
2185
  }
2166
2186
  case 'codespan': {
2167
- out += renderer.codespan(token.text);
2187
+ const codespanToken = token;
2188
+ out += renderer.codespan(codespanToken.text);
2168
2189
  break;
2169
2190
  }
2170
2191
  case 'br': {
@@ -2172,11 +2193,13 @@ class _Parser {
2172
2193
  break;
2173
2194
  }
2174
2195
  case 'del': {
2175
- out += renderer.del(this.parseInline(token.tokens, renderer));
2196
+ const delToken = token;
2197
+ out += renderer.del(this.parseInline(delToken.tokens, renderer));
2176
2198
  break;
2177
2199
  }
2178
2200
  case 'text': {
2179
- out += renderer.text(token.text);
2201
+ const textToken = token;
2202
+ out += renderer.text(textToken.text);
2180
2203
  break;
2181
2204
  }
2182
2205
  default: {
@@ -2244,10 +2267,11 @@ class Marked {
2244
2267
  values = values.concat(callback.call(this, token));
2245
2268
  switch (token.type) {
2246
2269
  case 'table': {
2247
- for (const cell of token.header) {
2270
+ const tableToken = token;
2271
+ for (const cell of tableToken.header) {
2248
2272
  values = values.concat(this.walkTokens(cell.tokens, callback));
2249
2273
  }
2250
- for (const row of token.rows) {
2274
+ for (const row of tableToken.rows) {
2251
2275
  for (const cell of row) {
2252
2276
  values = values.concat(this.walkTokens(cell.tokens, callback));
2253
2277
  }
@@ -2255,18 +2279,19 @@ class Marked {
2255
2279
  break;
2256
2280
  }
2257
2281
  case 'list': {
2258
- values = values.concat(this.walkTokens(token.items, callback));
2282
+ const listToken = token;
2283
+ values = values.concat(this.walkTokens(listToken.items, callback));
2259
2284
  break;
2260
2285
  }
2261
2286
  default: {
2262
- if (this.defaults.extensions && this.defaults.extensions.childTokens && this.defaults.extensions.childTokens[token.type]) { // Walk any extensions
2263
- this.defaults.extensions.childTokens[token.type].forEach((childTokens) => {
2264
- // @ts-expect-error we assume token[childToken] is an array of tokens but we can't be sure
2265
- values = values.concat(this.walkTokens(token[childTokens], callback));
2287
+ const genericToken = token;
2288
+ if (this.defaults.extensions?.childTokens?.[genericToken.type]) {
2289
+ this.defaults.extensions.childTokens[genericToken.type].forEach((childTokens) => {
2290
+ values = values.concat(this.walkTokens(genericToken[childTokens], callback));
2266
2291
  });
2267
2292
  }
2268
- else if (token.tokens) {
2269
- values = values.concat(this.walkTokens(token.tokens, callback));
2293
+ else if (genericToken.tokens) {
2294
+ values = values.concat(this.walkTokens(genericToken.tokens, callback));
2270
2295
  }
2271
2296
  }
2272
2297
  }
@@ -2306,8 +2331,9 @@ class Marked {
2306
2331
  if (!ext.level || (ext.level !== 'block' && ext.level !== 'inline')) {
2307
2332
  throw new Error("extension level must be 'block' or 'inline'");
2308
2333
  }
2309
- if (extensions[ext.level]) {
2310
- extensions[ext.level].unshift(ext.tokenizer);
2334
+ const extLevel = extensions[ext.level];
2335
+ if (extLevel) {
2336
+ extLevel.unshift(ext.tokenizer);
2311
2337
  }
2312
2338
  else {
2313
2339
  extensions[ext.level] = [ext.tokenizer];
@@ -2405,9 +2431,10 @@ class Marked {
2405
2431
  // ==-- Parse WalkTokens extensions --== //
2406
2432
  if (pack.walkTokens) {
2407
2433
  const walkTokens = this.defaults.walkTokens;
2434
+ const packWalktokens = pack.walkTokens;
2408
2435
  opts.walkTokens = function (token) {
2409
2436
  let values = [];
2410
- values.push(pack.walkTokens.call(this, token));
2437
+ values.push(packWalktokens.call(this, token));
2411
2438
  if (walkTokens) {
2412
2439
  values = values.concat(walkTokens.call(this, token));
2413
2440
  }
@@ -2430,6 +2457,13 @@ class Marked {
2430
2457
  }
2431
2458
  const origOpt = { ...optOrCallback };
2432
2459
  const opt = { ...this.defaults, ...origOpt };
2460
+ // Show warning if an extension set async to true but the parse was called with async: false
2461
+ if (this.defaults.async === true && origOpt.async === false) {
2462
+ if (!opt.silent) {
2463
+ console.warn('marked(): The async option was set to true by an extension. The async: false option sent to parse will be ignored.');
2464
+ }
2465
+ opt.async = true;
2466
+ }
2433
2467
  const throwError = this.#onError(!!opt.silent, !!opt.async, callback);
2434
2468
  // throw error in case of non string input
2435
2469
  if (typeof src === 'undefined' || src === null) {
@@ -2444,6 +2478,7 @@ class Marked {
2444
2478
  opt.hooks.options = opt;
2445
2479
  }
2446
2480
  if (callback) {
2481
+ const resultCallback = callback;
2447
2482
  const highlight = opt.highlight;
2448
2483
  let tokens;
2449
2484
  try {
@@ -2474,7 +2509,7 @@ class Marked {
2474
2509
  opt.highlight = highlight;
2475
2510
  return err
2476
2511
  ? throwError(err)
2477
- : callback(null, out);
2512
+ : resultCallback(null, out);
2478
2513
  };
2479
2514
  if (!highlight || highlight.length < 3) {
2480
2515
  return done();