marked 15.0.0 → 15.0.2

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 v15.0.0 - a markdown parser
2
+ * marked v15.0.2 - a markdown parser
3
3
  * Copyright (c) 2011-2024, Christopher Jeffrey. (MIT Licensed)
4
4
  * https://github.com/markedjs/marked
5
5
  */
@@ -255,7 +255,7 @@ const inlineCode = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/;
255
255
  const br = /^( {2,}|\\)\n(?!\s*$)/;
256
256
  const inlineText = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/;
257
257
  // list of unicode punctuation marks, plus any missing characters from CommonMark spec
258
- const _punctuation = '\\p{P}\\p{S}';
258
+ const _punctuation = /\p{P}\p{S}/u;
259
259
  const punctuation = edit(/^((?![*_])[\spunctuation])/, 'u')
260
260
  .replace(/punctuation/g, _punctuation).getRegex();
261
261
  // sequences em should skip over [title](link), `code`, <html>
@@ -448,7 +448,7 @@ function splitCells(tableRow, count) {
448
448
  if (!cells[0].trim()) {
449
449
  cells.shift();
450
450
  }
451
- if (cells.length > 0 && !cells[cells.length - 1].trim()) {
451
+ if (cells.length > 0 && !cells.at(-1)?.trim()) {
452
452
  cells.pop();
453
453
  }
454
454
  if (count) {
@@ -685,7 +685,7 @@ class _Tokenizer {
685
685
  if (lines.length === 0) {
686
686
  break;
687
687
  }
688
- const lastToken = tokens[tokens.length - 1];
688
+ const lastToken = tokens.at(-1);
689
689
  if (lastToken?.type === 'code') {
690
690
  // blockquote continuation cannot be preceded by a code block
691
691
  break;
@@ -708,7 +708,7 @@ class _Tokenizer {
708
708
  tokens[tokens.length - 1] = newToken;
709
709
  raw = raw.substring(0, raw.length - lastToken.raw.length) + newToken.raw;
710
710
  text = text.substring(0, text.length - oldToken.raw.length) + newToken.raw;
711
- lines = newText.substring(tokens[tokens.length - 1].raw.length).split('\n');
711
+ lines = newText.substring(tokens.at(-1).raw.length).split('\n');
712
712
  continue;
713
713
  }
714
714
  }
@@ -876,8 +876,11 @@ class _Tokenizer {
876
876
  list.raw += raw;
877
877
  }
878
878
  // Do not consume newlines at end of final item. Alternatively, make itemRegex *start* with any newlines to simplify/speed up endsWithBlankLine logic
879
- list.items[list.items.length - 1].raw = list.items[list.items.length - 1].raw.trimEnd();
880
- list.items[list.items.length - 1].text = list.items[list.items.length - 1].text.trimEnd();
879
+ const lastItem = list.items.at(-1);
880
+ if (lastItem) {
881
+ lastItem.raw = lastItem.raw.trimEnd();
882
+ lastItem.text = lastItem.text.trimEnd();
883
+ }
881
884
  list.raw = list.raw.trimEnd();
882
885
  // Item child tokens handled here at end because we needed to have the final item to trim it first
883
886
  for (let i = 0; i < list.items.length; i++) {
@@ -938,7 +941,7 @@ class _Tokenizer {
938
941
  }
939
942
  const headers = splitCells(cap[1]);
940
943
  const aligns = cap[2].replace(this.rules.other.tableAlignChars, '').split('|');
941
- const rows = cap[3] && cap[3].trim() ? cap[3].replace(this.rules.other.tableRowBlankLine, '').split('\n') : [];
944
+ const rows = cap[3]?.trim() ? cap[3].replace(this.rules.other.tableRowBlankLine, '').split('\n') : [];
942
945
  const item = {
943
946
  type: 'table',
944
947
  raw: cap[0],
@@ -1374,8 +1377,7 @@ class _Lexer {
1374
1377
  * Preprocessing
1375
1378
  */
1376
1379
  lex(src) {
1377
- src = src
1378
- .replace(other.carriageReturn, '\n');
1380
+ src = src.replace(other.carriageReturn, '\n');
1379
1381
  this.blockTokens(src, this.tokens);
1380
1382
  for (let i = 0; i < this.inlineQueue.length; i++) {
1381
1383
  const next = this.inlineQueue[i];
@@ -1388,29 +1390,26 @@ class _Lexer {
1388
1390
  if (this.options.pedantic) {
1389
1391
  src = src.replace(other.tabCharGlobal, ' ').replace(other.spaceLine, '');
1390
1392
  }
1391
- let token;
1392
- let lastToken;
1393
- let cutSrc;
1394
1393
  while (src) {
1395
- if (this.options.extensions
1396
- && this.options.extensions.block
1397
- && this.options.extensions.block.some((extTokenizer) => {
1398
- if (token = extTokenizer.call({ lexer: this }, src, tokens)) {
1399
- src = src.substring(token.raw.length);
1400
- tokens.push(token);
1401
- return true;
1402
- }
1403
- return false;
1404
- })) {
1394
+ let token;
1395
+ if (this.options.extensions?.block?.some((extTokenizer) => {
1396
+ if (token = extTokenizer.call({ lexer: this }, src, tokens)) {
1397
+ src = src.substring(token.raw.length);
1398
+ tokens.push(token);
1399
+ return true;
1400
+ }
1401
+ return false;
1402
+ })) {
1405
1403
  continue;
1406
1404
  }
1407
1405
  // newline
1408
1406
  if (token = this.tokenizer.space(src)) {
1409
1407
  src = src.substring(token.raw.length);
1410
- if (token.raw.length === 1 && tokens.length > 0) {
1408
+ const lastToken = tokens.at(-1);
1409
+ if (token.raw.length === 1 && lastToken !== undefined) {
1411
1410
  // if there's a single \n as a spacer, it's terminating the last line,
1412
1411
  // so move it there so that we don't get unnecessary paragraph tags
1413
- tokens[tokens.length - 1].raw += '\n';
1412
+ lastToken.raw += '\n';
1414
1413
  }
1415
1414
  else {
1416
1415
  tokens.push(token);
@@ -1420,12 +1419,12 @@ class _Lexer {
1420
1419
  // code
1421
1420
  if (token = this.tokenizer.code(src)) {
1422
1421
  src = src.substring(token.raw.length);
1423
- lastToken = tokens[tokens.length - 1];
1422
+ const lastToken = tokens.at(-1);
1424
1423
  // An indented code block cannot interrupt a paragraph.
1425
- if (lastToken && (lastToken.type === 'paragraph' || lastToken.type === 'text')) {
1424
+ if (lastToken?.type === 'paragraph' || lastToken?.type === 'text') {
1426
1425
  lastToken.raw += '\n' + token.raw;
1427
1426
  lastToken.text += '\n' + token.text;
1428
- this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
1427
+ this.inlineQueue.at(-1).src = lastToken.text;
1429
1428
  }
1430
1429
  else {
1431
1430
  tokens.push(token);
@@ -1471,11 +1470,11 @@ class _Lexer {
1471
1470
  // def
1472
1471
  if (token = this.tokenizer.def(src)) {
1473
1472
  src = src.substring(token.raw.length);
1474
- lastToken = tokens[tokens.length - 1];
1475
- if (lastToken && (lastToken.type === 'paragraph' || lastToken.type === 'text')) {
1473
+ const lastToken = tokens.at(-1);
1474
+ if (lastToken?.type === 'paragraph' || lastToken?.type === 'text') {
1476
1475
  lastToken.raw += '\n' + token.raw;
1477
1476
  lastToken.text += '\n' + token.raw;
1478
- this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
1477
+ this.inlineQueue.at(-1).src = lastToken.text;
1479
1478
  }
1480
1479
  else if (!this.tokens.links[token.tag]) {
1481
1480
  this.tokens.links[token.tag] = {
@@ -1499,8 +1498,8 @@ class _Lexer {
1499
1498
  }
1500
1499
  // top-level paragraph
1501
1500
  // prevent paragraph consuming extensions by clipping 'src' to extension start
1502
- cutSrc = src;
1503
- if (this.options.extensions && this.options.extensions.startBlock) {
1501
+ let cutSrc = src;
1502
+ if (this.options.extensions?.startBlock) {
1504
1503
  let startIndex = Infinity;
1505
1504
  const tempSrc = src.slice(1);
1506
1505
  let tempStart;
@@ -1515,29 +1514,29 @@ class _Lexer {
1515
1514
  }
1516
1515
  }
1517
1516
  if (this.state.top && (token = this.tokenizer.paragraph(cutSrc))) {
1518
- lastToken = tokens[tokens.length - 1];
1517
+ const lastToken = tokens.at(-1);
1519
1518
  if (lastParagraphClipped && lastToken?.type === 'paragraph') {
1520
1519
  lastToken.raw += '\n' + token.raw;
1521
1520
  lastToken.text += '\n' + token.text;
1522
1521
  this.inlineQueue.pop();
1523
- this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
1522
+ this.inlineQueue.at(-1).src = lastToken.text;
1524
1523
  }
1525
1524
  else {
1526
1525
  tokens.push(token);
1527
1526
  }
1528
- lastParagraphClipped = (cutSrc.length !== src.length);
1527
+ lastParagraphClipped = cutSrc.length !== src.length;
1529
1528
  src = src.substring(token.raw.length);
1530
1529
  continue;
1531
1530
  }
1532
1531
  // text
1533
1532
  if (token = this.tokenizer.text(src)) {
1534
1533
  src = src.substring(token.raw.length);
1535
- lastToken = tokens[tokens.length - 1];
1536
- if (lastToken && lastToken.type === 'text') {
1534
+ const lastToken = tokens.at(-1);
1535
+ if (lastToken?.type === 'text') {
1537
1536
  lastToken.raw += '\n' + token.raw;
1538
1537
  lastToken.text += '\n' + token.text;
1539
1538
  this.inlineQueue.pop();
1540
- this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
1539
+ this.inlineQueue.at(-1).src = lastToken.text;
1541
1540
  }
1542
1541
  else {
1543
1542
  tokens.push(token);
@@ -1566,18 +1565,18 @@ class _Lexer {
1566
1565
  * Lexing/Compiling
1567
1566
  */
1568
1567
  inlineTokens(src, tokens = []) {
1569
- let token, lastToken, cutSrc;
1570
1568
  // String with links masked to avoid interference with em and strong
1571
1569
  let maskedSrc = src;
1572
- let match;
1573
- let keepPrevChar, prevChar;
1570
+ let match = null;
1574
1571
  // Mask out reflinks
1575
1572
  if (this.tokens.links) {
1576
1573
  const links = Object.keys(this.tokens.links);
1577
1574
  if (links.length > 0) {
1578
1575
  while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {
1579
1576
  if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) {
1580
- maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);
1577
+ maskedSrc = maskedSrc.slice(0, match.index)
1578
+ + '[' + 'a'.repeat(match[0].length - 2) + ']'
1579
+ + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);
1581
1580
  }
1582
1581
  }
1583
1582
  }
@@ -1590,22 +1589,23 @@ class _Lexer {
1590
1589
  while ((match = this.tokenizer.rules.inline.anyPunctuation.exec(maskedSrc)) != null) {
1591
1590
  maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);
1592
1591
  }
1592
+ let keepPrevChar = false;
1593
+ let prevChar = '';
1593
1594
  while (src) {
1594
1595
  if (!keepPrevChar) {
1595
1596
  prevChar = '';
1596
1597
  }
1597
1598
  keepPrevChar = false;
1599
+ let token;
1598
1600
  // extensions
1599
- if (this.options.extensions
1600
- && this.options.extensions.inline
1601
- && this.options.extensions.inline.some((extTokenizer) => {
1602
- if (token = extTokenizer.call({ lexer: this }, src, tokens)) {
1603
- src = src.substring(token.raw.length);
1604
- tokens.push(token);
1605
- return true;
1606
- }
1607
- return false;
1608
- })) {
1601
+ if (this.options.extensions?.inline?.some((extTokenizer) => {
1602
+ if (token = extTokenizer.call({ lexer: this }, src, tokens)) {
1603
+ src = src.substring(token.raw.length);
1604
+ tokens.push(token);
1605
+ return true;
1606
+ }
1607
+ return false;
1608
+ })) {
1609
1609
  continue;
1610
1610
  }
1611
1611
  // escape
@@ -1617,7 +1617,6 @@ class _Lexer {
1617
1617
  // tag
1618
1618
  if (token = this.tokenizer.tag(src)) {
1619
1619
  src = src.substring(token.raw.length);
1620
- lastToken = tokens[tokens.length - 1];
1621
1620
  tokens.push(token);
1622
1621
  continue;
1623
1622
  }
@@ -1630,8 +1629,8 @@ class _Lexer {
1630
1629
  // reflink, nolink
1631
1630
  if (token = this.tokenizer.reflink(src, this.tokens.links)) {
1632
1631
  src = src.substring(token.raw.length);
1633
- lastToken = tokens[tokens.length - 1];
1634
- if (lastToken && token.type === 'text' && lastToken.type === 'text') {
1632
+ const lastToken = tokens.at(-1);
1633
+ if (token.type === 'text' && lastToken?.type === 'text') {
1635
1634
  lastToken.raw += token.raw;
1636
1635
  lastToken.text += token.text;
1637
1636
  }
@@ -1678,8 +1677,8 @@ class _Lexer {
1678
1677
  }
1679
1678
  // text
1680
1679
  // prevent inlineText consuming extensions by clipping 'src' to extension start
1681
- cutSrc = src;
1682
- if (this.options.extensions && this.options.extensions.startInline) {
1680
+ let cutSrc = src;
1681
+ if (this.options.extensions?.startInline) {
1683
1682
  let startIndex = Infinity;
1684
1683
  const tempSrc = src.slice(1);
1685
1684
  let tempStart;
@@ -1699,8 +1698,8 @@ class _Lexer {
1699
1698
  prevChar = token.raw.slice(-1);
1700
1699
  }
1701
1700
  keepPrevChar = true;
1702
- lastToken = tokens[tokens.length - 1];
1703
- if (lastToken && lastToken.type === 'text') {
1701
+ const lastToken = tokens.at(-1);
1702
+ if (lastToken?.type === 'text') {
1704
1703
  lastToken.raw += token.raw;
1705
1704
  lastToken.text += token.text;
1706
1705
  }
@@ -1780,7 +1779,7 @@ class _Renderer {
1780
1779
  if (item.task) {
1781
1780
  const checkbox = this.checkbox({ checked: !!item.checked });
1782
1781
  if (item.loose) {
1783
- if (item.tokens.length > 0 && item.tokens[0].type === 'paragraph') {
1782
+ if (item.tokens[0]?.type === 'paragraph') {
1784
1783
  item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
1785
1784
  if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {
1786
1785
  item.tokens[0].tokens[0].text = checkbox + ' ' + escape(item.tokens[0].tokens[0].text);
@@ -1972,7 +1971,7 @@ class _Parser {
1972
1971
  for (let i = 0; i < tokens.length; i++) {
1973
1972
  const anyToken = tokens[i];
1974
1973
  // Run any renderer extensions
1975
- if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[anyToken.type]) {
1974
+ if (this.options.extensions?.renderers?.[anyToken.type]) {
1976
1975
  const genericToken = anyToken;
1977
1976
  const ret = this.options.extensions.renderers[genericToken.type].call({ parser: this }, genericToken);
1978
1977
  if (ret !== false || !['space', 'hr', 'heading', 'code', 'table', 'blockquote', 'list', 'html', 'paragraph', 'text'].includes(genericToken.type)) {
@@ -2055,13 +2054,12 @@ class _Parser {
2055
2054
  /**
2056
2055
  * Parse Inline Tokens
2057
2056
  */
2058
- parseInline(tokens, renderer) {
2059
- renderer = renderer || this.renderer;
2057
+ parseInline(tokens, renderer = this.renderer) {
2060
2058
  let out = '';
2061
2059
  for (let i = 0; i < tokens.length; i++) {
2062
2060
  const anyToken = tokens[i];
2063
2061
  // Run any renderer extensions
2064
- if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[anyToken.type]) {
2062
+ if (this.options.extensions?.renderers?.[anyToken.type]) {
2065
2063
  const ret = this.options.extensions.renderers[anyToken.type].call({ parser: this }, anyToken);
2066
2064
  if (ret !== false || !['escape', 'html', 'link', 'image', 'strong', 'em', 'codespan', 'br', 'del', 'text'].includes(anyToken.type)) {
2067
2065
  out += ret || '';