reamkit 1.2.0 → 1.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.
Files changed (37) hide show
  1. package/README.md +3 -2
  2. package/dist/esm/core/converter/ream.js +4 -3
  3. package/dist/esm/core/document-model/types.d.ts +2 -0
  4. package/dist/esm/core/drawingml/chart-geometry.d.ts +1 -1
  5. package/dist/esm/core/drawingml/chart-geometry.js +79 -117
  6. package/dist/esm/core/drawingml/chart-parser.d.ts +3 -0
  7. package/dist/esm/core/drawingml/chart-parser.js +28 -1
  8. package/dist/esm/core/numbering/apply.js +2 -1
  9. package/dist/esm/core/opc/index.d.ts +1 -0
  10. package/dist/esm/core/opc/package.js +3 -2
  11. package/dist/esm/core/opc/relationship-types.d.ts +1 -0
  12. package/dist/esm/core/opc/relationship-types.js +5 -2
  13. package/dist/esm/excel/print-model.d.ts +3 -0
  14. package/dist/esm/excel/print-model.js +4 -8
  15. package/dist/esm/excel/sheet-drawing.d.ts +9 -0
  16. package/dist/esm/excel/sheet-drawing.js +113 -0
  17. package/dist/esm/excel/worksheet-parser.d.ts +1 -0
  18. package/dist/esm/excel/worksheet-parser.js +4 -1
  19. package/dist/esm/excel/xlsx-reader.js +41 -0
  20. package/dist/esm/excel/xlsx-to-pdf.js +25 -18
  21. package/dist/esm/index.d.ts +1 -0
  22. package/dist/esm/layout/page-doc.d.ts +1 -0
  23. package/dist/esm/layout/styled-layout.d.ts +2 -0
  24. package/dist/esm/layout/styled-layout.js +321 -171
  25. package/dist/esm/pdf/encryption.d.ts +34 -0
  26. package/dist/esm/pdf/encryption.js +143 -0
  27. package/dist/esm/pdf/index.d.ts +2 -1
  28. package/dist/esm/pdf/styled-page-emitter.d.ts +2 -0
  29. package/dist/esm/pdf/styled-page-emitter.js +25 -7
  30. package/dist/esm/pdf/styled-page-renderer.d.ts +1 -0
  31. package/dist/esm/pdf/styled-page-renderer.js +17 -2
  32. package/dist/esm/pdf/writer.d.ts +2 -0
  33. package/dist/esm/pdf/writer.js +6 -1
  34. package/dist/esm/word/document-parser.js +4 -0
  35. package/dist/esm/word/docx-reader.js +7 -11
  36. package/dist/esm/word/docx-to-pdf.js +23 -13
  37. package/package.json +1 -1
@@ -36,6 +36,11 @@ var DEFAULT_BORDER_SIZE_EIGHTH = 4;
36
36
  var FOOTNOTE_RULE_PT = .75;
37
37
  var FOOTNOTE_RULE_GAP_ABOVE = 4;
38
38
  var FOOTNOTE_SEPARATOR_HEIGHT = 10;
39
+ var FLOAT_TEXT_GAP = 6;
40
+ var MIN_WRAP_WIDTH = 36;
41
+ function isOutOfFlowFloat(f) {
42
+ return f !== void 0 && f.wrap !== "topAndBottom";
43
+ }
39
44
  var FOOTNOTE_RULE_WIDTH = 144;
40
45
  function assignNoteNumbers(body) {
41
46
  const footnotes = /* @__PURE__ */ new Map();
@@ -224,8 +229,9 @@ function layoutStyledDocument(body, options) {
224
229
  for (const note of tailNotes.sort((a, b) => a.n - b.n)) for (const el of substituteNoteNumber(note.content, note.n)) blocks.push(layoutBodyElement(el, options, fontResources, imageResources, lastCtx.contentWidth, lastCtx.pageContentHeight));
225
230
  }
226
231
  const bookmarks = /* @__PURE__ */ new Map();
232
+ const reflowParagraph = (paragraph, width, widths) => layoutParagraphBlock(paragraph, options, fontResources, imageResources, width, widths);
227
233
  return {
228
- pages: paginateSections(blocks, sectionCtxs, structBuilder, options.language ?? "en-US", notePlan, bookmarks),
234
+ pages: paginateSections(blocks, sectionCtxs, structBuilder, options.language ?? "en-US", notePlan, bookmarks, reflowParagraph),
229
235
  resources: options.resources ?? new ResourceStore(),
230
236
  fontResources,
231
237
  imageResources,
@@ -832,14 +838,14 @@ function collectFontResources(body, headersFooters, options) {
832
838
  }
833
839
  return out;
834
840
  }
835
- function layoutParagraphBlock(paragraph, options, fontResources, imageResources, contentWidth) {
841
+ function layoutParagraphBlock(paragraph, options, fontResources, imageResources, contentWidth, lineWidths) {
836
842
  const baseResolved = resolveParagraphProperties(paragraph.properties, options.styles);
837
843
  const baseDir = paragraphBaseDirection(paragraph, baseResolved);
838
844
  const resolved = baseDir === "rtl" && baseResolved.alignment === "left" ? {
839
845
  ...baseResolved,
840
846
  alignment: "right"
841
847
  } : baseResolved;
842
- const lines = wrap(tokenizeParagraph(paragraph, options, fontResources, imageResources, contentWidth, baseDir), paragraphMaxWidth(resolved, contentWidth, true), paragraphMaxWidth(resolved, contentWidth, false), resolved, options.hyphenator);
848
+ const lines = wrap(tokenizeParagraph(paragraph, options, fontResources, imageResources, contentWidth, baseDir), paragraphMaxWidth(resolved, contentWidth, true), paragraphMaxWidth(resolved, contentWidth, false), resolved, options.hyphenator, lineWidths);
843
849
  let heightPt = 0;
844
850
  for (const line of lines) heightPt += computeLineHeight(line, resolved);
845
851
  const numbering = paragraph.properties.numbering;
@@ -855,7 +861,8 @@ function layoutParagraphBlock(paragraph, options, fontResources, imageResources,
855
861
  level: numbering.ilvl
856
862
  } } : {},
857
863
  ...paragraph.runs.some((r) => r.pageBreak) ? { pageBreakAfter: true } : {},
858
- ...paragraph.bookmarks && paragraph.bookmarks.length > 0 ? { bookmarks: paragraph.bookmarks } : {}
864
+ ...paragraph.bookmarks && paragraph.bookmarks.length > 0 ? { bookmarks: paragraph.bookmarks } : {},
865
+ source: paragraph
859
866
  };
860
867
  }
861
868
  function resolveMathItems(items, fontFor) {
@@ -987,6 +994,7 @@ function tokenizePlansLtr(plans) {
987
994
  ...plan.run.href !== void 0 ? { href: plan.run.href } : {},
988
995
  ...plan.run.footnoteRef !== void 0 ? { footnoteRef: plan.run.footnoteRef } : {},
989
996
  ...plan.run.anchor !== void 0 ? { anchor: plan.run.anchor } : {},
997
+ ...plan.run.listMarker ? { listMarker: true } : {},
990
998
  resolvedRun: plan.resolvedRun,
991
999
  font: plan.font,
992
1000
  fontSizePt: plan.fontSizePt,
@@ -1040,6 +1048,7 @@ function tokenizePlansBidi(plans, realLevels) {
1040
1048
  ...plan.run.href !== void 0 ? { href: plan.run.href } : {},
1041
1049
  ...plan.run.footnoteRef !== void 0 ? { footnoteRef: plan.run.footnoteRef } : {},
1042
1050
  ...plan.run.anchor !== void 0 ? { anchor: plan.run.anchor } : {},
1051
+ ...plan.run.listMarker ? { listMarker: true } : {},
1043
1052
  resolvedRun: plan.resolvedRun,
1044
1053
  font: plan.font,
1045
1054
  fontSizePt: plan.fontSizePt,
@@ -1230,18 +1239,22 @@ function lineFromRange(entries, start, breakIdx, availableWidthPt, isFirst, reso
1230
1239
  mathDescentPt: mathDescent
1231
1240
  };
1232
1241
  }
1233
- function wrap(tokens, firstLineWidth, otherWidth, resolved, hyphenator) {
1242
+ function wrap(tokens, firstLineWidth, otherWidth, resolved, hyphenator, lineWidths) {
1234
1243
  if (tokens.length === 0) return [];
1244
+ const widths = lineWidths ?? [firstLineWidth, otherWidth];
1235
1245
  const entries = paragraphItemStream(tokens, hyphenator);
1236
- const { breaks } = breakLines(entries.map((e) => e.item), [firstLineWidth, otherWidth]);
1246
+ const { breaks } = breakLines(entries.map((e) => e.item), widths);
1237
1247
  const lines = [];
1238
1248
  let start = 0;
1239
1249
  let isFirst = true;
1250
+ let lineIdx = 0;
1240
1251
  for (const breakIdx of breaks) {
1241
- const line = lineFromRange(entries, start, breakIdx, isFirst ? firstLineWidth : otherWidth, isFirst, resolved);
1252
+ const width = lineIdx < widths.length ? widths[lineIdx] : widths[widths.length - 1];
1253
+ const line = lineFromRange(entries, start, breakIdx, width, isFirst, resolved);
1242
1254
  if (line) lines.push(line);
1243
1255
  start = breakIdx + 1;
1244
1256
  isFirst = false;
1257
+ lineIdx++;
1245
1258
  }
1246
1259
  if (lines.length > 0) lines[lines.length - 1].isLastInParagraph = true;
1247
1260
  return lines;
@@ -1533,7 +1546,7 @@ function createFigure(builder, alt, fallback) {
1533
1546
  node.alt = alt && alt.trim().length > 0 ? alt : fallback;
1534
1547
  return node.id;
1535
1548
  }
1536
- function listItemParagraphNode(builder, stack, list) {
1549
+ function listItemParagraphNode(builder, stack, list, wantLbl) {
1537
1550
  const lvl = list.level;
1538
1551
  while (stack.length > 0) {
1539
1552
  const t = stack[stack.length - 1];
@@ -1553,64 +1566,124 @@ function listItemParagraphNode(builder, stack, list) {
1553
1566
  stack.push(frame);
1554
1567
  }
1555
1568
  const li = builder.create("LI", frame.listNode);
1569
+ const lblId = wantLbl ? builder.create("Lbl", li).id : void 0;
1556
1570
  const lbody = builder.create("LBody", li);
1557
1571
  frame.lbody = lbody;
1558
- return builder.create("P", lbody).id;
1572
+ return {
1573
+ pId: builder.create("P", lbody).id,
1574
+ ...lblId !== void 0 ? { lblId } : {}
1575
+ };
1559
1576
  }
1560
- function paginateSections(blocks, sectionCtxs, builder, defaultLang = "en-US", notes, bookmarkPositions) {
1561
- if (sectionCtxs.length === 0) return [];
1562
- const pages = [];
1563
- let ctx = sectionCtxs[0];
1564
- let secIdx = 0;
1565
- let pageInSection = 0;
1566
- let globalPageIdx = 0;
1567
- let current = [];
1568
- let pendingPageBreak = false;
1569
- let cursorY = ctx.pageHeight - ctx.marginTop;
1570
- let colIdx = 0;
1571
- let colStartLen = 0;
1572
- const colLeft = () => ctx.marginLeft + (ctx.columns?.[colIdx]?.xOffsetPt ?? 0);
1573
- const colWidth = () => ctx.columns?.[colIdx]?.widthPt ?? ctx.contentWidth;
1574
- const colHasContent = () => current.length > colStartLen;
1575
- const advanceColumn = () => {
1576
- if (ctx.columns && colIdx + 1 < ctx.columns.length) {
1577
- colIdx++;
1578
- colStartLen = current.length;
1579
- cursorY = ctx.pageHeight - ctx.marginTop;
1580
- } else flushPage();
1577
+ var PageAssembler = class {
1578
+ constructor(sectionCtxs, builder, notes, bookmarkPositions) {
1579
+ this.sectionCtxs = sectionCtxs;
1580
+ this.builder = builder;
1581
+ this.notes = notes;
1582
+ this.bookmarkPositions = bookmarkPositions;
1583
+ this.ctx = sectionCtxs[0];
1584
+ this.cursorY = this.ctx.pageHeight - this.ctx.marginTop;
1585
+ }
1586
+ pages = [];
1587
+ ctx;
1588
+ secIdx = 0;
1589
+ pageInSection = 0;
1590
+ globalPageIdx = 0;
1591
+ current = [];
1592
+ pendingPageBreak = false;
1593
+ cursorY;
1594
+ colIdx = 0;
1595
+ colStartLen = 0;
1596
+ colLeft = () => this.ctx.marginLeft + (this.ctx.columns?.[this.colIdx]?.xOffsetPt ?? 0);
1597
+ colWidth = () => this.ctx.columns?.[this.colIdx]?.widthPt ?? this.ctx.contentWidth;
1598
+ colHasContent = () => this.current.length > this.colStartLen;
1599
+ advanceColumn = () => {
1600
+ if (this.ctx.columns && this.colIdx + 1 < this.ctx.columns.length) {
1601
+ this.colIdx++;
1602
+ this.colStartLen = this.current.length;
1603
+ this.cursorY = this.ctx.pageHeight - this.ctx.marginTop;
1604
+ } else this.flushPage();
1581
1605
  };
1582
- let floatsBehind = [];
1583
- let floatsFront = [];
1584
- const floatX = (f, widthPt) => {
1606
+ floatsBehind = [];
1607
+ floatsFront = [];
1608
+ exclusions = [];
1609
+ floatX = (f, widthPt) => {
1585
1610
  const h = f.posH;
1586
- if (!h) return colLeft();
1587
- const base = h.relativeFrom === "page" ? 0 : h.relativeFrom === "column" ? colLeft() : ctx.marginLeft;
1588
- const span = h.relativeFrom === "page" ? ctx.pageWidth : h.relativeFrom === "column" ? colWidth() : ctx.contentWidth;
1611
+ if (!h) return this.colLeft();
1612
+ const base = h.relativeFrom === "page" ? 0 : h.relativeFrom === "column" ? this.colLeft() : this.ctx.marginLeft;
1613
+ const span = h.relativeFrom === "page" ? this.ctx.pageWidth : h.relativeFrom === "column" ? this.colWidth() : this.ctx.contentWidth;
1589
1614
  if (h.align === "center") return base + (span - widthPt) / 2;
1590
1615
  if (h.align === "right") return base + span - widthPt;
1591
1616
  return base + (h.offsetPt ?? 0);
1592
1617
  };
1593
- const floatTopYUp = (f) => {
1618
+ floatTopYUp = (f) => {
1594
1619
  const v = f.posV;
1595
- if (!v) return cursorY;
1596
- if (v.relativeFrom === "page") return ctx.pageHeight - (v.offsetPt ?? 0);
1597
- if (v.relativeFrom === "margin") return ctx.pageHeight - ctx.marginTop - (v.offsetPt ?? 0);
1598
- return cursorY - (v.offsetPt ?? 0);
1620
+ if (!v) return this.cursorY;
1621
+ if (v.relativeFrom === "page") return this.ctx.pageHeight - (v.offsetPt ?? 0);
1622
+ if (v.relativeFrom === "margin") return this.ctx.pageHeight - this.ctx.marginTop - (v.offsetPt ?? 0);
1623
+ return this.cursorY - (v.offsetPt ?? 0);
1624
+ };
1625
+ listStack = [];
1626
+ pageNotes = [];
1627
+ noteReserve = 0;
1628
+ placedNotes = /* @__PURE__ */ new Set();
1629
+ bottomLimit = () => this.ctx.marginBottom + this.noteReserve;
1630
+ exclusionAt = (yTop, h) => {
1631
+ const cl = this.colLeft();
1632
+ const cr = cl + this.colWidth();
1633
+ for (const e of this.exclusions) {
1634
+ if (yTop - h >= e.topYUp || yTop <= e.bottomYUp) continue;
1635
+ if (e.x1 <= cl || e.x0 >= cr) continue;
1636
+ return e;
1637
+ }
1638
+ };
1639
+ lineGeometryAt = (yTop, h) => {
1640
+ const full = this.colWidth();
1641
+ const e = this.exclusionAt(yTop, h);
1642
+ if (!e) return {
1643
+ width: full,
1644
+ xOffset: 0
1645
+ };
1646
+ const cl = this.colLeft();
1647
+ const leftRoom = e.x0 - FLOAT_TEXT_GAP - cl;
1648
+ const rightRoom = cl + full - (e.x1 + FLOAT_TEXT_GAP);
1649
+ if (rightRoom >= leftRoom) {
1650
+ const w = Math.max(MIN_WRAP_WIDTH, rightRoom);
1651
+ return {
1652
+ width: w,
1653
+ xOffset: full - w
1654
+ };
1655
+ }
1656
+ return {
1657
+ width: Math.max(MIN_WRAP_WIDTH, leftRoom),
1658
+ xOffset: 0
1659
+ };
1660
+ };
1661
+ lineWidthsFor = (block, startY) => {
1662
+ if (this.exclusions.length === 0 || block.lines.length === 0) return void 0;
1663
+ const h0 = computeLineHeight(block.lines[0], block.resolved);
1664
+ if (h0 <= 0) return void 0;
1665
+ const widths = [];
1666
+ let narrowed = false;
1667
+ let y = startY;
1668
+ for (let i = 0; i < 200; i++) {
1669
+ const g = this.lineGeometryAt(y, h0);
1670
+ widths.push(g.width);
1671
+ if (g.width < this.colWidth()) narrowed = true;
1672
+ else if (i > 0) break;
1673
+ y -= h0;
1674
+ if (y < this.bottomLimit()) break;
1675
+ }
1676
+ return narrowed ? widths : void 0;
1599
1677
  };
1600
- const listStack = [];
1601
- let pageNotes = [];
1602
- let noteReserve = 0;
1603
- const placedNotes = /* @__PURE__ */ new Set();
1604
- const bottomLimit = () => ctx.marginBottom + noteReserve;
1605
- const lineFootnotes = (line) => {
1606
- if (!notes) return [];
1678
+ lineFootnotes = (line) => {
1679
+ if (!this.notes) return [];
1607
1680
  const out = [];
1608
1681
  for (const tok of line.tokens) {
1609
1682
  if (tok.kind !== "text" || tok.footnoteRef === void 0) continue;
1610
1683
  const id = tok.footnoteRef;
1611
- if (placedNotes.has(id) || out.some((o) => o.id === id)) continue;
1612
- const laid = notes.layout(ctx, id);
1613
- const n = notes.numbers.get(id);
1684
+ if (this.placedNotes.has(id) || out.some((o) => o.id === id)) continue;
1685
+ const laid = this.notes.layout(this.ctx, id);
1686
+ const n = this.notes.numbers.get(id);
1614
1687
  if (!laid || n === void 0) continue;
1615
1688
  out.push({
1616
1689
  id,
@@ -1621,108 +1694,125 @@ function paginateSections(blocks, sectionCtxs, builder, defaultLang = "en-US", n
1621
1694
  }
1622
1695
  return out;
1623
1696
  };
1624
- const renderNotesBand = () => {
1625
- if (pageNotes.length === 0) return [];
1697
+ renderNotesBand = () => {
1698
+ if (this.pageNotes.length === 0) return [];
1626
1699
  const out = [];
1627
- const top = ctx.marginBottom + noteReserve;
1700
+ const top = this.ctx.marginBottom + this.noteReserve;
1628
1701
  out.push({
1629
1702
  type: "fill",
1630
- x: pt(ctx.marginLeft),
1631
- y: pt(ctx.pageHeight - (top - FOOTNOTE_RULE_GAP_ABOVE)),
1703
+ x: pt(this.ctx.marginLeft),
1704
+ y: pt(this.ctx.pageHeight - (top - FOOTNOTE_RULE_GAP_ABOVE)),
1632
1705
  width: pt(FOOTNOTE_RULE_WIDTH),
1633
1706
  height: pt(FOOTNOTE_RULE_PT),
1634
1707
  fillColorHex: "000000"
1635
1708
  });
1636
1709
  let cursor = top - FOOTNOTE_SEPARATOR_HEIGHT;
1637
- for (const note of pageNotes.sort((a, b) => a.n - b.n)) {
1710
+ for (const note of this.pageNotes.sort((a, b) => a.n - b.n)) {
1638
1711
  let structId;
1639
- if (builder) {
1640
- const noteNode = builder.create("Note", builder.root);
1641
- structId = builder.create("P", noteNode).id;
1712
+ if (this.builder) {
1713
+ const noteNode = this.builder.create("Note", this.builder.root);
1714
+ structId = this.builder.create("P", noteNode).id;
1642
1715
  }
1643
- out.push(...drawBlocksSequentially(note.blocks, ctx.marginLeft, cursor, ctx.pageHeight, structId));
1716
+ out.push(...drawBlocksSequentially(note.blocks, this.ctx.marginLeft, cursor, this.ctx.pageHeight, structId));
1644
1717
  cursor -= note.heightPt;
1645
1718
  }
1646
1719
  return out;
1647
1720
  };
1648
- const dynBands = [];
1649
- const flushPage = (force = false) => {
1650
- if (current.length === 0 && !force) return;
1651
- const band = bandForPage(pageInSection, globalPageIdx, ctx.titlePg, ctx.evenAndOddHeaders);
1652
- const header = pickBand(ctx.headerSet, band);
1653
- const footer = pickBand(ctx.footerSet, band);
1654
- if (header.renderDynamic) dynBands.push({
1655
- pageIdx: pages.length,
1656
- pageNumber: globalPageIdx + 1,
1721
+ dynBands = [];
1722
+ flushPage = (force = false) => {
1723
+ if (this.current.length === 0 && !force) return;
1724
+ const band = bandForPage(this.pageInSection, this.globalPageIdx, this.ctx.titlePg, this.ctx.evenAndOddHeaders);
1725
+ const header = pickBand(this.ctx.headerSet, band);
1726
+ const footer = pickBand(this.ctx.footerSet, band);
1727
+ if (header.renderDynamic) this.dynBands.push({
1728
+ pageIdx: this.pages.length,
1729
+ pageNumber: this.globalPageIdx + 1,
1657
1730
  position: "header",
1658
1731
  render: header.renderDynamic
1659
1732
  });
1660
- if (footer.renderDynamic) dynBands.push({
1661
- pageIdx: pages.length,
1662
- pageNumber: globalPageIdx + 1,
1733
+ if (footer.renderDynamic) this.dynBands.push({
1734
+ pageIdx: this.pages.length,
1735
+ pageNumber: this.globalPageIdx + 1,
1663
1736
  position: "footer",
1664
1737
  render: footer.renderDynamic
1665
1738
  });
1666
- pages.push({
1739
+ this.pages.push({
1667
1740
  commands: [
1668
1741
  ...header.commands,
1669
- ...floatsBehind,
1670
- ...current,
1671
- ...floatsFront,
1672
- ...renderNotesBand(),
1742
+ ...this.floatsBehind,
1743
+ ...this.current,
1744
+ ...this.floatsFront,
1745
+ ...this.renderNotesBand(),
1673
1746
  ...footer.commands
1674
1747
  ],
1675
- width: pt(ctx.pageWidth),
1676
- height: pt(ctx.pageHeight)
1748
+ width: pt(this.ctx.pageWidth),
1749
+ height: pt(this.ctx.pageHeight)
1677
1750
  });
1678
- current = [];
1679
- floatsBehind = [];
1680
- floatsFront = [];
1681
- pageNotes = [];
1682
- noteReserve = 0;
1683
- colIdx = 0;
1684
- colStartLen = 0;
1685
- pageInSection++;
1686
- globalPageIdx++;
1687
- cursorY = ctx.pageHeight - ctx.marginTop;
1751
+ this.current = [];
1752
+ this.floatsBehind = [];
1753
+ this.floatsFront = [];
1754
+ this.exclusions = [];
1755
+ this.pageNotes = [];
1756
+ this.noteReserve = 0;
1757
+ this.colIdx = 0;
1758
+ this.colStartLen = 0;
1759
+ this.pageInSection++;
1760
+ this.globalPageIdx++;
1761
+ this.cursorY = this.ctx.pageHeight - this.ctx.marginTop;
1688
1762
  };
1763
+ };
1764
+ function paginateSections(blocks, sectionCtxs, builder, defaultLang = "en-US", notes, bookmarkPositions, reflowParagraph) {
1765
+ if (sectionCtxs.length === 0) return [];
1766
+ const asm = new PageAssembler(sectionCtxs, builder, notes, bookmarkPositions);
1689
1767
  for (let blockIdx = 0; blockIdx < blocks.length; blockIdx++) {
1690
- while (secIdx < sectionCtxs.length - 1 && blockIdx >= ctx.endIndex) {
1691
- flushPage();
1692
- secIdx++;
1693
- ctx = sectionCtxs[secIdx];
1694
- pageInSection = 0;
1695
- cursorY = ctx.pageHeight - ctx.marginTop;
1768
+ while (asm.secIdx < sectionCtxs.length - 1 && blockIdx >= asm.ctx.endIndex) {
1769
+ asm.flushPage();
1770
+ asm.secIdx++;
1771
+ asm.ctx = sectionCtxs[asm.secIdx];
1772
+ asm.pageInSection = 0;
1773
+ asm.cursorY = asm.ctx.pageHeight - asm.ctx.marginTop;
1696
1774
  }
1697
1775
  const block = blocks[blockIdx];
1698
- if (pendingPageBreak) {
1699
- pendingPageBreak = false;
1700
- if (current.length > 0) flushPage();
1776
+ if (asm.pendingPageBreak) {
1777
+ asm.pendingPageBreak = false;
1778
+ if (asm.current.length > 0) asm.flushPage();
1701
1779
  }
1702
- if (builder && !(block.kind === "paragraph" && block.list)) listStack.length = 0;
1780
+ if (builder && !(block.kind === "paragraph" && block.list)) asm.listStack.length = 0;
1703
1781
  if (block.kind === "paragraph") {
1704
- if (block.resolved.pageBreakBefore && current.length > 0) flushPage();
1705
- cursorY -= block.spacingBeforePt;
1782
+ if (block.resolved.pageBreakBefore && asm.current.length > 0) asm.flushPage();
1783
+ asm.cursorY -= block.spacingBeforePt;
1784
+ let pb = block;
1785
+ if (reflowParagraph && pb.source && asm.exclusions.length > 0) {
1786
+ const widths = asm.lineWidthsFor(block, asm.cursorY);
1787
+ if (widths) pb = reflowParagraph(pb.source, asm.colWidth(), widths);
1788
+ }
1706
1789
  let structId;
1790
+ let markerLblId;
1791
+ const firstLine = pb.lines[0];
1792
+ const splitMarker = builder !== void 0 && pb.list !== void 0 && firstLine !== void 0 && pb.resolved.alignment === "left" && pb.resolved.bidi !== true && !firstLine.tokens.some((t) => t.bidiLevel % 2 === 1) && firstLine.tokens.some((t) => t.kind === "text" && t.listMarker) && firstLine.tokens.some((t) => !(t.kind === "text" && t.listMarker));
1707
1793
  if (builder) {
1708
- structId = block.list ? listItemParagraphNode(builder, listStack, block.list) : builder.create(paragraphStructType(block.resolved), builder.root).id;
1709
- const lang = dominantParagraphLang(block.lines);
1794
+ if (pb.list) {
1795
+ const nodes = listItemParagraphNode(builder, asm.listStack, pb.list, splitMarker);
1796
+ structId = nodes.pId;
1797
+ markerLblId = nodes.lblId;
1798
+ } else structId = builder.create(paragraphStructType(pb.resolved), builder.root).id;
1799
+ const lang = dominantParagraphLang(pb.lines);
1710
1800
  if (lang && lang !== defaultLang) builder.node(structId).lang = lang;
1711
1801
  }
1712
1802
  let firstLineOfBlock = true;
1713
- for (const line of block.lines) {
1714
- const h = computeLineHeight(line, block.resolved);
1715
- let newNotes = lineFootnotes(line);
1716
- const addedReserve = (sub) => sub.reduce((sum, x) => sum + x.heightPt, 0) + (pageNotes.length === 0 && sub.length > 0 ? FOOTNOTE_SEPARATOR_HEIGHT : 0);
1717
- if (cursorY - h < bottomLimit() + addedReserve(newNotes) && colHasContent()) {
1718
- advanceColumn();
1719
- newNotes = lineFootnotes(line);
1803
+ for (const line of pb.lines) {
1804
+ const h = computeLineHeight(line, pb.resolved);
1805
+ let newNotes = asm.lineFootnotes(line);
1806
+ const addedReserve = (sub) => sub.reduce((sum, x) => sum + x.heightPt, 0) + (asm.pageNotes.length === 0 && sub.length > 0 ? FOOTNOTE_SEPARATOR_HEIGHT : 0);
1807
+ if (asm.cursorY - h < asm.bottomLimit() + addedReserve(newNotes) && asm.colHasContent()) {
1808
+ asm.advanceColumn();
1809
+ newNotes = asm.lineFootnotes(line);
1720
1810
  }
1721
1811
  if (newNotes.length > 0) {
1722
- noteReserve += addedReserve(newNotes);
1812
+ asm.noteReserve += addedReserve(newNotes);
1723
1813
  for (const x of newNotes) {
1724
- placedNotes.add(x.id);
1725
- pageNotes.push({
1814
+ asm.placedNotes.add(x.id);
1815
+ asm.pageNotes.push({
1726
1816
  n: x.n,
1727
1817
  blocks: x.blocks,
1728
1818
  heightPt: x.heightPt
@@ -1731,51 +1821,93 @@ function paginateSections(blocks, sectionCtxs, builder, defaultLang = "en-US", n
1731
1821
  }
1732
1822
  if (firstLineOfBlock) {
1733
1823
  firstLineOfBlock = false;
1734
- if (block.bookmarks && bookmarkPositions) {
1735
- for (const bookmarkName of block.bookmarks) if (!bookmarkPositions.has(bookmarkName)) bookmarkPositions.set(bookmarkName, {
1736
- pageIdx: pages.length,
1737
- yTopPt: cursorY
1824
+ if (pb.bookmarks && asm.bookmarkPositions) {
1825
+ for (const bookmarkName of pb.bookmarks) if (!asm.bookmarkPositions.has(bookmarkName)) asm.bookmarkPositions.set(bookmarkName, {
1826
+ pageIdx: asm.pages.length,
1827
+ yTopPt: asm.cursorY
1738
1828
  });
1739
1829
  }
1740
1830
  }
1741
- cursorY -= h;
1742
- const indentLeft = block.resolved.indentLeft + (line.firstLine ? block.resolved.indentFirstLine : 0);
1743
- const offset = alignmentOffset(block.resolved.alignment, line.contentWidthPt, line.availableWidthPt);
1744
- current.push({
1831
+ asm.cursorY -= h;
1832
+ const indentLeft = pb.resolved.indentLeft + (line.firstLine ? pb.resolved.indentFirstLine : 0);
1833
+ const offset = alignmentOffset(pb.resolved.alignment, line.contentWidthPt, line.availableWidthPt);
1834
+ const baselineY = pt(asm.ctx.pageHeight - (asm.cursorY + lineDescent(line)));
1835
+ const exclusionShift = asm.exclusions.length > 0 ? asm.lineGeometryAt(asm.cursorY + h, h).xOffset : 0;
1836
+ const originX = asm.colLeft() + indentLeft + offset + exclusionShift;
1837
+ if (markerLblId !== void 0 && line === firstLine) {
1838
+ let k = 0;
1839
+ let markerWidth = 0;
1840
+ while (k < line.tokens.length) {
1841
+ const t = line.tokens[k];
1842
+ if (t.kind !== "text" || !t.listMarker) break;
1843
+ markerWidth += t.widthPt;
1844
+ k++;
1845
+ }
1846
+ asm.current.push({
1847
+ type: "line",
1848
+ line: {
1849
+ ...line,
1850
+ tokens: line.tokens.slice(0, k),
1851
+ isLastInParagraph: false
1852
+ },
1853
+ originX: pt(originX),
1854
+ baselineY,
1855
+ structId: markerLblId
1856
+ });
1857
+ asm.current.push({
1858
+ type: "line",
1859
+ line: {
1860
+ ...line,
1861
+ tokens: line.tokens.slice(k)
1862
+ },
1863
+ originX: pt(originX + markerWidth),
1864
+ baselineY,
1865
+ ...structId !== void 0 ? { structId } : {}
1866
+ });
1867
+ } else asm.current.push({
1745
1868
  type: "line",
1746
1869
  line,
1747
- originX: pt(colLeft() + indentLeft + offset),
1748
- baselineY: pt(ctx.pageHeight - (cursorY + lineDescent(line))),
1870
+ originX: pt(originX),
1871
+ baselineY,
1749
1872
  ...structId !== void 0 ? { structId } : {}
1750
1873
  });
1751
1874
  }
1752
- cursorY -= block.spacingAfterPt;
1753
- if (block.pageBreakAfter) pendingPageBreak = true;
1875
+ asm.cursorY -= pb.spacingAfterPt;
1876
+ if (pb.pageBreakAfter) asm.pendingPageBreak = true;
1754
1877
  } else if (block.kind === "image") {
1755
1878
  const figId = builder ? createFigure(builder, block.altText, "Image") : void 0;
1756
1879
  const emitImageAt = (x, topYUp, sink) => {
1757
1880
  sink.push({
1758
1881
  type: "image",
1759
1882
  x: pt(x),
1760
- y: pt(ctx.pageHeight - topYUp),
1883
+ y: pt(asm.ctx.pageHeight - topYUp),
1761
1884
  width: pt(block.widthPt),
1762
1885
  height: pt(block.heightPt),
1763
1886
  imageResourceName: block.resourceName,
1764
1887
  ...figId !== void 0 ? { structId: figId } : {}
1765
1888
  });
1766
1889
  };
1767
- if (block.float?.wrap === "none") emitImageAt(floatX(block.float, block.widthPt), floatTopYUp(block.float), block.float.behind ? floatsBehind : floatsFront);
1768
- else {
1769
- cursorY -= block.spacingBeforePt;
1770
- if (cursorY - block.heightPt < bottomLimit() && colHasContent()) advanceColumn();
1771
- cursorY -= block.heightPt;
1772
- emitImageAt(colLeft(), cursorY + block.heightPt, current);
1773
- cursorY -= block.spacingAfterPt;
1890
+ if (isOutOfFlowFloat(block.float)) {
1891
+ const fx = asm.floatX(block.float, block.widthPt);
1892
+ const fy = asm.floatTopYUp(block.float);
1893
+ emitImageAt(fx, fy, block.float.behind ? asm.floatsBehind : asm.floatsFront);
1894
+ if (block.float.wrap !== "none") asm.exclusions.push({
1895
+ x0: fx,
1896
+ x1: fx + block.widthPt,
1897
+ topYUp: fy,
1898
+ bottomYUp: fy - block.heightPt
1899
+ });
1900
+ } else {
1901
+ asm.cursorY -= block.spacingBeforePt;
1902
+ if (asm.cursorY - block.heightPt < asm.bottomLimit() && asm.colHasContent()) asm.advanceColumn();
1903
+ asm.cursorY -= block.heightPt;
1904
+ emitImageAt(asm.colLeft(), asm.cursorY + block.heightPt, asm.current);
1905
+ asm.cursorY -= block.spacingAfterPt;
1774
1906
  }
1775
1907
  } else if (block.kind === "shape") {
1776
1908
  const figId = builder ? createFigure(builder, block.altText, "Shape") : void 0;
1777
1909
  const emitShapeAt = (x, bottomYUp, sink) => {
1778
- const transform = flipTransform(buildShapeTransform(x, bottomYUp, block.widthPt, block.heightPt, block.rotation60k, block.flipH, block.flipV), ctx.pageHeight);
1910
+ const transform = flipTransform(buildShapeTransform(x, bottomYUp, block.widthPt, block.heightPt, block.rotation60k, block.flipH, block.flipV), asm.ctx.pageHeight);
1779
1911
  sink.push({
1780
1912
  type: "shape",
1781
1913
  shape: {
@@ -1802,20 +1934,29 @@ function paginateSections(blocks, sectionCtxs, builder, defaultLang = "en-US", n
1802
1934
  type: "line",
1803
1935
  line,
1804
1936
  originX: pt(x + block.insetLeftPt + lineOffset),
1805
- baselineY: pt(ctx.pageHeight - (textY + lineDescent(line))),
1937
+ baselineY: pt(asm.ctx.pageHeight - (textY + lineDescent(line))),
1806
1938
  ...figId !== void 0 ? { structId: figId } : {}
1807
1939
  });
1808
1940
  }
1809
1941
  }
1810
1942
  };
1811
- if (block.float?.wrap === "none") emitShapeAt(floatX(block.float, block.widthPt), floatTopYUp(block.float) - block.heightPt, block.float.behind ? floatsBehind : floatsFront);
1812
- else {
1813
- cursorY -= block.spacingBeforePt;
1814
- if (cursorY - block.heightPt < bottomLimit() && colHasContent()) advanceColumn();
1815
- cursorY -= block.heightPt;
1816
- const offset = alignmentOffset(block.resolvedAlignment, block.widthPt, colWidth());
1817
- emitShapeAt(colLeft() + offset, cursorY, current);
1818
- cursorY -= block.spacingAfterPt;
1943
+ if (isOutOfFlowFloat(block.float)) {
1944
+ const fx = asm.floatX(block.float, block.widthPt);
1945
+ const fy = asm.floatTopYUp(block.float);
1946
+ emitShapeAt(fx, fy - block.heightPt, block.float.behind ? asm.floatsBehind : asm.floatsFront);
1947
+ if (block.float.wrap !== "none") asm.exclusions.push({
1948
+ x0: fx,
1949
+ x1: fx + block.widthPt,
1950
+ topYUp: fy,
1951
+ bottomYUp: fy - block.heightPt
1952
+ });
1953
+ } else {
1954
+ asm.cursorY -= block.spacingBeforePt;
1955
+ if (asm.cursorY - block.heightPt < asm.bottomLimit() && asm.colHasContent()) asm.advanceColumn();
1956
+ asm.cursorY -= block.heightPt;
1957
+ const offset = alignmentOffset(block.resolvedAlignment, block.widthPt, asm.colWidth());
1958
+ emitShapeAt(asm.colLeft() + offset, asm.cursorY, asm.current);
1959
+ asm.cursorY -= block.spacingAfterPt;
1819
1960
  }
1820
1961
  } else if (block.kind === "chart") {
1821
1962
  const figId = builder ? createFigure(builder, block.altText, "Chart") : void 0;
@@ -1834,7 +1975,7 @@ function paginateSections(blocks, sectionCtxs, builder, defaultLang = "en-US", n
1834
1975
  1,
1835
1976
  x,
1836
1977
  bottomYUp
1837
- ], ctx.pageHeight)
1978
+ ], asm.ctx.pageHeight)
1838
1979
  },
1839
1980
  ...fig
1840
1981
  });
@@ -1842,18 +1983,27 @@ function paginateSections(blocks, sectionCtxs, builder, defaultLang = "en-US", n
1842
1983
  type: "line",
1843
1984
  line: t.line,
1844
1985
  originX: pt(x + t.x),
1845
- baselineY: pt(ctx.pageHeight - (bottomYUp + t.y)),
1986
+ baselineY: pt(asm.ctx.pageHeight - (bottomYUp + t.y)),
1846
1987
  ...fig
1847
1988
  });
1848
1989
  };
1849
- if (block.float?.wrap === "none") emitChartAt(floatX(block.float, block.widthPt), floatTopYUp(block.float) - block.heightPt, block.float.behind ? floatsBehind : floatsFront);
1850
- else {
1851
- cursorY -= block.spacingBeforePt;
1852
- if (cursorY - block.heightPt < bottomLimit() && colHasContent()) advanceColumn();
1853
- cursorY -= block.heightPt;
1854
- const offset = alignmentOffset(block.resolvedAlignment, block.widthPt, colWidth());
1855
- emitChartAt(colLeft() + offset, cursorY, current);
1856
- cursorY -= block.spacingAfterPt;
1990
+ if (isOutOfFlowFloat(block.float)) {
1991
+ const fx = asm.floatX(block.float, block.widthPt);
1992
+ const fy = asm.floatTopYUp(block.float);
1993
+ emitChartAt(fx, fy - block.heightPt, block.float.behind ? asm.floatsBehind : asm.floatsFront);
1994
+ if (block.float.wrap !== "none") asm.exclusions.push({
1995
+ x0: fx,
1996
+ x1: fx + block.widthPt,
1997
+ topYUp: fy,
1998
+ bottomYUp: fy - block.heightPt
1999
+ });
2000
+ } else {
2001
+ asm.cursorY -= block.spacingBeforePt;
2002
+ if (asm.cursorY - block.heightPt < asm.bottomLimit() && asm.colHasContent()) asm.advanceColumn();
2003
+ asm.cursorY -= block.heightPt;
2004
+ const offset = alignmentOffset(block.resolvedAlignment, block.widthPt, asm.colWidth());
2005
+ emitChartAt(asm.colLeft() + offset, asm.cursorY, asm.current);
2006
+ asm.cursorY -= block.spacingAfterPt;
1857
2007
  }
1858
2008
  } else {
1859
2009
  const colCount = block.rows.reduce((max, r) => Math.max(max, r.cells.reduce((s, c) => Math.max(s, c.colStart + c.colSpan), 0)), 0);
@@ -1862,7 +2012,7 @@ function paginateSections(blocks, sectionCtxs, builder, defaultLang = "en-US", n
1862
2012
  else break;
1863
2013
  const headerHeightPt = headerRows.reduce((s, r) => s + r.heightPt, 0);
1864
2014
  const tableNode = builder ? builder.create("Table", builder.root) : void 0;
1865
- const tableX = colLeft() + block.xOffsetPt;
2015
+ const tableX = asm.colLeft() + block.xOffsetPt;
1866
2016
  for (let ri = 0; ri < block.rows.length; ri++) {
1867
2017
  const row = block.rows[ri];
1868
2018
  const isLeadingHeader = ri < headerRows.length;
@@ -1880,34 +2030,34 @@ function paginateSections(blocks, sectionCtxs, builder, defaultLang = "en-US", n
1880
2030
  return b.create("P", cellNode).id;
1881
2031
  });
1882
2032
  }
1883
- const chunks = row.heightPt > ctx.pageContentHeight ? splitRowIntoChunks(row, ctx.pageContentHeight) : [row];
2033
+ const chunks = row.heightPt > asm.ctx.pageContentHeight ? splitRowIntoChunks(row, asm.ctx.pageContentHeight) : [row];
1884
2034
  for (let ci = 0; ci < chunks.length; ci++) {
1885
2035
  const chunk = chunks[ci];
1886
- const forcedBreak = ci === 0 && row.breakBefore && !isLeadingHeader && current.length > 0;
1887
- const overflow = cursorY - chunk.heightPt < bottomLimit() && colHasContent();
2036
+ const forcedBreak = ci === 0 && row.breakBefore && !isLeadingHeader && asm.current.length > 0;
2037
+ const overflow = asm.cursorY - chunk.heightPt < asm.bottomLimit() && asm.colHasContent();
1888
2038
  if (forcedBreak || overflow) {
1889
- if (forcedBreak) flushPage();
1890
- else advanceColumn();
1891
- if (!isLeadingHeader && headerRows.length > 0 && cursorY - headerHeightPt - chunk.heightPt >= bottomLimit()) for (const hr of headerRows) {
1892
- emitRowChunk(current, hr, tableX, cursorY, ctx.pageHeight, colCount, void 0);
1893
- cursorY -= hr.heightPt;
2039
+ if (forcedBreak) asm.flushPage();
2040
+ else asm.advanceColumn();
2041
+ if (!isLeadingHeader && headerRows.length > 0 && asm.cursorY - headerHeightPt - chunk.heightPt >= asm.bottomLimit()) for (const hr of headerRows) {
2042
+ emitRowChunk(asm.current, hr, tableX, asm.cursorY, asm.ctx.pageHeight, colCount, void 0);
2043
+ asm.cursorY -= hr.heightPt;
1894
2044
  }
1895
2045
  }
1896
- emitRowChunk(current, chunk, tableX, cursorY, ctx.pageHeight, colCount, cellStructIds);
1897
- cursorY -= chunk.heightPt;
2046
+ emitRowChunk(asm.current, chunk, tableX, asm.cursorY, asm.ctx.pageHeight, colCount, cellStructIds);
2047
+ asm.cursorY -= chunk.heightPt;
1898
2048
  }
1899
2049
  }
1900
2050
  }
1901
2051
  }
1902
- flushPage();
1903
- if (pages.length === 0) flushPage(true);
1904
- for (const d of dynBands) {
1905
- const cmds = d.render(d.pageNumber, pages.length);
1906
- const page = pages[d.pageIdx];
2052
+ asm.flushPage();
2053
+ if (asm.pages.length === 0) asm.flushPage(true);
2054
+ for (const d of asm.dynBands) {
2055
+ const cmds = d.render(d.pageNumber, asm.pages.length);
2056
+ const page = asm.pages[d.pageIdx];
1907
2057
  if (d.position === "header") page.commands.unshift(...cmds);
1908
2058
  else page.commands.push(...cmds);
1909
2059
  }
1910
- return pages;
2060
+ return asm.pages;
1911
2061
  }
1912
2062
  function tableCellRowSpan(rows, startRowIdx, colStart) {
1913
2063
  let span = 1;