@orkestrel/markdown 0.0.8 → 0.0.10

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.
@@ -544,152 +544,6 @@ function parseBlocks(lines, depth) {
544
544
  return blocks;
545
545
  }
546
546
  /**
547
- * Collects a GFM table starting at a header row, parsing the header, the
548
- * alignment row, and every contiguous body row that follows.
549
- *
550
- * @param lines - The markdown lines to scan.
551
- * @param start - The index of the header row.
552
- * @returns The parsed table node and the index of the first line after it.
553
- *
554
- * @example
555
- * ```ts
556
- * collectTable(['| a |', '| - |'], 0) // { node: { element: 'table', ... }, next: 2 }
557
- * ```
558
- */
559
- function collectTable(lines, start) {
560
- const headerCells = splitTableRow(lines[start] ?? "");
561
- const columns = headerCells.length;
562
- const header = headerCells.map((cell) => parseInline(cell.trim()));
563
- const align = delimiterToAlignments(lines[start + 1] ?? "");
564
- const padded = [];
565
- for (let column = 0; column < columns; column += 1) padded.push(align[column] ?? null);
566
- const rows = [];
567
- let index = start + 2;
568
- while (index < lines.length && !isBlankLine(lines[index] ?? "") && (lines[index] ?? "").includes("|")) {
569
- const cells = splitTableRow(lines[index] ?? "");
570
- const row = [];
571
- for (let column = 0; column < columns; column += 1) row.push(parseInline((cells[column] ?? "").trim()));
572
- rows.push(row);
573
- index += 1;
574
- }
575
- return {
576
- node: {
577
- element: "table",
578
- header,
579
- rows,
580
- align: padded
581
- },
582
- next: index
583
- };
584
- }
585
- /**
586
- * Collects a list starting at the first item, gathering sibling items at the
587
- * same indent/ordering and recursing into each item's own block content.
588
- *
589
- * @param lines - The markdown lines to scan.
590
- * @param start - The index of the first list item.
591
- * @param depth - The current recursion depth (each item recurses at `depth + 1`).
592
- * @returns The parsed list node and the index of the first line after it.
593
- *
594
- * @example
595
- * ```ts
596
- * collectList(['- item'], 0, 0) // { node: { element: 'list', ... }, next: 1 }
597
- * ```
598
- */
599
- function collectList(lines, start, depth) {
600
- const first = extractListItem(lines[start] ?? "");
601
- const ordered = first?.ordered ?? false;
602
- const startOrdinal = first?.start ?? 1;
603
- const topIndent = first?.indent ?? 0;
604
- const items = [];
605
- const chain = [];
606
- let nested = true;
607
- for (let cursor = start; cursor < lines.length; cursor += 1) {
608
- const parsed = extractListItem(lines[cursor] ?? "");
609
- const previous = chain[chain.length - 1];
610
- if (parsed === void 0 || previous !== void 0 && (previous.content.length > 0 || parsed.indent !== previous.marker)) {
611
- nested = false;
612
- break;
613
- }
614
- chain.push(parsed);
615
- }
616
- const remaining = 64 - depth;
617
- if (nested && remaining > 0 && chain.length > remaining) {
618
- const terminal = chain[remaining - 1];
619
- if (terminal !== void 0) {
620
- const source = [terminal.content];
621
- for (let cursor = start + remaining; cursor < lines.length; cursor += 1) source.push((lines[cursor] ?? "").slice(terminal.marker));
622
- let children = [{
623
- element: "paragraph",
624
- children: [{
625
- element: "text",
626
- value: source.join("\n")
627
- }]
628
- }];
629
- let node;
630
- for (let cursor = remaining - 1; cursor >= 0; cursor -= 1) {
631
- const parsed = chain[cursor];
632
- if (parsed === void 0) continue;
633
- node = {
634
- element: "list",
635
- ordered: parsed.ordered,
636
- start: parsed.start,
637
- items: [{
638
- element: "listItem",
639
- children
640
- }]
641
- };
642
- children = [node];
643
- }
644
- if (node !== void 0) return {
645
- node,
646
- next: lines.length
647
- };
648
- }
649
- }
650
- let index = start;
651
- while (index < lines.length) {
652
- const parsed = extractListItem(lines[index] ?? "");
653
- if (!parsed || parsed.indent > topIndent || parsed.ordered !== ordered) break;
654
- const itemLines = [parsed.content];
655
- const continuation = parsed.marker;
656
- index += 1;
657
- while (index < lines.length) {
658
- const next = lines[index] ?? "";
659
- if (isBlankLine(next)) {
660
- const after = lines[index + 1] ?? "";
661
- if (index + 1 < lines.length && !isBlankLine(after) && countIndent(after) >= continuation) {
662
- itemLines.push("");
663
- index += 1;
664
- continue;
665
- }
666
- break;
667
- }
668
- if (countIndent(next) >= continuation) {
669
- itemLines.push(next.slice(continuation));
670
- index += 1;
671
- continue;
672
- }
673
- if (extractListItem(next) || startsBlock(lines, index)) break;
674
- itemLines.push(next.trim());
675
- index += 1;
676
- }
677
- items.push({
678
- element: "listItem",
679
- children: parseBlocks(itemLines, depth + 1)
680
- });
681
- }
682
- return {
683
- node: {
684
- element: "list",
685
- ordered,
686
- start: startOrdinal,
687
- items
688
- },
689
- next: index
690
- };
691
- }
692
- /**
693
547
  * Parses a markdown string into a typed {@link MarkdownDocument} AST via the
694
548
  * block phase.
695
549
  *
@@ -1644,6 +1498,152 @@ function scanInline(source, from, to, depth = 0) {
1644
1498
  return nodes;
1645
1499
  }
1646
1500
  /**
1501
+ * Collects a GFM table starting at a header row, parsing the header, the
1502
+ * alignment row, and every contiguous body row that follows.
1503
+ *
1504
+ * @param lines - The markdown lines to scan.
1505
+ * @param start - The index of the header row.
1506
+ * @returns The parsed table node and the index of the first line after it.
1507
+ *
1508
+ * @example
1509
+ * ```ts
1510
+ * collectTable(['| a |', '| - |'], 0) // { node: { element: 'table', ... }, next: 2 }
1511
+ * ```
1512
+ */
1513
+ function collectTable(lines, start) {
1514
+ const headerCells = splitTableRow(lines[start] ?? "");
1515
+ const columns = headerCells.length;
1516
+ const header = headerCells.map((cell) => parseInline(cell.trim()));
1517
+ const align = delimiterToAlignments(lines[start + 1] ?? "");
1518
+ const padded = [];
1519
+ for (let column = 0; column < columns; column += 1) padded.push(align[column] ?? null);
1520
+ const rows = [];
1521
+ let index = start + 2;
1522
+ while (index < lines.length && !isBlankLine(lines[index] ?? "") && (lines[index] ?? "").includes("|")) {
1523
+ const cells = splitTableRow(lines[index] ?? "");
1524
+ const row = [];
1525
+ for (let column = 0; column < columns; column += 1) row.push(parseInline((cells[column] ?? "").trim()));
1526
+ rows.push(row);
1527
+ index += 1;
1528
+ }
1529
+ return {
1530
+ node: {
1531
+ element: "table",
1532
+ header,
1533
+ rows,
1534
+ align: padded
1535
+ },
1536
+ next: index
1537
+ };
1538
+ }
1539
+ /**
1540
+ * Collects a list starting at the first item, gathering sibling items at the
1541
+ * same indent/ordering and recursing into each item's own block content.
1542
+ *
1543
+ * @param lines - The markdown lines to scan.
1544
+ * @param start - The index of the first list item.
1545
+ * @param depth - The current recursion depth (each item recurses at `depth + 1`).
1546
+ * @returns The parsed list node and the index of the first line after it.
1547
+ *
1548
+ * @example
1549
+ * ```ts
1550
+ * collectList(['- item'], 0, 0) // { node: { element: 'list', ... }, next: 1 }
1551
+ * ```
1552
+ */
1553
+ function collectList(lines, start, depth) {
1554
+ const first = extractListItem(lines[start] ?? "");
1555
+ const ordered = first?.ordered ?? false;
1556
+ const startOrdinal = first?.start ?? 1;
1557
+ const topIndent = first?.indent ?? 0;
1558
+ const items = [];
1559
+ const chain = [];
1560
+ let nested = true;
1561
+ for (let cursor = start; cursor < lines.length; cursor += 1) {
1562
+ const parsed = extractListItem(lines[cursor] ?? "");
1563
+ const previous = chain[chain.length - 1];
1564
+ if (parsed === void 0 || previous !== void 0 && (previous.content.length > 0 || parsed.indent !== previous.marker)) {
1565
+ nested = false;
1566
+ break;
1567
+ }
1568
+ chain.push(parsed);
1569
+ }
1570
+ const remaining = 64 - depth;
1571
+ if (nested && remaining > 0 && chain.length > remaining) {
1572
+ const terminal = chain[remaining - 1];
1573
+ if (terminal !== void 0) {
1574
+ const source = [terminal.content];
1575
+ for (let cursor = start + remaining; cursor < lines.length; cursor += 1) source.push((lines[cursor] ?? "").slice(terminal.marker));
1576
+ let children = [{
1577
+ element: "paragraph",
1578
+ children: [{
1579
+ element: "text",
1580
+ value: source.join("\n")
1581
+ }]
1582
+ }];
1583
+ let node;
1584
+ for (let cursor = remaining - 1; cursor >= 0; cursor -= 1) {
1585
+ const parsed = chain[cursor];
1586
+ if (parsed === void 0) continue;
1587
+ node = {
1588
+ element: "list",
1589
+ ordered: parsed.ordered,
1590
+ start: parsed.start,
1591
+ items: [{
1592
+ element: "listItem",
1593
+ children
1594
+ }]
1595
+ };
1596
+ children = [node];
1597
+ }
1598
+ if (node !== void 0) return {
1599
+ node,
1600
+ next: lines.length
1601
+ };
1602
+ }
1603
+ }
1604
+ let index = start;
1605
+ while (index < lines.length) {
1606
+ const parsed = extractListItem(lines[index] ?? "");
1607
+ if (!parsed || parsed.indent > topIndent || parsed.ordered !== ordered) break;
1608
+ const itemLines = [parsed.content];
1609
+ const continuation = parsed.marker;
1610
+ index += 1;
1611
+ while (index < lines.length) {
1612
+ const next = lines[index] ?? "";
1613
+ if (isBlankLine(next)) {
1614
+ const after = lines[index + 1] ?? "";
1615
+ if (index + 1 < lines.length && !isBlankLine(after) && countIndent(after) >= continuation) {
1616
+ itemLines.push("");
1617
+ index += 1;
1618
+ continue;
1619
+ }
1620
+ break;
1621
+ }
1622
+ if (countIndent(next) >= continuation) {
1623
+ itemLines.push(next.slice(continuation));
1624
+ index += 1;
1625
+ continue;
1626
+ }
1627
+ if (extractListItem(next) || startsBlock(lines, index)) break;
1628
+ itemLines.push(next.trim());
1629
+ index += 1;
1630
+ }
1631
+ items.push({
1632
+ element: "listItem",
1633
+ children: parseBlocks(itemLines, depth + 1)
1634
+ });
1635
+ }
1636
+ return {
1637
+ node: {
1638
+ element: "list",
1639
+ ordered,
1640
+ start: startOrdinal,
1641
+ items
1642
+ },
1643
+ next: index
1644
+ };
1645
+ }
1646
+ /**
1647
1647
  * Project a {@link MarkdownNode} into an unsanitized {@link HTMLDocument}.
1648
1648
  *
1649
1649
  * @remarks