marked 12.0.2 → 13.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.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * marked v12.0.2 - a markdown parser
2
+ * marked v13.0.0 - a markdown parser
3
3
  * Copyright (c) 2011-2024, Christopher Jeffrey. (MIT Licensed)
4
4
  * https://github.com/markedjs/marked
5
5
  */
@@ -317,23 +317,82 @@ class _Tokenizer {
317
317
  if (cap) {
318
318
  return {
319
319
  type: 'hr',
320
- raw: cap[0]
320
+ raw: rtrim(cap[0], '\n')
321
321
  };
322
322
  }
323
323
  }
324
324
  blockquote(src) {
325
325
  const cap = this.rules.block.blockquote.exec(src);
326
326
  if (cap) {
327
- // precede setext continuation with 4 spaces so it isn't a setext
328
- let text = cap[0].replace(/\n {0,3}((?:=+|-+) *)(?=\n|$)/g, '\n $1');
329
- text = rtrim(text.replace(/^ *>[ \t]?/gm, ''), '\n');
330
- const top = this.lexer.state.top;
331
- this.lexer.state.top = true;
332
- const tokens = this.lexer.blockTokens(text);
333
- this.lexer.state.top = top;
327
+ let lines = rtrim(cap[0], '\n').split('\n');
328
+ let raw = '';
329
+ let text = '';
330
+ const tokens = [];
331
+ while (lines.length > 0) {
332
+ let inBlockquote = false;
333
+ const currentLines = [];
334
+ let i;
335
+ for (i = 0; i < lines.length; i++) {
336
+ // get lines up to a continuation
337
+ if (/^ {0,3}>/.test(lines[i])) {
338
+ currentLines.push(lines[i]);
339
+ inBlockquote = true;
340
+ }
341
+ else if (!inBlockquote) {
342
+ currentLines.push(lines[i]);
343
+ }
344
+ else {
345
+ break;
346
+ }
347
+ }
348
+ lines = lines.slice(i);
349
+ const currentRaw = currentLines.join('\n');
350
+ const currentText = currentRaw
351
+ // precede setext continuation with 4 spaces so it isn't a setext
352
+ .replace(/\n {0,3}((?:=+|-+) *)(?=\n|$)/g, '\n $1')
353
+ .replace(/^ {0,3}>[ \t]?/gm, '');
354
+ raw = raw ? `${raw}\n${currentRaw}` : currentRaw;
355
+ text = text ? `${text}\n${currentText}` : currentText;
356
+ // parse blockquote lines as top level tokens
357
+ // merge paragraphs if this is a continuation
358
+ const top = this.lexer.state.top;
359
+ this.lexer.state.top = true;
360
+ this.lexer.blockTokens(currentText, tokens, true);
361
+ this.lexer.state.top = top;
362
+ // if there is no continuation then we are done
363
+ if (lines.length === 0) {
364
+ break;
365
+ }
366
+ const lastToken = tokens[tokens.length - 1];
367
+ if (lastToken?.type === 'code') {
368
+ // blockquote continuation cannot be preceded by a code block
369
+ break;
370
+ }
371
+ else if (lastToken?.type === 'blockquote') {
372
+ // include continuation in nested blockquote
373
+ const oldToken = lastToken;
374
+ const newText = oldToken.raw + '\n' + lines.join('\n');
375
+ const newToken = this.blockquote(newText);
376
+ tokens[tokens.length - 1] = newToken;
377
+ raw = raw.substring(0, raw.length - oldToken.raw.length) + newToken.raw;
378
+ text = text.substring(0, text.length - oldToken.text.length) + newToken.text;
379
+ break;
380
+ }
381
+ else if (lastToken?.type === 'list') {
382
+ // include continuation in nested list
383
+ const oldToken = lastToken;
384
+ const newText = oldToken.raw + '\n' + lines.join('\n');
385
+ const newToken = this.list(newText);
386
+ tokens[tokens.length - 1] = newToken;
387
+ raw = raw.substring(0, raw.length - lastToken.raw.length) + newToken.raw;
388
+ text = text.substring(0, text.length - oldToken.raw.length) + newToken.raw;
389
+ lines = newText.substring(tokens[tokens.length - 1].raw.length).split('\n');
390
+ continue;
391
+ }
392
+ }
334
393
  return {
335
394
  type: 'blockquote',
336
- raw: cap[0],
395
+ raw,
337
396
  tokens,
338
397
  text
339
398
  };
@@ -570,17 +629,21 @@ class _Tokenizer {
570
629
  item.align.push(null);
571
630
  }
572
631
  }
573
- for (const header of headers) {
632
+ for (let i = 0; i < headers.length; i++) {
574
633
  item.header.push({
575
- text: header,
576
- tokens: this.lexer.inline(header)
634
+ text: headers[i],
635
+ tokens: this.lexer.inline(headers[i]),
636
+ header: true,
637
+ align: item.align[i]
577
638
  });
578
639
  }
579
640
  for (const row of rows) {
580
- item.rows.push(splitCells(row, item.header.length).map(cell => {
641
+ item.rows.push(splitCells(row, item.header.length).map((cell, i) => {
581
642
  return {
582
643
  text: cell,
583
- tokens: this.lexer.inline(cell)
644
+ tokens: this.lexer.inline(cell),
645
+ header: false,
646
+ align: item.align[i]
584
647
  };
585
648
  }));
586
649
  }
@@ -1276,7 +1339,7 @@ class _Lexer {
1276
1339
  this.inlineQueue = [];
1277
1340
  return this.tokens;
1278
1341
  }
1279
- blockTokens(src, tokens = []) {
1342
+ blockTokens(src, tokens = [], lastParagraphClipped = false) {
1280
1343
  if (this.options.pedantic) {
1281
1344
  src = src.replace(/\t/g, ' ').replace(/^ +$/gm, '');
1282
1345
  }
@@ -1288,7 +1351,6 @@ class _Lexer {
1288
1351
  let token;
1289
1352
  let lastToken;
1290
1353
  let cutSrc;
1291
- let lastParagraphClipped;
1292
1354
  while (src) {
1293
1355
  if (this.options.extensions
1294
1356
  && this.options.extensions.block
@@ -1414,7 +1476,7 @@ class _Lexer {
1414
1476
  }
1415
1477
  if (this.state.top && (token = this.tokenizer.paragraph(cutSrc))) {
1416
1478
  lastToken = tokens[tokens.length - 1];
1417
- if (lastParagraphClipped && lastToken.type === 'paragraph') {
1479
+ if (lastParagraphClipped && lastToken?.type === 'paragraph') {
1418
1480
  lastToken.raw += '\n' + token.raw;
1419
1481
  lastToken.text += '\n' + token.text;
1420
1482
  this.inlineQueue.pop();
@@ -1633,53 +1695,103 @@ class _Lexer {
1633
1695
  */
1634
1696
  class _Renderer {
1635
1697
  options;
1698
+ parser; // set by the parser
1636
1699
  constructor(options) {
1637
1700
  this.options = options || exports.defaults;
1638
1701
  }
1639
- code(code, infostring, escaped) {
1640
- const lang = (infostring || '').match(/^\S*/)?.[0];
1641
- code = code.replace(/\n$/, '') + '\n';
1642
- if (!lang) {
1702
+ space(token) {
1703
+ return '';
1704
+ }
1705
+ code({ text, lang, escaped }) {
1706
+ const langString = (lang || '').match(/^\S*/)?.[0];
1707
+ const code = text.replace(/\n$/, '') + '\n';
1708
+ if (!langString) {
1643
1709
  return '<pre><code>'
1644
1710
  + (escaped ? code : escape$1(code, true))
1645
1711
  + '</code></pre>\n';
1646
1712
  }
1647
1713
  return '<pre><code class="language-'
1648
- + escape$1(lang)
1714
+ + escape$1(langString)
1649
1715
  + '">'
1650
1716
  + (escaped ? code : escape$1(code, true))
1651
1717
  + '</code></pre>\n';
1652
1718
  }
1653
- blockquote(quote) {
1654
- return `<blockquote>\n${quote}</blockquote>\n`;
1719
+ blockquote({ tokens }) {
1720
+ const body = this.parser.parse(tokens);
1721
+ return `<blockquote>\n${body}</blockquote>\n`;
1655
1722
  }
1656
- html(html, block) {
1657
- return html;
1723
+ html({ text }) {
1724
+ return text;
1658
1725
  }
1659
- heading(text, level, raw) {
1660
- // ignore IDs
1661
- return `<h${level}>${text}</h${level}>\n`;
1726
+ heading({ tokens, depth }) {
1727
+ return `<h${depth}>${this.parser.parseInline(tokens)}</h${depth}>\n`;
1662
1728
  }
1663
- hr() {
1729
+ hr(token) {
1664
1730
  return '<hr>\n';
1665
1731
  }
1666
- list(body, ordered, start) {
1732
+ list(token) {
1733
+ const ordered = token.ordered;
1734
+ const start = token.start;
1735
+ let body = '';
1736
+ for (let j = 0; j < token.items.length; j++) {
1737
+ const item = token.items[j];
1738
+ body += this.listitem(item);
1739
+ }
1667
1740
  const type = ordered ? 'ol' : 'ul';
1668
- const startatt = (ordered && start !== 1) ? (' start="' + start + '"') : '';
1669
- return '<' + type + startatt + '>\n' + body + '</' + type + '>\n';
1670
- }
1671
- listitem(text, task, checked) {
1672
- return `<li>${text}</li>\n`;
1741
+ const startAttr = (ordered && start !== 1) ? (' start="' + start + '"') : '';
1742
+ return '<' + type + startAttr + '>\n' + body + '</' + type + '>\n';
1743
+ }
1744
+ listitem(item) {
1745
+ let itemBody = '';
1746
+ if (item.task) {
1747
+ const checkbox = this.checkbox({ checked: !!item.checked });
1748
+ if (item.loose) {
1749
+ if (item.tokens.length > 0 && item.tokens[0].type === 'paragraph') {
1750
+ item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
1751
+ if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {
1752
+ item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text;
1753
+ }
1754
+ }
1755
+ else {
1756
+ item.tokens.unshift({
1757
+ type: 'text',
1758
+ raw: checkbox + ' ',
1759
+ text: checkbox + ' '
1760
+ });
1761
+ }
1762
+ }
1763
+ else {
1764
+ itemBody += checkbox + ' ';
1765
+ }
1766
+ }
1767
+ itemBody += this.parser.parse(item.tokens, !!item.loose);
1768
+ return `<li>${itemBody}</li>\n`;
1673
1769
  }
1674
- checkbox(checked) {
1770
+ checkbox({ checked }) {
1675
1771
  return '<input '
1676
1772
  + (checked ? 'checked="" ' : '')
1677
1773
  + 'disabled="" type="checkbox">';
1678
1774
  }
1679
- paragraph(text) {
1680
- return `<p>${text}</p>\n`;
1775
+ paragraph({ tokens }) {
1776
+ return `<p>${this.parser.parseInline(tokens)}</p>\n`;
1681
1777
  }
1682
- table(header, body) {
1778
+ table(token) {
1779
+ let header = '';
1780
+ // header
1781
+ let cell = '';
1782
+ for (let j = 0; j < token.header.length; j++) {
1783
+ cell += this.tablecell(token.header[j]);
1784
+ }
1785
+ header += this.tablerow({ text: cell });
1786
+ let body = '';
1787
+ for (let j = 0; j < token.rows.length; j++) {
1788
+ const row = token.rows[j];
1789
+ cell = '';
1790
+ for (let k = 0; k < row.length; k++) {
1791
+ cell += this.tablecell(row[k]);
1792
+ }
1793
+ body += this.tablerow({ text: cell });
1794
+ }
1683
1795
  if (body)
1684
1796
  body = `<tbody>${body}</tbody>`;
1685
1797
  return '<table>\n'
@@ -1689,35 +1801,37 @@ class _Renderer {
1689
1801
  + body
1690
1802
  + '</table>\n';
1691
1803
  }
1692
- tablerow(content) {
1693
- return `<tr>\n${content}</tr>\n`;
1804
+ tablerow({ text }) {
1805
+ return `<tr>\n${text}</tr>\n`;
1694
1806
  }
1695
- tablecell(content, flags) {
1696
- const type = flags.header ? 'th' : 'td';
1697
- const tag = flags.align
1698
- ? `<${type} align="${flags.align}">`
1807
+ tablecell(token) {
1808
+ const content = this.parser.parseInline(token.tokens);
1809
+ const type = token.header ? 'th' : 'td';
1810
+ const tag = token.align
1811
+ ? `<${type} align="${token.align}">`
1699
1812
  : `<${type}>`;
1700
1813
  return tag + content + `</${type}>\n`;
1701
1814
  }
1702
1815
  /**
1703
1816
  * span level renderer
1704
1817
  */
1705
- strong(text) {
1706
- return `<strong>${text}</strong>`;
1818
+ strong({ tokens }) {
1819
+ return `<strong>${this.parser.parseInline(tokens)}</strong>`;
1707
1820
  }
1708
- em(text) {
1709
- return `<em>${text}</em>`;
1821
+ em({ tokens }) {
1822
+ return `<em>${this.parser.parseInline(tokens)}</em>`;
1710
1823
  }
1711
- codespan(text) {
1824
+ codespan({ text }) {
1712
1825
  return `<code>${text}</code>`;
1713
1826
  }
1714
- br() {
1827
+ br(token) {
1715
1828
  return '<br>';
1716
1829
  }
1717
- del(text) {
1718
- return `<del>${text}</del>`;
1830
+ del({ tokens }) {
1831
+ return `<del>${this.parser.parseInline(tokens)}</del>`;
1719
1832
  }
1720
- link(href, title, text) {
1833
+ link({ href, title, tokens }) {
1834
+ const text = this.parser.parseInline(tokens);
1721
1835
  const cleanHref = cleanUrl(href);
1722
1836
  if (cleanHref === null) {
1723
1837
  return text;
@@ -1730,7 +1844,7 @@ class _Renderer {
1730
1844
  out += '>' + text + '</a>';
1731
1845
  return out;
1732
1846
  }
1733
- image(href, title, text) {
1847
+ image({ href, title, text }) {
1734
1848
  const cleanHref = cleanUrl(href);
1735
1849
  if (cleanHref === null) {
1736
1850
  return text;
@@ -1743,8 +1857,8 @@ class _Renderer {
1743
1857
  out += '>';
1744
1858
  return out;
1745
1859
  }
1746
- text(text) {
1747
- return text;
1860
+ text(token) {
1861
+ return 'tokens' in token && token.tokens ? this.parser.parseInline(token.tokens) : token.text;
1748
1862
  }
1749
1863
  }
1750
1864
 
@@ -1754,28 +1868,28 @@ class _Renderer {
1754
1868
  */
1755
1869
  class _TextRenderer {
1756
1870
  // no need for block level renderers
1757
- strong(text) {
1871
+ strong({ text }) {
1758
1872
  return text;
1759
1873
  }
1760
- em(text) {
1874
+ em({ text }) {
1761
1875
  return text;
1762
1876
  }
1763
- codespan(text) {
1877
+ codespan({ text }) {
1764
1878
  return text;
1765
1879
  }
1766
- del(text) {
1880
+ del({ text }) {
1767
1881
  return text;
1768
1882
  }
1769
- html(text) {
1883
+ html({ text }) {
1770
1884
  return text;
1771
1885
  }
1772
- text(text) {
1886
+ text({ text }) {
1773
1887
  return text;
1774
1888
  }
1775
- link(href, title, text) {
1889
+ link({ text }) {
1776
1890
  return '' + text;
1777
1891
  }
1778
- image(href, title, text) {
1892
+ image({ text }) {
1779
1893
  return '' + text;
1780
1894
  }
1781
1895
  br() {
@@ -1795,6 +1909,7 @@ class _Parser {
1795
1909
  this.options.renderer = this.options.renderer || new _Renderer();
1796
1910
  this.renderer = this.options.renderer;
1797
1911
  this.renderer.options = this.options;
1912
+ this.renderer.parser = this;
1798
1913
  this.textRenderer = new _TextRenderer();
1799
1914
  }
1800
1915
  /**
@@ -1817,116 +1932,72 @@ class _Parser {
1817
1932
  parse(tokens, top = true) {
1818
1933
  let out = '';
1819
1934
  for (let i = 0; i < tokens.length; i++) {
1820
- const token = tokens[i];
1935
+ const anyToken = tokens[i];
1821
1936
  // Run any renderer extensions
1822
- if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {
1823
- const genericToken = token;
1937
+ if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[anyToken.type]) {
1938
+ const genericToken = anyToken;
1824
1939
  const ret = this.options.extensions.renderers[genericToken.type].call({ parser: this }, genericToken);
1825
1940
  if (ret !== false || !['space', 'hr', 'heading', 'code', 'table', 'blockquote', 'list', 'html', 'paragraph', 'text'].includes(genericToken.type)) {
1826
1941
  out += ret || '';
1827
1942
  continue;
1828
1943
  }
1829
1944
  }
1945
+ const token = anyToken;
1830
1946
  switch (token.type) {
1831
1947
  case 'space': {
1948
+ out += this.renderer.space(token);
1832
1949
  continue;
1833
1950
  }
1834
1951
  case 'hr': {
1835
- out += this.renderer.hr();
1952
+ out += this.renderer.hr(token);
1836
1953
  continue;
1837
1954
  }
1838
1955
  case 'heading': {
1839
- const headingToken = token;
1840
- out += this.renderer.heading(this.parseInline(headingToken.tokens), headingToken.depth, unescape(this.parseInline(headingToken.tokens, this.textRenderer)));
1956
+ out += this.renderer.heading(token);
1841
1957
  continue;
1842
1958
  }
1843
1959
  case 'code': {
1844
- const codeToken = token;
1845
- out += this.renderer.code(codeToken.text, codeToken.lang, !!codeToken.escaped);
1960
+ out += this.renderer.code(token);
1846
1961
  continue;
1847
1962
  }
1848
1963
  case 'table': {
1849
- const tableToken = token;
1850
- let header = '';
1851
- // header
1852
- let cell = '';
1853
- for (let j = 0; j < tableToken.header.length; j++) {
1854
- cell += this.renderer.tablecell(this.parseInline(tableToken.header[j].tokens), { header: true, align: tableToken.align[j] });
1855
- }
1856
- header += this.renderer.tablerow(cell);
1857
- let body = '';
1858
- for (let j = 0; j < tableToken.rows.length; j++) {
1859
- const row = tableToken.rows[j];
1860
- cell = '';
1861
- for (let k = 0; k < row.length; k++) {
1862
- cell += this.renderer.tablecell(this.parseInline(row[k].tokens), { header: false, align: tableToken.align[k] });
1863
- }
1864
- body += this.renderer.tablerow(cell);
1865
- }
1866
- out += this.renderer.table(header, body);
1964
+ out += this.renderer.table(token);
1867
1965
  continue;
1868
1966
  }
1869
1967
  case 'blockquote': {
1870
- const blockquoteToken = token;
1871
- const body = this.parse(blockquoteToken.tokens);
1872
- out += this.renderer.blockquote(body);
1968
+ out += this.renderer.blockquote(token);
1873
1969
  continue;
1874
1970
  }
1875
1971
  case 'list': {
1876
- const listToken = token;
1877
- const ordered = listToken.ordered;
1878
- const start = listToken.start;
1879
- const loose = listToken.loose;
1880
- let body = '';
1881
- for (let j = 0; j < listToken.items.length; j++) {
1882
- const item = listToken.items[j];
1883
- const checked = item.checked;
1884
- const task = item.task;
1885
- let itemBody = '';
1886
- if (item.task) {
1887
- const checkbox = this.renderer.checkbox(!!checked);
1888
- if (loose) {
1889
- if (item.tokens.length > 0 && item.tokens[0].type === 'paragraph') {
1890
- item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
1891
- if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {
1892
- item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text;
1893
- }
1894
- }
1895
- else {
1896
- item.tokens.unshift({
1897
- type: 'text',
1898
- text: checkbox + ' '
1899
- });
1900
- }
1901
- }
1902
- else {
1903
- itemBody += checkbox + ' ';
1904
- }
1905
- }
1906
- itemBody += this.parse(item.tokens, loose);
1907
- body += this.renderer.listitem(itemBody, task, !!checked);
1908
- }
1909
- out += this.renderer.list(body, ordered, start);
1972
+ out += this.renderer.list(token);
1910
1973
  continue;
1911
1974
  }
1912
1975
  case 'html': {
1913
- const htmlToken = token;
1914
- out += this.renderer.html(htmlToken.text, htmlToken.block);
1976
+ out += this.renderer.html(token);
1915
1977
  continue;
1916
1978
  }
1917
1979
  case 'paragraph': {
1918
- const paragraphToken = token;
1919
- out += this.renderer.paragraph(this.parseInline(paragraphToken.tokens));
1980
+ out += this.renderer.paragraph(token);
1920
1981
  continue;
1921
1982
  }
1922
1983
  case 'text': {
1923
1984
  let textToken = token;
1924
- let body = textToken.tokens ? this.parseInline(textToken.tokens) : textToken.text;
1985
+ let body = this.renderer.text(textToken);
1925
1986
  while (i + 1 < tokens.length && tokens[i + 1].type === 'text') {
1926
1987
  textToken = tokens[++i];
1927
- body += '\n' + (textToken.tokens ? this.parseInline(textToken.tokens) : textToken.text);
1988
+ body += '\n' + this.renderer.text(textToken);
1989
+ }
1990
+ if (top) {
1991
+ out += this.renderer.paragraph({
1992
+ type: 'paragraph',
1993
+ raw: body,
1994
+ text: body,
1995
+ tokens: [{ type: 'text', raw: body, text: body }]
1996
+ });
1997
+ }
1998
+ else {
1999
+ out += body;
1928
2000
  }
1929
- out += top ? this.renderer.paragraph(body) : body;
1930
2001
  continue;
1931
2002
  }
1932
2003
  default: {
@@ -1950,63 +2021,55 @@ class _Parser {
1950
2021
  renderer = renderer || this.renderer;
1951
2022
  let out = '';
1952
2023
  for (let i = 0; i < tokens.length; i++) {
1953
- const token = tokens[i];
2024
+ const anyToken = tokens[i];
1954
2025
  // Run any renderer extensions
1955
- if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {
1956
- const ret = this.options.extensions.renderers[token.type].call({ parser: this }, token);
1957
- if (ret !== false || !['escape', 'html', 'link', 'image', 'strong', 'em', 'codespan', 'br', 'del', 'text'].includes(token.type)) {
2026
+ if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[anyToken.type]) {
2027
+ const ret = this.options.extensions.renderers[anyToken.type].call({ parser: this }, anyToken);
2028
+ if (ret !== false || !['escape', 'html', 'link', 'image', 'strong', 'em', 'codespan', 'br', 'del', 'text'].includes(anyToken.type)) {
1958
2029
  out += ret || '';
1959
2030
  continue;
1960
2031
  }
1961
2032
  }
2033
+ const token = anyToken;
1962
2034
  switch (token.type) {
1963
2035
  case 'escape': {
1964
- const escapeToken = token;
1965
- out += renderer.text(escapeToken.text);
2036
+ out += renderer.text(token);
1966
2037
  break;
1967
2038
  }
1968
2039
  case 'html': {
1969
- const tagToken = token;
1970
- out += renderer.html(tagToken.text);
2040
+ out += renderer.html(token);
1971
2041
  break;
1972
2042
  }
1973
2043
  case 'link': {
1974
- const linkToken = token;
1975
- out += renderer.link(linkToken.href, linkToken.title, this.parseInline(linkToken.tokens, renderer));
2044
+ out += renderer.link(token);
1976
2045
  break;
1977
2046
  }
1978
2047
  case 'image': {
1979
- const imageToken = token;
1980
- out += renderer.image(imageToken.href, imageToken.title, imageToken.text);
2048
+ out += renderer.image(token);
1981
2049
  break;
1982
2050
  }
1983
2051
  case 'strong': {
1984
- const strongToken = token;
1985
- out += renderer.strong(this.parseInline(strongToken.tokens, renderer));
2052
+ out += renderer.strong(token);
1986
2053
  break;
1987
2054
  }
1988
2055
  case 'em': {
1989
- const emToken = token;
1990
- out += renderer.em(this.parseInline(emToken.tokens, renderer));
2056
+ out += renderer.em(token);
1991
2057
  break;
1992
2058
  }
1993
2059
  case 'codespan': {
1994
- const codespanToken = token;
1995
- out += renderer.codespan(codespanToken.text);
2060
+ out += renderer.codespan(token);
1996
2061
  break;
1997
2062
  }
1998
2063
  case 'br': {
1999
- out += renderer.br();
2064
+ out += renderer.br(token);
2000
2065
  break;
2001
2066
  }
2002
2067
  case 'del': {
2003
- const delToken = token;
2004
- out += renderer.del(this.parseInline(delToken.tokens, renderer));
2068
+ out += renderer.del(token);
2005
2069
  break;
2006
2070
  }
2007
2071
  case 'text': {
2008
- const textToken = token;
2009
- out += renderer.text(textToken.text);
2072
+ out += renderer.text(token);
2010
2073
  break;
2011
2074
  }
2012
2075
  default: {
@@ -2182,15 +2245,19 @@ class Marked {
2182
2245
  if (!(prop in renderer)) {
2183
2246
  throw new Error(`renderer '${prop}' does not exist`);
2184
2247
  }
2185
- if (prop === 'options') {
2248
+ if (['options', 'parser'].includes(prop)) {
2186
2249
  // ignore options property
2187
2250
  continue;
2188
2251
  }
2189
2252
  const rendererProp = prop;
2190
- const rendererFunc = pack.renderer[rendererProp];
2253
+ let rendererFunc = pack.renderer[rendererProp];
2191
2254
  const prevRenderer = renderer[rendererProp];
2192
2255
  // Replace renderer with func to run extension, but fall back if false
2193
2256
  renderer[rendererProp] = (...args) => {
2257
+ if (!pack.useNewRenderer) {
2258
+ // TODO: Remove this in next major version
2259
+ rendererFunc = this.#convertRendererFunction(rendererFunc, rendererProp, renderer);
2260
+ }
2194
2261
  let ret = rendererFunc.apply(renderer, args);
2195
2262
  if (ret === false) {
2196
2263
  ret = prevRenderer.apply(renderer, args);
@@ -2281,6 +2348,215 @@ class Marked {
2281
2348
  });
2282
2349
  return this;
2283
2350
  }
2351
+ // TODO: Remove this in next major release
2352
+ #convertRendererFunction(func, prop, renderer) {
2353
+ switch (prop) {
2354
+ case 'heading':
2355
+ return function (token) {
2356
+ if (!token.type || token.type !== prop) {
2357
+ // @ts-ignore
2358
+ // eslint-disable-next-line prefer-rest-params
2359
+ return func.apply(this, arguments);
2360
+ }
2361
+ return func(renderer.parser.parseInline(token.tokens), token.depth, unescape(renderer.parser.parseInline(token.tokens, renderer.parser.textRenderer)));
2362
+ };
2363
+ case 'code':
2364
+ return function (token) {
2365
+ if (!token.type || token.type !== prop) {
2366
+ // @ts-ignore
2367
+ // eslint-disable-next-line prefer-rest-params
2368
+ return func.apply(this, arguments);
2369
+ }
2370
+ return func(token.text, token.lang, !!token.escaped);
2371
+ };
2372
+ case 'table':
2373
+ return function (token) {
2374
+ if (!token.type || token.type !== prop) {
2375
+ // @ts-ignore
2376
+ // eslint-disable-next-line prefer-rest-params
2377
+ return func.apply(this, arguments);
2378
+ }
2379
+ let header = '';
2380
+ // header
2381
+ let cell = '';
2382
+ for (let j = 0; j < token.header.length; j++) {
2383
+ cell += this.tablecell({
2384
+ text: token.header[j].text,
2385
+ tokens: token.header[j].tokens,
2386
+ header: true,
2387
+ align: token.align[j]
2388
+ });
2389
+ }
2390
+ header += this.tablerow({ text: cell });
2391
+ let body = '';
2392
+ for (let j = 0; j < token.rows.length; j++) {
2393
+ const row = token.rows[j];
2394
+ cell = '';
2395
+ for (let k = 0; k < row.length; k++) {
2396
+ cell += this.tablecell({
2397
+ text: row[k].text,
2398
+ tokens: row[k].tokens,
2399
+ header: false,
2400
+ align: token.align[k]
2401
+ });
2402
+ }
2403
+ body += this.tablerow({ text: cell });
2404
+ }
2405
+ return func(header, body);
2406
+ };
2407
+ case 'blockquote':
2408
+ return function (token) {
2409
+ if (!token.type || token.type !== prop) {
2410
+ // @ts-ignore
2411
+ // eslint-disable-next-line prefer-rest-params
2412
+ return func.apply(this, arguments);
2413
+ }
2414
+ const body = this.parser.parse(token.tokens);
2415
+ return func(body);
2416
+ };
2417
+ case 'list':
2418
+ return function (token) {
2419
+ if (!token.type || token.type !== prop) {
2420
+ // @ts-ignore
2421
+ // eslint-disable-next-line prefer-rest-params
2422
+ return func.apply(this, arguments);
2423
+ }
2424
+ const ordered = token.ordered;
2425
+ const start = token.start;
2426
+ const loose = token.loose;
2427
+ let body = '';
2428
+ for (let j = 0; j < token.items.length; j++) {
2429
+ const item = token.items[j];
2430
+ const checked = item.checked;
2431
+ const task = item.task;
2432
+ let itemBody = '';
2433
+ if (item.task) {
2434
+ const checkbox = this.checkbox({ checked: !!checked });
2435
+ if (loose) {
2436
+ if (item.tokens.length > 0 && item.tokens[0].type === 'paragraph') {
2437
+ item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
2438
+ if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {
2439
+ item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text;
2440
+ }
2441
+ }
2442
+ else {
2443
+ item.tokens.unshift({
2444
+ type: 'text',
2445
+ text: checkbox + ' '
2446
+ });
2447
+ }
2448
+ }
2449
+ else {
2450
+ itemBody += checkbox + ' ';
2451
+ }
2452
+ }
2453
+ itemBody += this.parser.parse(item.tokens, loose);
2454
+ body += this.listitem({
2455
+ type: 'list_item',
2456
+ raw: itemBody,
2457
+ text: itemBody,
2458
+ task,
2459
+ checked: !!checked,
2460
+ loose,
2461
+ tokens: item.tokens
2462
+ });
2463
+ }
2464
+ return func(body, ordered, start);
2465
+ };
2466
+ case 'html':
2467
+ return function (token) {
2468
+ if (!token.type || token.type !== prop) {
2469
+ // @ts-ignore
2470
+ // eslint-disable-next-line prefer-rest-params
2471
+ return func.apply(this, arguments);
2472
+ }
2473
+ return func(token.text, token.block);
2474
+ };
2475
+ case 'paragraph':
2476
+ return function (token) {
2477
+ if (!token.type || token.type !== prop) {
2478
+ // @ts-ignore
2479
+ // eslint-disable-next-line prefer-rest-params
2480
+ return func.apply(this, arguments);
2481
+ }
2482
+ return func(this.parser.parseInline(token.tokens));
2483
+ };
2484
+ case 'escape':
2485
+ return function (token) {
2486
+ if (!token.type || token.type !== prop) {
2487
+ // @ts-ignore
2488
+ // eslint-disable-next-line prefer-rest-params
2489
+ return func.apply(this, arguments);
2490
+ }
2491
+ return func(token.text);
2492
+ };
2493
+ case 'link':
2494
+ return function (token) {
2495
+ if (!token.type || token.type !== prop) {
2496
+ // @ts-ignore
2497
+ // eslint-disable-next-line prefer-rest-params
2498
+ return func.apply(this, arguments);
2499
+ }
2500
+ return func(token.href, token.title, this.parser.parseInline(token.tokens));
2501
+ };
2502
+ case 'image':
2503
+ return function (token) {
2504
+ if (!token.type || token.type !== prop) {
2505
+ // @ts-ignore
2506
+ // eslint-disable-next-line prefer-rest-params
2507
+ return func.apply(this, arguments);
2508
+ }
2509
+ return func(token.href, token.title, token.text);
2510
+ };
2511
+ case 'strong':
2512
+ return function (token) {
2513
+ if (!token.type || token.type !== prop) {
2514
+ // @ts-ignore
2515
+ // eslint-disable-next-line prefer-rest-params
2516
+ return func.apply(this, arguments);
2517
+ }
2518
+ return func(this.parser.parseInline(token.tokens));
2519
+ };
2520
+ case 'em':
2521
+ return function (token) {
2522
+ if (!token.type || token.type !== prop) {
2523
+ // @ts-ignore
2524
+ // eslint-disable-next-line prefer-rest-params
2525
+ return func.apply(this, arguments);
2526
+ }
2527
+ return func(this.parser.parseInline(token.tokens));
2528
+ };
2529
+ case 'codespan':
2530
+ return function (token) {
2531
+ if (!token.type || token.type !== prop) {
2532
+ // @ts-ignore
2533
+ // eslint-disable-next-line prefer-rest-params
2534
+ return func.apply(this, arguments);
2535
+ }
2536
+ return func(token.text);
2537
+ };
2538
+ case 'del':
2539
+ return function (token) {
2540
+ if (!token.type || token.type !== prop) {
2541
+ // @ts-ignore
2542
+ // eslint-disable-next-line prefer-rest-params
2543
+ return func.apply(this, arguments);
2544
+ }
2545
+ return func(this.parser.parseInline(token.tokens));
2546
+ };
2547
+ case 'text':
2548
+ return function (token) {
2549
+ if (!token.type || token.type !== prop) {
2550
+ // @ts-ignore
2551
+ // eslint-disable-next-line prefer-rest-params
2552
+ return func.apply(this, arguments);
2553
+ }
2554
+ return func(token.text);
2555
+ };
2556
+ // do nothing
2557
+ }
2558
+ return func;
2559
+ }
2284
2560
  setOptions(opt) {
2285
2561
  this.defaults = { ...this.defaults, ...opt };
2286
2562
  return this;