oasis-editor 0.0.89 → 0.0.91

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.
@@ -1,7 +1,7 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { v as visitRun, a as assertNever, c as createSignal, b as createEditorStateFromDocument, d as createInitialEditorState, S as STANDARD_FONT_SIZES_PT, f as fontSizePxToPt, p as probeLocalFontFamilies, e as createEditorParagraphFromRuns, i as isInlineObjectRun, g as createEditorStyledRun, h as getParagraphLength, j as getParagraphText, k as getActiveZone, l as getDocumentSections, m as getActiveSectionIndex, n as getParagraphs, o as normalizeSelection, q as positionToParagraphOffset, r as paragraphOffsetToPosition, s as clampPosition, t as findParagraphIndex, u as createCollapsedSelection, w as isSelectionCollapsed, x as parseFontSizePtToPx, y as formatFontSizePt, z as createEditorParagraph, A as getBlockParagraphs, B as findParagraphTableLocation, C as buildTableCellLayout, P as PT_PER_PX, D as createEditorTableCell, E as createEditorTableRow, F as createEditorTable, G as underlineStyleToCssDecorationStyle, H as resolveImageSrc, I as listKindForTag, J as isParagraphTag, K as collectInlineRuns, L as parseParagraphStyle, M as getRunImage, N as InlineShell, O as BalloonShell, Q as DocumentShell, R as createMemo, T as buildCanvasLayoutSnapshot, U as getCaretRectFromSnapshot, V as getParagraphRectFromSnapshot, W as createComponent, X as CaretOverlay, Y as Show, Z as createRenderEffect, _ as style, $ as setAttribute, a0 as setStyleProperty, a1 as memo, a2 as template, a3 as useI18n, a4 as createEffect, a5 as insert, a6 as use, a7 as addEventListener, a8 as Dialog, a9 as delegateEvents, aa as className, ab as For, ac as UNDERLINE_STYLE_OPTIONS, ad as Tabs, ae as onMount, af as onCleanup, ag as PluginUiHost, ah as OasisEditorEditor, ai as OasisBrandMark, aj as setPreciseFontPreference, ak as setWelcomeSeen, al as enablePreciseFontMode, am as TWIPS_PER_POINT, an as PX_PER_INCH, ao as TWIPS_PER_INCH, ap as resolveEffectiveParagraphStyle, aq as resolveEffectiveTextStyleForParagraph, ar as EMU_PER_PX, as as EMU_PER_PT, at as getRunFootnoteReference, au as getRunEndnoteReference, av as iterateFootnoteReferenceRuns, aw as iterateEndnoteReferenceRuns, ax as imageContentTypeDefaults, ay as getRunFieldChar, az as getRunFieldInstruction, aA as createEditorRun, aB as JSZip, aC as imageExtensionFromMime, aD as pxToPt$1, aE as resolveFloatingObjectRect, aF as getTextBoxFloatingGeometry, aG as getPresetPathSegments, aH as projectBlocksLayout, aI as buildListLabels, aJ as getImageFloatingGeometry, aK as textStyleToFontSizePt, aL as PX_PER_POINT, aM as DEFAULT_FONT_SIZE_PX, aN as isDoubleUnderlineStyle, aO as isWavyUnderlineStyle, aP as underlineStyleLineWidthPx, aQ as underlineStyleDashArray, aR as resolveListLabel, aS as getListLabelInset, aT as getAlignedListLabelInset, aU as getParagraphBorderInsets, aV as buildSegmentTable, aW as buildCanvasTableLayout, aX as resolveCanvasTableWidth, aY as resolveFloatingTableRect, aZ as normalizeFamily, a_ as ROBOTO_FONT_FILES, a$ as loadFontAsset, b0 as OFFICE_COMPAT_FONT_FAMILIES, b1 as buildSfnt, b2 as defaultFontDecoderRegistry, b3 as SfntFontProgram, b4 as collectPdfFontFamilies, b5 as projectDocumentLayout, b6 as getPageContentWidth, b7 as getPageHeaderZoneTop, b8 as getPageBodyTop, b9 as getPageColumnRects, ba as findFootnoteReference, bb as FOOTNOTE_MARKER_GUTTER_PX, bc as resolveImporterForFile, bd as getDocumentSectionsCanonical, be as getDocumentParagraphsCanonical, bf as getDocumentParagraphs, bg as getDocumentPageSettings, bh as getTableCellContentWidthForParagraph, bi as on, bj as debounce, bk as unwrap, bl as perfTimer, bm as getRunTextBox, bn as createEditorDocument, bo as resolveResizedDimensions, bp as resolveTextBoxRenderHeight, bq as getToolbarStyleState, br as getCachedCanvasImage, bs as measureParagraphMinContentWidthPx, bt as getEditableBlocksForZone, bu as findParagraphLocation, bv as createSectionBoundaryParagraph, bw as normalizePageSettings, bx as DEFAULT_EDITOR_PAGE_SETTINGS, by as markStart, bz as markEnd, bA as getParagraphEntries, bB as getParagraphById, bC as createEditorFootnote, bD as createFootnoteReferenceRun, bE as renumberFootnotes, bF as getFootnoteDisplayMarker, bG as getHeadingLevel, bH as preciseFontModeVersion, bI as isPreciseFontModeEnabled, bJ as resolveNamedTextStyle, bK as togglePreciseFontMode, bL as nextFontSizePt, bM as previousFontSizePt, bN as fontSizePtToPx, bO as createDefaultToolbarPreset, bP as MenuRegistry, bQ as createToolbarRegistry, bR as Editor, bS as resolveCommandRef, bT as commandRefName, bU as createOasisEditorClient, bV as createEditorZoom, bW as startLongTaskObserver, bX as installGlobalReport, bY as applyStoredPreciseFontPreference, bZ as getWelcomeSeen, b_ as isLocalFontAccessSupported, b$ as EDITOR_SCROLL_PADDING_PX, c0 as Toolbar, c1 as OasisEditorLoading, c2 as I18nProvider, c3 as createTranslator, c4 as createEditorLogger, c5 as registerDomStatsSurface } from "./index-BICQTKCZ.js";
4
+ import { v as visitRun, a as assertNever, c as createSignal, b as createEditorStateFromDocument, d as createInitialEditorState, S as STANDARD_FONT_SIZES_PT, f as fontSizePxToPt, p as probeLocalFontFamilies, e as createEditorParagraphFromRuns, i as isInlineObjectRun, g as createEditorStyledRun, h as getParagraphLength, j as getParagraphText, k as getActiveZone, l as getDocumentSections, m as getActiveSectionIndex, n as getParagraphs, o as normalizeSelection, q as positionToParagraphOffset, r as paragraphOffsetToPosition, s as clampPosition, t as findParagraphIndex, u as createCollapsedSelection, w as isSelectionCollapsed, x as parseFontSizePtToPx, y as formatFontSizePt, z as createEditorParagraph, A as getBlockParagraphs, B as findParagraphTableLocation, C as buildTableCellLayout, P as PT_PER_PX, D as createEditorTableCell, E as createEditorTableRow, F as createEditorTable, G as underlineStyleToCssDecorationStyle, H as resolveImageSrc, I as listKindForTag, J as isParagraphTag, K as collectInlineRuns, L as parseParagraphStyle, M as getRunImage, N as InlineShell, O as BalloonShell, Q as DocumentShell, R as createMemo, T as buildCanvasLayoutSnapshot, U as getCaretRectFromSnapshot, V as getParagraphRectFromSnapshot, W as createComponent, X as CaretOverlay, Y as Show, Z as createRenderEffect, _ as style, $ as setAttribute, a0 as setStyleProperty, a1 as memo, a2 as template, a3 as useI18n, a4 as createEffect, a5 as insert, a6 as use, a7 as addEventListener, a8 as Dialog, a9 as delegateEvents, aa as className, ab as For, ac as UNDERLINE_STYLE_OPTIONS, ad as Tabs, ae as onMount, af as onCleanup, ag as PluginUiHost, ah as OasisEditorEditor, ai as OasisBrandMark, aj as setPreciseFontPreference, ak as setWelcomeSeen, al as enablePreciseFontMode, am as TWIPS_PER_POINT, an as PX_PER_INCH, ao as TWIPS_PER_INCH, ap as resolveEffectiveParagraphStyle, aq as resolveEffectiveTextStyleForParagraph, ar as EMU_PER_PX, as as EMU_PER_PT, at as getRunFootnoteReference, au as getRunEndnoteReference, av as iterateFootnoteReferenceRuns, aw as iterateEndnoteReferenceRuns, ax as imageContentTypeDefaults, ay as getRunFieldChar, az as getRunFieldInstruction, aA as createEditorRun, aB as JSZip, aC as imageExtensionFromMime, aD as pxToPt$1, aE as resolveFloatingObjectRect, aF as getTextBoxFloatingGeometry, aG as getPresetPathSegments, aH as projectBlocksLayout, aI as buildListLabels, aJ as getImageFloatingGeometry, aK as textStyleToFontSizePt, aL as PX_PER_POINT, aM as DEFAULT_FONT_SIZE_PX, aN as isDoubleUnderlineStyle, aO as isWavyUnderlineStyle, aP as underlineStyleLineWidthPx, aQ as underlineStyleDashArray, aR as resolveListLabel, aS as getListLabelInset, aT as getAlignedListLabelInset, aU as getParagraphBorderInsets, aV as buildSegmentTable, aW as buildCanvasTableLayout, aX as resolveCanvasTableWidth, aY as resolveFloatingTableRect, aZ as normalizeFamily, a_ as ROBOTO_FONT_FILES, a$ as loadFontAsset, b0 as OFFICE_COMPAT_FONT_FAMILIES, b1 as buildSfnt, b2 as defaultFontDecoderRegistry, b3 as SfntFontProgram, b4 as collectPdfFontFamilies, b5 as projectDocumentLayout, b6 as getPageContentWidth, b7 as getPageHeaderZoneTop, b8 as getPageBodyTop, b9 as getPageColumnRects, ba as findFootnoteReference, bb as FOOTNOTE_MARKER_GUTTER_PX, bc as resolveImporterForFile, bd as getDocumentSectionsCanonical, be as getDocumentParagraphsCanonical, bf as getDocumentParagraphs, bg as getDocumentPageSettings, bh as getTableCellContentWidthForParagraph, bi as on, bj as debounce, bk as unwrap, bl as perfTimer, bm as getRunTextBox, bn as createEditorDocument, bo as resolveResizedDimensions, bp as resolveTextBoxRenderHeight, bq as getToolbarStyleState, br as getCachedCanvasImage, bs as measureParagraphMinContentWidthPx, bt as getEditableBlocksForZone, bu as findParagraphLocation, bv as createSectionBoundaryParagraph, bw as normalizePageSettings, bx as DEFAULT_EDITOR_PAGE_SETTINGS, by as markStart, bz as markEnd, bA as getParagraphEntries, bB as getParagraphById, bC as createEditorFootnote, bD as createFootnoteReferenceRun, bE as renumberFootnotes, bF as getFootnoteDisplayMarker, bG as getHeadingLevel, bH as preciseFontModeVersion, bI as isPreciseFontModeEnabled, bJ as resolveNamedTextStyle, bK as togglePreciseFontMode, bL as nextFontSizePt, bM as previousFontSizePt, bN as fontSizePtToPx, bO as createDefaultToolbarPreset, bP as MenuRegistry, bQ as createToolbarRegistry, bR as Editor, bS as resolveCommandRef, bT as commandRefName, bU as createOasisEditorClient, bV as createEditorZoom, bW as startLongTaskObserver, bX as installGlobalReport, bY as applyStoredPreciseFontPreference, bZ as getWelcomeSeen, b_ as isLocalFontAccessSupported, b$ as EDITOR_SCROLL_PADDING_PX, c0 as Toolbar, c1 as OasisEditorLoading, c2 as I18nProvider, c3 as createTranslator, c4 as createEditorLogger, c5 as registerDomStatsSurface } from "./index-C2DlzueH.js";
5
5
  function cloneStyle(style2) {
6
6
  return style2 ? { ...style2 } : void 0;
7
7
  }
@@ -30434,7 +30434,11 @@ function createEditorTableContextMenuActions(deps) {
30434
30434
  };
30435
30435
  }
30436
30436
  function createEditorChrome(deps) {
30437
- const { computeFontFamilyOptions: computeFontFamilyOptions2, computeFontSizeOptions: computeFontSizeOptions2, loadLocalFontFamilyOptions } = createEditorFontOptions({
30437
+ const {
30438
+ computeFontFamilyOptions: computeFontFamilyOptions2,
30439
+ computeFontSizeOptions: computeFontSizeOptions2,
30440
+ loadLocalFontFamilyOptions
30441
+ } = createEditorFontOptions({
30438
30442
  state: deps.state,
30439
30443
  toolbarStyleState: deps.toolbarStyleState
30440
30444
  });
@@ -33181,6 +33185,10 @@ function serializeParagraphBorders(style2) {
33181
33185
  const DEFAULT_TABLE_BORDER_COLOR = "6F6F6F";
33182
33186
  const DEFAULT_TABLE_BORDER_WIDTH_PT = 0.75;
33183
33187
  const DEFAULT_CELL_PADDING_LEFT_RIGHT_PT = 5.4;
33188
+ function serializeExtAttributes(attrs) {
33189
+ if (!attrs) return "";
33190
+ return Object.entries(attrs).map(([name, value]) => ` ${name}="${escapeXml(value)}"`).join("");
33191
+ }
33184
33192
  function serializeRevisionAttrs(revision) {
33185
33193
  const numericId = /^\d+$/.test(revision.id) ? revision.id : String(
33186
33194
  Array.from(revision.id).reduce(
@@ -33441,10 +33449,11 @@ function serializeTableRowStyleXml(style2) {
33441
33449
  if (hidden) parts.push(hidden);
33442
33450
  const header = serializeOnOffElement("tblHeader", style2.isHeader);
33443
33451
  if (header) parts.push(header);
33452
+ if (style2.align) parts.push(`<w:jc w:val="${style2.align}"/>`);
33444
33453
  return parts.length > 0 ? `<w:trPr>${parts.join("")}</w:trPr>` : "";
33445
33454
  }
33446
33455
  function serializeTableRowProperties(row) {
33447
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
33456
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
33448
33457
  const parts = [];
33449
33458
  const conditional = serializeConditionalFlags(row.conditionalStyle);
33450
33459
  if (conditional) parts.push(conditional);
@@ -33471,13 +33480,14 @@ function serializeTableRowProperties(row) {
33471
33480
  if (((_g = row.style) == null ? void 0 : _g.isHeader) ?? row.isHeader) parts.push("<w:tblHeader/>");
33472
33481
  const hidden = serializeOnOffElement("hidden", (_h = row.style) == null ? void 0 : _h.hidden);
33473
33482
  if (hidden) parts.push(hidden);
33474
- if ((_i = row.style) == null ? void 0 : _i.propertyRevision) {
33483
+ if ((_i = row.style) == null ? void 0 : _i.align) parts.push(`<w:jc w:val="${row.style.align}"/>`);
33484
+ if ((_j = row.style) == null ? void 0 : _j.propertyRevision) {
33475
33485
  const revision = row.style.propertyRevision;
33476
33486
  parts.push(
33477
33487
  `<w:trPrChange ${serializeRevisionAttrs(revision)}>${serializeTableRowStyleXml(revision.previous)}</w:trPrChange>`
33478
33488
  );
33479
33489
  }
33480
- if (((_j = row.style) == null ? void 0 : _j.revision) && row.style.revision.type !== "merge") {
33490
+ if (((_k = row.style) == null ? void 0 : _k.revision) && row.style.revision.type !== "merge") {
33481
33491
  const revision = row.style.revision;
33482
33492
  const element = revision.type === "insert" ? "ins" : "del";
33483
33493
  parts.push(`<w:${element} ${serializeRevisionAttrs(revision)}/>`);
@@ -33595,6 +33605,46 @@ function serializeTableProperties(table) {
33595
33605
  }
33596
33606
  return `<w:tblPr>${parts.join("")}</w:tblPr>`;
33597
33607
  }
33608
+ function serializeTablePropertyExceptions(exceptions, tblPrExChangeXml) {
33609
+ if (!exceptions && !tblPrExChangeXml) {
33610
+ return "";
33611
+ }
33612
+ const parts = [];
33613
+ if ((exceptions == null ? void 0 : exceptions.width) !== void 0) {
33614
+ parts.push(serializeTableWidth(exceptions.width));
33615
+ }
33616
+ if (exceptions == null ? void 0 : exceptions.align) {
33617
+ parts.push(`<w:jc w:val="${exceptions.align}"/>`);
33618
+ }
33619
+ const cellSpacingXml = serializeDocxWidthElement(
33620
+ "tblCellSpacing",
33621
+ exceptions == null ? void 0 : exceptions.cellSpacing
33622
+ );
33623
+ if (cellSpacingXml) {
33624
+ parts.push(cellSpacingXml);
33625
+ }
33626
+ const indentXml = serializeDocxWidthElement("tblInd", exceptions == null ? void 0 : exceptions.indentLeft);
33627
+ if (indentXml) {
33628
+ parts.push(indentXml);
33629
+ }
33630
+ const bordersXml = exceptions ? serializeTableBorders(exceptions) : "";
33631
+ if (bordersXml) {
33632
+ parts.push(bordersXml);
33633
+ }
33634
+ if (exceptions == null ? void 0 : exceptions.layout) {
33635
+ parts.push(`<w:tblLayout w:type="${exceptions.layout}"/>`);
33636
+ }
33637
+ const marginsXml = serializeTableDefaultCellMargins(
33638
+ exceptions == null ? void 0 : exceptions.defaultCellMargins
33639
+ );
33640
+ if (marginsXml) {
33641
+ parts.push(marginsXml);
33642
+ }
33643
+ if (tblPrExChangeXml) {
33644
+ parts.push(tblPrExChangeXml);
33645
+ }
33646
+ return parts.length > 0 ? `<w:tblPrEx>${parts.join("")}</w:tblPrEx>` : "";
33647
+ }
33598
33648
  function serializeTableXml(table, serializeParagraphXml2) {
33599
33649
  const tableLayout = buildTableCellLayout(table);
33600
33650
  const tableEntriesByKey = new Map(
@@ -33618,9 +33668,9 @@ function serializeTableXml(table, serializeParagraphXml2) {
33618
33668
  ];
33619
33669
  const paragraphsXml = paragraphs.map((paragraph) => serializeParagraphXml2(paragraph, cell)).join("");
33620
33670
  const contentXml = cell.vMerge === "continue" ? "<w:p/>" : paragraphsXml;
33621
- return `<w:tc>${serializeTableCellProperties(cell, fallbackWidthPt)}${contentXml}</w:tc>`;
33671
+ return `<w:tc${serializeExtAttributes(cell.extAttributes)}>${serializeTableCellProperties(cell, fallbackWidthPt)}${contentXml}</w:tc>`;
33622
33672
  }).join("");
33623
- return `<w:tr>${row.tblPrExXml ?? ""}${serializeTableRowProperties(row)}${cellsXml}</w:tr>`;
33673
+ return `<w:tr${serializeExtAttributes(row.extAttributes)}>${serializeTablePropertyExceptions(row.propertyExceptions, row.tblPrExChangeXml)}${serializeTableRowProperties(row)}${cellsXml}</w:tr>`;
33624
33674
  }).join("");
33625
33675
  const gridXml = table.gridCols ? `<w:tblGrid>${table.gridCols.map((width) => `<w:gridCol w:w="${pointsToTwips(width) ?? 0}"/>`).join("")}${table.gridRevision ? `<w:tblGridChange ${serializeRevisionAttrs(table.gridRevision)}><w:tblGrid>${table.gridRevision.previous.map((width) => `<w:gridCol w:w="${pointsToTwips(width) ?? 0}"/>`).join("")}</w:tblGrid></w:tblGridChange>` : ""}</w:tblGrid>` : "";
33626
33676
  return `<w:tbl>${serializeTableProperties(table)}${gridXml}${rowsXml}</w:tbl>`;
@@ -33675,6 +33725,16 @@ function materializeRunStyle(run, paragraphStyleId, styles) {
33675
33725
  noProof: effective.noProof,
33676
33726
  webHidden: effective.webHidden,
33677
33727
  specVanish: effective.specVanish,
33728
+ rtl: effective.rtl,
33729
+ complexScript: effective.complexScript,
33730
+ snapToGrid: effective.snapToGrid,
33731
+ fitText: effective.fitText,
33732
+ emphasisMark: effective.emphasisMark,
33733
+ textBorder: effective.textBorder,
33734
+ outline: effective.outline,
33735
+ shadow: effective.shadow,
33736
+ emboss: effective.emboss,
33737
+ imprint: effective.imprint,
33678
33738
  textEffect: effective.textEffect,
33679
33739
  characterScale: effective.characterScale,
33680
33740
  characterSpacing: effective.characterSpacing,
@@ -33972,15 +34032,23 @@ function serializeRunProperties(styles) {
33972
34032
  }
33973
34033
  if (styles.strike) parts.push("<w:strike/>");
33974
34034
  if (styles.doubleStrike) parts.push("<w:dstrike/>");
34035
+ if (styles.outline) parts.push("<w:outline/>");
34036
+ if (styles.shadow) parts.push("<w:shadow/>");
34037
+ if (styles.emboss) parts.push("<w:emboss/>");
34038
+ if (styles.imprint) parts.push("<w:imprint/>");
33975
34039
  if (styles.smallCaps) parts.push("<w:smallCaps/>");
33976
34040
  if (styles.allCaps) parts.push("<w:caps/>");
33977
34041
  if (styles.hidden) parts.push("<w:vanish/>");
33978
34042
  if (styles.noProof) parts.push("<w:noProof/>");
33979
34043
  if (styles.webHidden) parts.push("<w:webHidden/>");
33980
34044
  if (styles.specVanish) parts.push("<w:specVanish/>");
34045
+ if (styles.snapToGrid === false) parts.push('<w:snapToGrid w:val="0"/>');
33981
34046
  if (styles.textEffect) {
33982
34047
  parts.push(`<w:effect w:val="${escapeXml(styles.textEffect)}"/>`);
33983
34048
  }
34049
+ if (styles.textBorder) {
34050
+ parts.push(`<w:bdr ${serializeDocxBorderAttrs(styles.textBorder)}`);
34051
+ }
33984
34052
  if (styles.characterScale !== void 0 && styles.characterScale !== null && Number.isFinite(styles.characterScale)) {
33985
34053
  parts.push(
33986
34054
  `<w:w w:val="${Math.max(1, Math.round(styles.characterScale))}"/>`
@@ -34048,6 +34116,17 @@ function serializeRunProperties(styles) {
34048
34116
  `<w:shd w:val="clear" w:color="auto" w:fill="${normalizeDocxColor(styles.shading, "FFFFFF")}"/>`
34049
34117
  );
34050
34118
  }
34119
+ if (styles.fitText !== void 0 && styles.fitText !== null && Number.isFinite(styles.fitText)) {
34120
+ const twips = pointsToSignedTwips(styles.fitText);
34121
+ if (twips !== null && twips > 0) {
34122
+ parts.push(`<w:fitText w:val="${twips}"/>`);
34123
+ }
34124
+ }
34125
+ if (styles.rtl) parts.push("<w:rtl/>");
34126
+ if (styles.complexScript) parts.push("<w:cs/>");
34127
+ if (styles.emphasisMark) {
34128
+ parts.push(`<w:em w:val="${escapeXml(styles.emphasisMark)}"/>`);
34129
+ }
34051
34130
  if (styles.language) {
34052
34131
  const attrs = [];
34053
34132
  if (styles.language.value) {
@@ -34777,31 +34856,17 @@ const CONDITIONAL_TYPE_ORDER = [
34777
34856
  "seCell"
34778
34857
  ];
34779
34858
  function serializeConditionalTcPr(cond) {
34780
- if (cond.cellStyle) {
34781
- return serializeTableCellStyleXml(cond.cellStyle);
34782
- }
34783
- const parts = [];
34784
- if (cond.borders) {
34785
- const b = cond.borders;
34786
- const edges = [
34787
- ["top", b.borderTop],
34788
- ["left", b.borderLeft],
34789
- ["bottom", b.borderBottom],
34790
- ["right", b.borderRight]
34791
- ];
34792
- const borderXml = edges.filter(
34793
- (entry) => entry[1] != null
34794
- ).map(([name, border]) => `<w:${name} ${serializeDocxBorderAttrs(border)}`).join("");
34795
- if (borderXml) {
34796
- parts.push(`<w:tcBorders>${borderXml}</w:tcBorders>`);
34797
- }
34798
- }
34799
- if (cond.shading) {
34800
- parts.push(
34801
- `<w:shd w:val="clear" w:color="auto" w:fill="${normalizeDocxColor(cond.shading, "FFFFFF")}"/>`
34802
- );
34803
- }
34804
- return parts.length > 0 ? `<w:tcPr>${parts.join("")}</w:tcPr>` : "";
34859
+ const cellStyle = {
34860
+ ...cond.borders ? {
34861
+ ...cond.borders.borderTop ? { borderTop: cond.borders.borderTop } : {},
34862
+ ...cond.borders.borderLeft ? { borderLeft: cond.borders.borderLeft } : {},
34863
+ ...cond.borders.borderBottom ? { borderBottom: cond.borders.borderBottom } : {},
34864
+ ...cond.borders.borderRight ? { borderRight: cond.borders.borderRight } : {}
34865
+ } : {},
34866
+ ...cond.shading ? { shading: cond.shading } : {},
34867
+ ...cond.cellStyle
34868
+ };
34869
+ return Object.keys(cellStyle).length > 0 ? serializeTableCellStyleXml(cellStyle) : "";
34805
34870
  }
34806
34871
  function serializeWidthElement(name, value) {
34807
34872
  if (typeof value === "number") {
@@ -35000,7 +35065,7 @@ function serializeNoteSettings(tagName, settings) {
35000
35065
  }
35001
35066
  return parts.length > 0 ? `<w:${tagName}>${parts.join("")}</w:${tagName}>` : null;
35002
35067
  }
35003
- function buildSettingsXml(hasEvenAndOddHeaders, defaultTabStop, footnoteSettings, endnoteSettings) {
35068
+ function buildSettingsXml(hasEvenAndOddHeaders, defaultTabStop, footnoteSettings, endnoteSettings, allowSpaceOfSameStyleInTable) {
35004
35069
  const parts = [];
35005
35070
  const defaultTabStopTwips = pointsToTwips(defaultTabStop);
35006
35071
  if (defaultTabStopTwips !== null) {
@@ -35017,6 +35082,11 @@ function buildSettingsXml(hasEvenAndOddHeaders, defaultTabStop, footnoteSettings
35017
35082
  if (hasEvenAndOddHeaders) {
35018
35083
  parts.push("<w:evenAndOddHeaders/>");
35019
35084
  }
35085
+ if (allowSpaceOfSameStyleInTable) {
35086
+ parts.push(
35087
+ `<w:compat><w:allowSpaceOfSameStyleInTable/></w:compat>`
35088
+ );
35089
+ }
35020
35090
  return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:settings xmlns:w="${WORD_NS$1}">${parts.join("")}</w:settings>`;
35021
35091
  }
35022
35092
  function buildPartRelationshipsXml(images, hyperlinks) {
@@ -35449,7 +35519,7 @@ function buildPartContext(blocks, numberingContext, state, document2) {
35449
35519
  };
35450
35520
  }
35451
35521
  async function exportEditorDocumentToDocx(document2) {
35452
- var _a, _b, _c, _d, _e, _f;
35522
+ var _a, _b, _c, _d, _e, _f, _g, _h;
35453
35523
  document2 = renumberImageCaptionsInDocument(document2);
35454
35524
  const zip = new JSZip();
35455
35525
  const numberingContext = buildNumberingContext(document2);
@@ -35534,7 +35604,7 @@ async function exportEditorDocumentToDocx(document2) {
35534
35604
  return (((_a2 = section.evenPageHeader) == null ? void 0 : _a2.length) ?? 0) > 0 || (((_b2 = section.evenPageFooter) == null ? void 0 : _b2.length) ?? 0) > 0;
35535
35605
  }
35536
35606
  );
35537
- const hasDocumentSettings = hasEvenAndOddHeaders || ((_a = document2.settings) == null ? void 0 : _a.defaultTabStop) !== void 0 || ((_b = document2.footnotes) == null ? void 0 : _b.settings) !== void 0 || ((_c = document2.endnotes) == null ? void 0 : _c.settings) !== void 0;
35607
+ const hasDocumentSettings = hasEvenAndOddHeaders || ((_a = document2.settings) == null ? void 0 : _a.defaultTabStop) !== void 0 || ((_b = document2.settings) == null ? void 0 : _b.allowSpaceOfSameStyleInTable) !== void 0 || ((_c = document2.footnotes) == null ? void 0 : _c.settings) !== void 0 || ((_d = document2.endnotes) == null ? void 0 : _d.settings) !== void 0;
35538
35608
  const allImages = [
35539
35609
  ...bodyContext.images,
35540
35610
  ...parts.flatMap((part) => part.context.images)
@@ -35616,9 +35686,10 @@ async function exportEditorDocumentToDocx(document2) {
35616
35686
  "word/settings.xml",
35617
35687
  buildSettingsXml(
35618
35688
  hasEvenAndOddHeaders,
35619
- (_d = document2.settings) == null ? void 0 : _d.defaultTabStop,
35620
- (_e = document2.footnotes) == null ? void 0 : _e.settings,
35621
- (_f = document2.endnotes) == null ? void 0 : _f.settings
35689
+ (_e = document2.settings) == null ? void 0 : _e.defaultTabStop,
35690
+ (_f = document2.footnotes) == null ? void 0 : _f.settings,
35691
+ (_g = document2.endnotes) == null ? void 0 : _g.settings,
35692
+ (_h = document2.settings) == null ? void 0 : _h.allowSpaceOfSameStyleInTable
35622
35693
  )
35623
35694
  );
35624
35695
  }
@@ -36130,6 +36201,63 @@ function drawFragmentShading(writer, pageIndex, line, fragment, originX, originY
36130
36201
  fill: styles.shading
36131
36202
  });
36132
36203
  }
36204
+ function drawFragmentBorder(writer, pageIndex, line, fragment, originX, originY, styles) {
36205
+ const border = styles.textBorder;
36206
+ if (!border || border.type === "none" || border.width <= 0) {
36207
+ return;
36208
+ }
36209
+ const bounds = resolveFragmentBounds(
36210
+ line,
36211
+ fragment,
36212
+ styles.fontSize ?? DEFAULT_FONT_SIZE_PX
36213
+ );
36214
+ if (!bounds) {
36215
+ return;
36216
+ }
36217
+ writer.drawRect(pageIndex, {
36218
+ x: pxToPt$1(originX + bounds.left),
36219
+ y: pxToPt$1(originY + line.top + 1),
36220
+ width: pxToPt$1(Math.max(0, bounds.right - bounds.left)),
36221
+ height: pxToPt$1(Math.max(2, line.height - 2)),
36222
+ stroke: border.color,
36223
+ lineWidth: pxToPt$1(Math.max(0.5, border.width * PX_PER_POINT))
36224
+ });
36225
+ }
36226
+ const PDF_EMPHASIS_GLYPH = {
36227
+ dot: "•",
36228
+ comma: "‚",
36229
+ circle: "○",
36230
+ underDot: "•"
36231
+ };
36232
+ function drawFragmentEmphasis(writer, pageIndex, line, fragment, originX, originY, styles) {
36233
+ const mark = styles.emphasisMark;
36234
+ if (!mark || mark === "none") {
36235
+ return;
36236
+ }
36237
+ const glyph = PDF_EMPHASIS_GLYPH[mark];
36238
+ if (!glyph) {
36239
+ return;
36240
+ }
36241
+ const slots = resolveFragmentSlots(line, fragment);
36242
+ const below = mark === "underDot";
36243
+ const size = Math.max(4, line.height * 0.35);
36244
+ const y = below ? originY + line.top + line.height + size : originY + line.top + size;
36245
+ for (let i = 0; i < slots.length; i += 1) {
36246
+ const slot = slots[i];
36247
+ if (slot.char === " " || slot.char === " " || slot.char === "\n") {
36248
+ continue;
36249
+ }
36250
+ const next = slots[i + 1];
36251
+ const centerX = next ? (slot.left + next.left) / 2 : slot.left + line.height * 0.25;
36252
+ writer.drawText(pageIndex, {
36253
+ x: pxToPt$1(originX + centerX - size * 0.25),
36254
+ y: pxToPt$1(y),
36255
+ text: glyph,
36256
+ fontSize: pxToPt$1(size),
36257
+ color: styles.color ?? "#000000"
36258
+ });
36259
+ }
36260
+ }
36133
36261
  function drawFragmentDecoration(writer, pageIndex, line, fragment, originX, originY, styles, kind) {
36134
36262
  const bounds = resolveFragmentBounds(
36135
36263
  line,
@@ -36410,6 +36538,15 @@ async function drawFragmentText(writer, pageIndex, paragraph, line, fragment, do
36410
36538
  originY,
36411
36539
  styles
36412
36540
  );
36541
+ drawFragmentBorder(
36542
+ writer,
36543
+ pageIndex,
36544
+ line,
36545
+ fragment,
36546
+ originX,
36547
+ originY,
36548
+ styles
36549
+ );
36413
36550
  drawTabLeaders(
36414
36551
  writer,
36415
36552
  pageIndex,
@@ -36422,42 +36559,50 @@ async function drawFragmentText(writer, pageIndex, paragraph, line, fragment, do
36422
36559
  styles.color ?? "#000000"
36423
36560
  );
36424
36561
  const paragraphAlign = resolveEffectiveParagraphStyle(paragraph.style, document2.styles).align ?? "left";
36425
- if (paragraphAlign === "justify") {
36426
- const chunks = groupSlotChunksByWhitespace(chars);
36427
- for (const chunk of chunks) {
36428
- const chunkText = chunk.map((c) => styles.allCaps ? c.char.toUpperCase() : c.char).join("");
36429
- if (chunkText.length === 0) continue;
36562
+ const baseTextOptions = {
36563
+ fontSize: fontSizePt,
36564
+ bold: styles.bold,
36565
+ italic: styles.italic,
36566
+ fontResourceName: fontFace.writerResourceName,
36567
+ characterSpacing: styles.characterSpacing ?? 0,
36568
+ horizontalScale: styles.characterScale ?? 100
36569
+ };
36570
+ const mainColor = styles.color ?? "#000000";
36571
+ const offsetPt = pxToPt$1(1);
36572
+ const emitChunk = (leftPx, text2) => {
36573
+ if (styles.emboss || styles.imprint) {
36574
+ const dir = styles.imprint ? 1 : -1;
36430
36575
  writer.drawText(pageIndex, {
36431
- x: pxToPt$1(originX + chunk[0].left),
36432
- y: pxToPt$1(baselineY),
36433
- text: chunkText,
36434
- fontSize: fontSizePt,
36435
- color: styles.color ?? "#000000",
36436
- bold: styles.bold,
36437
- italic: styles.italic,
36438
- fontResourceName: fontFace.writerResourceName,
36439
- characterSpacing: styles.characterSpacing ?? 0,
36440
- horizontalScale: styles.characterScale ?? 100
36576
+ ...baseTextOptions,
36577
+ x: pxToPt$1(leftPx) + offsetPt * dir,
36578
+ y: pxToPt$1(baselineY) + offsetPt * dir,
36579
+ text: text2,
36580
+ color: "#BFBFBF"
36441
36581
  });
36442
36582
  }
36443
- } else {
36444
- const chunks = groupSlotChunksByOffsetGaps(chars);
36445
- for (const chunk of chunks) {
36446
- const chunkText = chunk.map((c) => styles.allCaps ? c.char.toUpperCase() : c.char).join("");
36447
- if (chunkText.length === 0) continue;
36583
+ if (styles.shadow) {
36448
36584
  writer.drawText(pageIndex, {
36449
- x: pxToPt$1(originX + chunk[0].left),
36450
- y: pxToPt$1(baselineY),
36451
- text: chunkText,
36452
- fontSize: fontSizePt,
36453
- color: styles.color ?? "#000000",
36454
- bold: styles.bold,
36455
- italic: styles.italic,
36456
- fontResourceName: fontFace.writerResourceName,
36457
- characterSpacing: styles.characterSpacing ?? 0,
36458
- horizontalScale: styles.characterScale ?? 100
36585
+ ...baseTextOptions,
36586
+ x: pxToPt$1(leftPx) + offsetPt,
36587
+ y: pxToPt$1(baselineY) + offsetPt,
36588
+ text: text2,
36589
+ color: "#808080"
36459
36590
  });
36460
36591
  }
36592
+ writer.drawText(pageIndex, {
36593
+ ...baseTextOptions,
36594
+ x: pxToPt$1(leftPx),
36595
+ y: pxToPt$1(baselineY),
36596
+ text: text2,
36597
+ color: mainColor,
36598
+ renderMode: styles.outline ? 1 : 0
36599
+ });
36600
+ };
36601
+ const chunks = paragraphAlign === "justify" ? groupSlotChunksByWhitespace(chars) : groupSlotChunksByOffsetGaps(chars);
36602
+ for (const chunk of chunks) {
36603
+ const chunkText = chunk.map((c) => styles.allCaps ? c.char.toUpperCase() : c.char).join("");
36604
+ if (chunkText.length === 0) continue;
36605
+ emitChunk(originX + chunk[0].left, chunkText);
36461
36606
  }
36462
36607
  if (styles.underline) {
36463
36608
  drawFragmentDecoration(
@@ -36495,6 +36640,17 @@ async function drawFragmentText(writer, pageIndex, paragraph, line, fragment, do
36495
36640
  "doubleStrike"
36496
36641
  );
36497
36642
  }
36643
+ if (styles.emphasisMark) {
36644
+ drawFragmentEmphasis(
36645
+ writer,
36646
+ pageIndex,
36647
+ line,
36648
+ fragment,
36649
+ originX,
36650
+ originY,
36651
+ styles
36652
+ );
36653
+ }
36498
36654
  }
36499
36655
  function getListOrdinals(document2) {
36500
36656
  return buildListLabels(document2);
@@ -37066,227 +37222,6 @@ class PdfFontRegistry {
37066
37222
  return matchedFamilies;
37067
37223
  }
37068
37224
  }
37069
- class SimpleTextLayouter {
37070
- constructor(font) {
37071
- this.font = font;
37072
- }
37073
- layout(text) {
37074
- const glyphs = [];
37075
- const positions = [];
37076
- let advanceWidth = 0;
37077
- for (const char of text) {
37078
- const codePoint = char.codePointAt(0) ?? 65533;
37079
- const glyphId = this.font.glyphForCodePoint(codePoint);
37080
- const glyphAdvance = this.font.advanceWidthForGlyph(glyphId);
37081
- glyphs.push({
37082
- id: glyphId,
37083
- codePoints: glyphId === 0 ? [65533] : [codePoint],
37084
- advanceWidth: glyphAdvance
37085
- });
37086
- positions.push({ xAdvance: glyphAdvance });
37087
- advanceWidth += glyphAdvance;
37088
- }
37089
- return { glyphs, positions, advanceWidth };
37090
- }
37091
- }
37092
- function view(bytes) {
37093
- return new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
37094
- }
37095
- function u16(bytes, offset) {
37096
- return view(bytes).getUint16(offset);
37097
- }
37098
- function i16(bytes, offset) {
37099
- return view(bytes).getInt16(offset);
37100
- }
37101
- function writeU16(target, offset, value) {
37102
- view(target).setUint16(offset, value, false);
37103
- }
37104
- function writeU32(target, offset, value) {
37105
- view(target).setUint32(offset, value, false);
37106
- }
37107
- function pad4(length) {
37108
- return length + 3 & -4;
37109
- }
37110
- function concat(chunks) {
37111
- const total = chunks.reduce((sum, chunk) => sum + pad4(chunk.byteLength), 0);
37112
- const result = new Uint8Array(total);
37113
- let offset = 0;
37114
- for (const chunk of chunks) {
37115
- result.set(chunk, offset);
37116
- offset += pad4(chunk.byteLength);
37117
- }
37118
- return result;
37119
- }
37120
- function readLoca(loca, indexToLocFormat) {
37121
- const offsets = [];
37122
- const table = view(loca);
37123
- if (indexToLocFormat === 0) {
37124
- for (let offset = 0; offset + 1 < loca.byteLength; offset += 2) {
37125
- offsets.push(table.getUint16(offset) * 2);
37126
- }
37127
- } else {
37128
- for (let offset = 0; offset + 3 < loca.byteLength; offset += 4) {
37129
- offsets.push(table.getUint32(offset));
37130
- }
37131
- }
37132
- return offsets;
37133
- }
37134
- function glyphRange(offsets, glyphId) {
37135
- const start = offsets[glyphId];
37136
- const end = offsets[glyphId + 1];
37137
- return start === void 0 || end === void 0 ? null : { start, end };
37138
- }
37139
- function collectCompositeGlyphs(glyph, addGlyph) {
37140
- if (glyph.byteLength < 10 || i16(glyph, 0) >= 0) {
37141
- return;
37142
- }
37143
- let offset = 10;
37144
- let flags = 0;
37145
- do {
37146
- if (offset + 4 > glyph.byteLength) return;
37147
- flags = u16(glyph, offset);
37148
- addGlyph(u16(glyph, offset + 2));
37149
- offset += 4;
37150
- offset += flags & 1 ? 4 : 2;
37151
- if (flags & 8) offset += 2;
37152
- else if (flags & 64) offset += 4;
37153
- else if (flags & 128) offset += 8;
37154
- } while (flags & 32);
37155
- }
37156
- function subsetClosure(font, initialGlyphs) {
37157
- const glyf = font.getRawTableData("glyf");
37158
- const loca = font.getRawTableData("loca");
37159
- const head = font.getRawTableData("head");
37160
- if (!glyf || !loca || !head) {
37161
- return Array.from(/* @__PURE__ */ new Set([0, ...initialGlyphs])).sort((a, b) => a - b);
37162
- }
37163
- const offsets = readLoca(loca, u16(head, 50));
37164
- const used = /* @__PURE__ */ new Set([0, ...initialGlyphs]);
37165
- const stack = Array.from(used);
37166
- while (stack.length > 0) {
37167
- const glyphId = stack.pop();
37168
- const range = glyphRange(offsets, glyphId);
37169
- if (!range || range.end <= range.start || range.end > glyf.byteLength) {
37170
- continue;
37171
- }
37172
- const glyph = glyf.slice(range.start, range.end);
37173
- collectCompositeGlyphs(glyph, (componentId) => {
37174
- if (!used.has(componentId)) {
37175
- used.add(componentId);
37176
- stack.push(componentId);
37177
- }
37178
- });
37179
- }
37180
- return Array.from(used).sort((a, b) => a - b);
37181
- }
37182
- function buildLoca(offsets) {
37183
- const loca = new Uint8Array(offsets.length * 4);
37184
- offsets.forEach((offset, index) => writeU32(loca, index * 4, offset));
37185
- return loca;
37186
- }
37187
- function buildHmtx(font, maxGlyphId) {
37188
- const hmtx = new Uint8Array((maxGlyphId + 1) * 4);
37189
- for (let glyphId = 0; glyphId <= maxGlyphId; glyphId += 1) {
37190
- writeU16(hmtx, glyphId * 4, font.advanceWidthForGlyph(glyphId));
37191
- writeU16(hmtx, glyphId * 4 + 2, 0);
37192
- }
37193
- return hmtx;
37194
- }
37195
- function buildSubsetTables(font, glyphIds) {
37196
- const glyf = font.getRawTableData("glyf");
37197
- const loca = font.getRawTableData("loca");
37198
- const head = font.getRawTableData("head");
37199
- const hhea = font.getRawTableData("hhea");
37200
- const maxp = font.getRawTableData("maxp");
37201
- const cmap = font.getRawTableData("cmap");
37202
- if (!glyf || !loca || !head || !hhea || !maxp || !cmap) {
37203
- throw new Error("Missing required TrueType tables for subsetting");
37204
- }
37205
- const maxGlyphId = Math.max(0, ...glyphIds);
37206
- const used = new Set(glyphIds);
37207
- const sourceOffsets = readLoca(loca, u16(head, 50));
37208
- const locaOffsets = [];
37209
- const glyfChunks = [];
37210
- let glyfOffset = 0;
37211
- for (let glyphId = 0; glyphId <= maxGlyphId; glyphId += 1) {
37212
- locaOffsets.push(glyfOffset);
37213
- const range = glyphRange(sourceOffsets, glyphId);
37214
- if (used.has(glyphId) && range && range.end > range.start) {
37215
- const glyph = glyf.slice(range.start, range.end);
37216
- glyfChunks.push(glyph);
37217
- glyfOffset += pad4(glyph.byteLength);
37218
- }
37219
- }
37220
- locaOffsets.push(glyfOffset);
37221
- const newHead = head.slice();
37222
- writeU32(newHead, 8, 0);
37223
- writeU16(newHead, 50, 1);
37224
- const newHhea = hhea.slice();
37225
- writeU16(newHhea, 34, maxGlyphId + 1);
37226
- const newMaxp = maxp.slice();
37227
- writeU16(newMaxp, 4, maxGlyphId + 1);
37228
- const tables = {
37229
- cmap,
37230
- head: newHead,
37231
- hhea: newHhea,
37232
- hmtx: buildHmtx(font, maxGlyphId),
37233
- loca: buildLoca(locaOffsets),
37234
- maxp: newMaxp,
37235
- glyf: concat(glyfChunks)
37236
- };
37237
- for (const tag of ["OS/2", "name", "post"]) {
37238
- const table = font.getRawTableData(tag);
37239
- if (table) tables[tag] = table;
37240
- }
37241
- return tables;
37242
- }
37243
- class TrueTypePdfFontSubsetter {
37244
- createSubset(font, glyphs) {
37245
- const unicodeByGlyph = /* @__PURE__ */ new Map();
37246
- const initialGlyphs = [];
37247
- for (const glyph of glyphs) {
37248
- initialGlyphs.push(glyph.id);
37249
- if (!unicodeByGlyph.has(glyph.id)) {
37250
- unicodeByGlyph.set(glyph.id, glyph.codePoints);
37251
- }
37252
- }
37253
- const glyphIds = subsetClosure(font, initialGlyphs);
37254
- const tables = buildSubsetTables(font, glyphIds);
37255
- const fontFile = buildSfnt(
37256
- 65536,
37257
- new Map(
37258
- Object.entries(tables).map(([tag, data]) => [
37259
- tag.charCodeAt(0) << 24 | tag.charCodeAt(1) << 16 | tag.charCodeAt(2) << 8 | tag.charCodeAt(3),
37260
- data
37261
- ])
37262
- )
37263
- ).ttf;
37264
- const maxGlyphId = Math.max(0, ...glyphIds);
37265
- const widths = [];
37266
- const unicode = [];
37267
- for (let glyphId = 0; glyphId <= maxGlyphId; glyphId += 1) {
37268
- widths[glyphId] = font.advanceWidthForGlyph(glyphId) / font.unitsPerEm * 1e3;
37269
- unicode[glyphId] = unicodeByGlyph.get(glyphId) ?? [0];
37270
- }
37271
- return {
37272
- fontFile,
37273
- widths,
37274
- unicode,
37275
- encodeGlyph: (glyphId) => glyphId
37276
- };
37277
- }
37278
- }
37279
- function parseEmbeddedFontSync(sourceBytes) {
37280
- const sfntBytes = defaultFontDecoderRegistry.decodeSync(sourceBytes);
37281
- return SfntFontProgram.parse(sfntBytes);
37282
- }
37283
- function createPdfEmbeddableFont(program) {
37284
- return {
37285
- program,
37286
- layouter: new SimpleTextLayouter(program),
37287
- subsetter: new TrueTypePdfFontSubsetter()
37288
- };
37289
- }
37290
37225
  const PDF_HEADER = "%PDF-1.4\n% Oasis PDF\n";
37291
37226
  const DEFAULT_PDF_FONT_RESOURCES = [
37292
37227
  { kind: "base14", resourceName: "F1", baseFont: "Helvetica" },
@@ -37480,53 +37415,15 @@ function textMarkerComment(value) {
37480
37415
  );
37481
37416
  return `% OasisText ${encodePdfUtf16Hex(codePoints)}`;
37482
37417
  }
37483
- class OasisPdfWriter {
37484
- constructor(fontResources = DEFAULT_PDF_FONT_RESOURCES) {
37485
- __publicField(this, "pages", []);
37486
- __publicField(this, "fontResources", /* @__PURE__ */ new Map());
37487
- __publicField(this, "unicodeFontStates", /* @__PURE__ */ new Map());
37488
- __publicField(this, "usedFontResourceNames", /* @__PURE__ */ new Set());
37489
- __publicField(this, "imageResources", /* @__PURE__ */ new Map());
37490
- for (const resource of fontResources) {
37491
- this.registerFontResource(resource);
37492
- }
37493
- }
37494
- registerFontResource(resource) {
37495
- this.fontResources.set(resource.resourceName, resource);
37496
- if (resource.kind === "unicode" && !this.unicodeFontStates.has(resource.resourceName)) {
37497
- const font = createPdfEmbeddableFont(
37498
- parseEmbeddedFontSync(resource.fontData)
37499
- );
37500
- const scale = 1e3 / font.program.unitsPerEm;
37501
- const notdef = {
37502
- id: 0,
37503
- codePoints: [0],
37504
- advanceWidth: font.program.advanceWidthForGlyph(0)
37505
- };
37506
- this.unicodeFontStates.set(resource.resourceName, {
37507
- resource,
37508
- font,
37509
- usedGlyphs: /* @__PURE__ */ new Map([[0, notdef]]),
37510
- scale,
37511
- layoutCache: /* @__PURE__ */ new Map()
37512
- });
37513
- }
37418
+ class PdfContentStream {
37419
+ constructor(page, fonts, images) {
37420
+ this.page = page;
37421
+ this.fonts = fonts;
37422
+ this.images = images;
37514
37423
  }
37515
- addPage(size) {
37516
- this.pages.push({
37517
- width: Math.max(1, size.width),
37518
- height: Math.max(1, size.height),
37519
- commands: [],
37520
- imageResourceNames: /* @__PURE__ */ new Set()
37521
- });
37522
- return this.pages.length - 1;
37523
- }
37524
- getPageCount() {
37525
- return this.pages.length;
37526
- }
37527
- drawRect(pageIndex, options) {
37528
- const page = this.pages[pageIndex];
37529
- if (!page || options.width <= 0 || options.height <= 0) {
37424
+ drawRect(options) {
37425
+ const page = this.page;
37426
+ if (options.width <= 0 || options.height <= 0) {
37530
37427
  return;
37531
37428
  }
37532
37429
  const commands = ["q"];
@@ -37556,11 +37453,8 @@ class OasisPdfWriter {
37556
37453
  commands.push("Q");
37557
37454
  page.commands.push(commands.join("\n"));
37558
37455
  }
37559
- drawLine(pageIndex, options) {
37560
- const page = this.pages[pageIndex];
37561
- if (!page) {
37562
- return;
37563
- }
37456
+ drawLine(options) {
37457
+ const page = this.page;
37564
37458
  const dashCommand = options.dashArray && options.dashArray.length > 0 ? `[${options.dashArray.map((value) => formatNumber(value)).join(" ")}] 0 d` : null;
37565
37459
  const commands = [
37566
37460
  "q",
@@ -37581,9 +37475,9 @@ class OasisPdfWriter {
37581
37475
  // Fills/strokes an arbitrary path. Segment coordinates are in points with a
37582
37476
  // top-left origin (callers convert px→pt, like drawRect/drawLine); the y axis
37583
37477
  // is flipped here to the PDF bottom-left origin.
37584
- drawPath(pageIndex, options) {
37585
- const page = this.pages[pageIndex];
37586
- if (!page || options.segments.length === 0) {
37478
+ drawPath(options) {
37479
+ const page = this.page;
37480
+ if (options.segments.length === 0) {
37587
37481
  return;
37588
37482
  }
37589
37483
  if (!options.fill && !options.stroke) {
@@ -37632,24 +37526,18 @@ class OasisPdfWriter {
37632
37526
  }
37633
37527
  // Saves the graphics state (`q`). Pair with restoreGraphicsState. Any draw
37634
37528
  // commands emitted in between inherit the current transform/clip.
37635
- saveGraphicsState(pageIndex) {
37636
- const page = this.pages[pageIndex];
37637
- if (page) {
37638
- page.commands.push("q");
37639
- }
37529
+ saveGraphicsState() {
37530
+ this.page.commands.push("q");
37640
37531
  }
37641
- restoreGraphicsState(pageIndex) {
37642
- const page = this.pages[pageIndex];
37643
- if (page) {
37644
- page.commands.push("Q");
37645
- }
37532
+ restoreGraphicsState() {
37533
+ this.page.commands.push("Q");
37646
37534
  }
37647
37535
  // Concatenates a clockwise rotation (in degrees, matching the canvas/editor
37648
37536
  // convention) about a top-left-origin point onto the current CTM. Must sit
37649
37537
  // inside a saveGraphicsState/restoreGraphicsState pair.
37650
- rotateAbout(pageIndex, centerX, centerY, degrees) {
37651
- const page = this.pages[pageIndex];
37652
- if (!page || !degrees) {
37538
+ rotateAbout(centerX, centerY, degrees) {
37539
+ const page = this.page;
37540
+ if (!degrees) {
37653
37541
  return;
37654
37542
  }
37655
37543
  const cyf = page.height - centerY;
@@ -37664,9 +37552,9 @@ class OasisPdfWriter {
37664
37552
  }
37665
37553
  // Intersects the clip path with a rectangle (top-left origin). Must sit inside
37666
37554
  // a saveGraphicsState/restoreGraphicsState pair so the clip can be undone.
37667
- clipRect(pageIndex, x, y, width, height) {
37668
- const page = this.pages[pageIndex];
37669
- if (!page || width <= 0 || height <= 0) {
37555
+ clipRect(x, y, width, height) {
37556
+ const page = this.page;
37557
+ if (width <= 0 || height <= 0) {
37670
37558
  return;
37671
37559
  }
37672
37560
  page.commands.push(
@@ -37675,48 +37563,42 @@ class OasisPdfWriter {
37675
37563
  "n"
37676
37564
  );
37677
37565
  }
37678
- drawText(pageIndex, options) {
37679
- const page = this.pages[pageIndex];
37680
- if (!page || options.text.length === 0) {
37566
+ drawText(options) {
37567
+ if (options.text.length === 0) {
37681
37568
  return;
37682
37569
  }
37683
- const fontResourceName = resolveFontName(options);
37684
- this.usedFontResourceNames.add(fontResourceName);
37685
- const unicodeFont = this.unicodeFontStates.get(fontResourceName);
37686
- if (unicodeFont) {
37687
- this.drawUnicodeText(page, unicodeFont, options);
37570
+ const fontResourceName = this.fonts.resolveAndMarkFontName(options);
37571
+ const unicodeState = this.fonts.getUnicodeState(fontResourceName);
37572
+ const showCommand = unicodeState ? this.fonts.buildUnicodeShowCommand(unicodeState, options.text) : `<${encodePdfHexString(options.text)}> Tj`;
37573
+ if (showCommand === null) {
37688
37574
  return;
37689
37575
  }
37576
+ this.emitTextBlock(fontResourceName, showCommand, options);
37577
+ }
37578
+ emitTextBlock(fontResourceName, showCommand, options) {
37579
+ const page = this.page;
37690
37580
  page.commands.push(
37691
37581
  [
37692
37582
  textMarkerComment(options.text),
37693
37583
  "BT",
37694
37584
  colorCommand(options.color, "rg", [0, 0, 0]),
37695
37585
  `/${fontResourceName} ${formatNumber(options.fontSize ?? 12)} Tf`,
37586
+ ...options.renderMode && options.renderMode !== 0 ? [
37587
+ colorCommand(options.color, "RG", [0, 0, 0]),
37588
+ `${formatNumber(Math.max(0.3, (options.fontSize ?? 12) * 0.03))} w`,
37589
+ `${options.renderMode} Tr`
37590
+ ] : [],
37696
37591
  ...options.horizontalScale && options.horizontalScale > 0 && options.horizontalScale !== 100 ? [`${formatNumber(options.horizontalScale)} Tz`] : [],
37697
37592
  ...options.characterSpacing && options.characterSpacing !== 0 ? [`${formatNumber(options.characterSpacing)} Tc`] : [],
37698
37593
  `${formatNumber(options.x)} ${formatNumber(page.height - options.y)} Td`,
37699
- `<${encodePdfHexString(options.text)}> Tj`,
37594
+ showCommand,
37700
37595
  "ET"
37701
37596
  ].join("\n")
37702
37597
  );
37703
37598
  }
37704
- registerImageResource(resource) {
37705
- const resourceName = resource.resourceName ?? `Im${this.imageResources.size + 1}`;
37706
- if (!this.imageResources.has(resourceName)) {
37707
- this.imageResources.set(resourceName, {
37708
- resourceName,
37709
- width: Math.max(1, Math.round(resource.width)),
37710
- height: Math.max(1, Math.round(resource.height)),
37711
- data: resource.data,
37712
- filter: resource.filter
37713
- });
37714
- }
37715
- return resourceName;
37716
- }
37717
- drawImage(pageIndex, options) {
37718
- const page = this.pages[pageIndex];
37719
- if (!page || options.width <= 0 || options.height <= 0 || !this.imageResources.has(options.resourceName)) {
37599
+ drawImage(options) {
37600
+ const page = this.page;
37601
+ if (options.width <= 0 || options.height <= 0 || !this.images.has(options.resourceName)) {
37720
37602
  return;
37721
37603
  }
37722
37604
  page.imageResourceNames.add(options.resourceName);
@@ -37767,72 +37649,292 @@ class OasisPdfWriter {
37767
37649
  ].join("\n")
37768
37650
  );
37769
37651
  }
37770
- layoutUnicodeText(state, text) {
37771
- const cached = state.layoutCache.get(text);
37772
- if (cached) {
37773
- return cached;
37652
+ }
37653
+ class SimpleTextLayouter {
37654
+ constructor(font) {
37655
+ this.font = font;
37656
+ }
37657
+ layout(text) {
37658
+ const glyphs = [];
37659
+ const positions = [];
37660
+ let advanceWidth = 0;
37661
+ for (const char of text) {
37662
+ const codePoint = char.codePointAt(0) ?? 65533;
37663
+ const glyphId = this.font.glyphForCodePoint(codePoint);
37664
+ const glyphAdvance = this.font.advanceWidthForGlyph(glyphId);
37665
+ glyphs.push({
37666
+ id: glyphId,
37667
+ codePoints: glyphId === 0 ? [65533] : [codePoint],
37668
+ advanceWidth: glyphAdvance
37669
+ });
37670
+ positions.push({ xAdvance: glyphAdvance });
37671
+ advanceWidth += glyphAdvance;
37774
37672
  }
37775
- const run = state.font.layouter.layout(text);
37776
- state.layoutCache.set(text, run);
37777
- return run;
37673
+ return { glyphs, positions, advanceWidth };
37778
37674
  }
37779
- encodeUnicodeGlyphRun(state, run) {
37780
- return run.glyphs.map((glyph, index) => {
37781
- if (!state.usedGlyphs.has(glyph.id)) {
37782
- state.usedGlyphs.set(glyph.id, glyph);
37675
+ }
37676
+ function view(bytes) {
37677
+ return new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
37678
+ }
37679
+ function u16(bytes, offset) {
37680
+ return view(bytes).getUint16(offset);
37681
+ }
37682
+ function i16(bytes, offset) {
37683
+ return view(bytes).getInt16(offset);
37684
+ }
37685
+ function writeU16(target, offset, value) {
37686
+ view(target).setUint16(offset, value, false);
37687
+ }
37688
+ function writeU32(target, offset, value) {
37689
+ view(target).setUint32(offset, value, false);
37690
+ }
37691
+ function pad4(length) {
37692
+ return length + 3 & -4;
37693
+ }
37694
+ function concat(chunks) {
37695
+ const total = chunks.reduce((sum, chunk) => sum + pad4(chunk.byteLength), 0);
37696
+ const result = new Uint8Array(total);
37697
+ let offset = 0;
37698
+ for (const chunk of chunks) {
37699
+ result.set(chunk, offset);
37700
+ offset += pad4(chunk.byteLength);
37701
+ }
37702
+ return result;
37703
+ }
37704
+ function readLoca(loca, indexToLocFormat) {
37705
+ const offsets = [];
37706
+ const table = view(loca);
37707
+ if (indexToLocFormat === 0) {
37708
+ for (let offset = 0; offset + 1 < loca.byteLength; offset += 2) {
37709
+ offsets.push(table.getUint16(offset) * 2);
37710
+ }
37711
+ } else {
37712
+ for (let offset = 0; offset + 3 < loca.byteLength; offset += 4) {
37713
+ offsets.push(table.getUint32(offset));
37714
+ }
37715
+ }
37716
+ return offsets;
37717
+ }
37718
+ function glyphRange(offsets, glyphId) {
37719
+ const start = offsets[glyphId];
37720
+ const end = offsets[glyphId + 1];
37721
+ return start === void 0 || end === void 0 ? null : { start, end };
37722
+ }
37723
+ function collectCompositeGlyphs(glyph, addGlyph) {
37724
+ if (glyph.byteLength < 10 || i16(glyph, 0) >= 0) {
37725
+ return;
37726
+ }
37727
+ let offset = 10;
37728
+ let flags = 0;
37729
+ do {
37730
+ if (offset + 4 > glyph.byteLength) return;
37731
+ flags = u16(glyph, offset);
37732
+ addGlyph(u16(glyph, offset + 2));
37733
+ offset += 4;
37734
+ offset += flags & 1 ? 4 : 2;
37735
+ if (flags & 8) offset += 2;
37736
+ else if (flags & 64) offset += 4;
37737
+ else if (flags & 128) offset += 8;
37738
+ } while (flags & 32);
37739
+ }
37740
+ function subsetClosure(font, initialGlyphs) {
37741
+ const glyf = font.getRawTableData("glyf");
37742
+ const loca = font.getRawTableData("loca");
37743
+ const head = font.getRawTableData("head");
37744
+ if (!glyf || !loca || !head) {
37745
+ return Array.from(/* @__PURE__ */ new Set([0, ...initialGlyphs])).sort((a, b) => a - b);
37746
+ }
37747
+ const offsets = readLoca(loca, u16(head, 50));
37748
+ const used = /* @__PURE__ */ new Set([0, ...initialGlyphs]);
37749
+ const stack = Array.from(used);
37750
+ while (stack.length > 0) {
37751
+ const glyphId = stack.pop();
37752
+ const range = glyphRange(offsets, glyphId);
37753
+ if (!range || range.end <= range.start || range.end > glyf.byteLength) {
37754
+ continue;
37755
+ }
37756
+ const glyph = glyf.slice(range.start, range.end);
37757
+ collectCompositeGlyphs(glyph, (componentId) => {
37758
+ if (!used.has(componentId)) {
37759
+ used.add(componentId);
37760
+ stack.push(componentId);
37783
37761
  }
37784
- const position = run.positions[index];
37785
- const nominalWidth = glyph.advanceWidth * state.scale;
37786
- const desiredAdvance = ((position == null ? void 0 : position.xAdvance) ?? glyph.advanceWidth) * state.scale;
37787
- return { glyphId: glyph.id, nominalWidth, desiredAdvance };
37788
37762
  });
37789
37763
  }
37790
- drawUnicodeText(page, state, options) {
37791
- const run = this.layoutUnicodeText(state, options.text);
37764
+ return Array.from(used).sort((a, b) => a - b);
37765
+ }
37766
+ function buildLoca(offsets) {
37767
+ const loca = new Uint8Array(offsets.length * 4);
37768
+ offsets.forEach((offset, index) => writeU32(loca, index * 4, offset));
37769
+ return loca;
37770
+ }
37771
+ function buildHmtx(font, maxGlyphId) {
37772
+ const hmtx = new Uint8Array((maxGlyphId + 1) * 4);
37773
+ for (let glyphId = 0; glyphId <= maxGlyphId; glyphId += 1) {
37774
+ writeU16(hmtx, glyphId * 4, font.advanceWidthForGlyph(glyphId));
37775
+ writeU16(hmtx, glyphId * 4 + 2, 0);
37776
+ }
37777
+ return hmtx;
37778
+ }
37779
+ function buildSubsetTables(font, glyphIds) {
37780
+ const glyf = font.getRawTableData("glyf");
37781
+ const loca = font.getRawTableData("loca");
37782
+ const head = font.getRawTableData("head");
37783
+ const hhea = font.getRawTableData("hhea");
37784
+ const maxp = font.getRawTableData("maxp");
37785
+ const cmap = font.getRawTableData("cmap");
37786
+ if (!glyf || !loca || !head || !hhea || !maxp || !cmap) {
37787
+ throw new Error("Missing required TrueType tables for subsetting");
37788
+ }
37789
+ const maxGlyphId = Math.max(0, ...glyphIds);
37790
+ const used = new Set(glyphIds);
37791
+ const sourceOffsets = readLoca(loca, u16(head, 50));
37792
+ const locaOffsets = [];
37793
+ const glyfChunks = [];
37794
+ let glyfOffset = 0;
37795
+ for (let glyphId = 0; glyphId <= maxGlyphId; glyphId += 1) {
37796
+ locaOffsets.push(glyfOffset);
37797
+ const range = glyphRange(sourceOffsets, glyphId);
37798
+ if (used.has(glyphId) && range && range.end > range.start) {
37799
+ const glyph = glyf.slice(range.start, range.end);
37800
+ glyfChunks.push(glyph);
37801
+ glyfOffset += pad4(glyph.byteLength);
37802
+ }
37803
+ }
37804
+ locaOffsets.push(glyfOffset);
37805
+ const newHead = head.slice();
37806
+ writeU32(newHead, 8, 0);
37807
+ writeU16(newHead, 50, 1);
37808
+ const newHhea = hhea.slice();
37809
+ writeU16(newHhea, 34, maxGlyphId + 1);
37810
+ const newMaxp = maxp.slice();
37811
+ writeU16(newMaxp, 4, maxGlyphId + 1);
37812
+ const tables = {
37813
+ cmap,
37814
+ head: newHead,
37815
+ hhea: newHhea,
37816
+ hmtx: buildHmtx(font, maxGlyphId),
37817
+ loca: buildLoca(locaOffsets),
37818
+ maxp: newMaxp,
37819
+ glyf: concat(glyfChunks)
37820
+ };
37821
+ for (const tag of ["OS/2", "name", "post"]) {
37822
+ const table = font.getRawTableData(tag);
37823
+ if (table) tables[tag] = table;
37824
+ }
37825
+ return tables;
37826
+ }
37827
+ class TrueTypePdfFontSubsetter {
37828
+ createSubset(font, glyphs) {
37829
+ const unicodeByGlyph = /* @__PURE__ */ new Map();
37830
+ const initialGlyphs = [];
37831
+ for (const glyph of glyphs) {
37832
+ initialGlyphs.push(glyph.id);
37833
+ if (!unicodeByGlyph.has(glyph.id)) {
37834
+ unicodeByGlyph.set(glyph.id, glyph.codePoints);
37835
+ }
37836
+ }
37837
+ const glyphIds = subsetClosure(font, initialGlyphs);
37838
+ const tables = buildSubsetTables(font, glyphIds);
37839
+ const fontFile = buildSfnt(
37840
+ 65536,
37841
+ new Map(
37842
+ Object.entries(tables).map(([tag, data]) => [
37843
+ tag.charCodeAt(0) << 24 | tag.charCodeAt(1) << 16 | tag.charCodeAt(2) << 8 | tag.charCodeAt(3),
37844
+ data
37845
+ ])
37846
+ )
37847
+ ).ttf;
37848
+ const maxGlyphId = Math.max(0, ...glyphIds);
37849
+ const widths = [];
37850
+ const unicode = [];
37851
+ for (let glyphId = 0; glyphId <= maxGlyphId; glyphId += 1) {
37852
+ widths[glyphId] = font.advanceWidthForGlyph(glyphId) / font.unitsPerEm * 1e3;
37853
+ unicode[glyphId] = unicodeByGlyph.get(glyphId) ?? [0];
37854
+ }
37855
+ return {
37856
+ fontFile,
37857
+ widths,
37858
+ unicode,
37859
+ encodeGlyph: (glyphId) => glyphId
37860
+ };
37861
+ }
37862
+ }
37863
+ function parseEmbeddedFontSync(sourceBytes) {
37864
+ const sfntBytes = defaultFontDecoderRegistry.decodeSync(sourceBytes);
37865
+ return SfntFontProgram.parse(sfntBytes);
37866
+ }
37867
+ function createPdfEmbeddableFont(program) {
37868
+ return {
37869
+ program,
37870
+ layouter: new SimpleTextLayouter(program),
37871
+ subsetter: new TrueTypePdfFontSubsetter()
37872
+ };
37873
+ }
37874
+ class PdfFontTable {
37875
+ constructor(fontResources) {
37876
+ __publicField(this, "fontResources", /* @__PURE__ */ new Map());
37877
+ __publicField(this, "unicodeFontStates", /* @__PURE__ */ new Map());
37878
+ __publicField(this, "usedFontResourceNames", /* @__PURE__ */ new Set());
37879
+ for (const resource of fontResources) {
37880
+ this.registerFontResource(resource);
37881
+ }
37882
+ }
37883
+ registerFontResource(resource) {
37884
+ this.fontResources.set(resource.resourceName, resource);
37885
+ if (resource.kind === "unicode" && !this.unicodeFontStates.has(resource.resourceName)) {
37886
+ const font = createPdfEmbeddableFont(
37887
+ parseEmbeddedFontSync(resource.fontData)
37888
+ );
37889
+ const scale = 1e3 / font.program.unitsPerEm;
37890
+ const notdef = {
37891
+ id: 0,
37892
+ codePoints: [0],
37893
+ advanceWidth: font.program.advanceWidthForGlyph(0)
37894
+ };
37895
+ this.unicodeFontStates.set(resource.resourceName, {
37896
+ resource,
37897
+ font,
37898
+ usedGlyphs: /* @__PURE__ */ new Map([[0, notdef]]),
37899
+ scale,
37900
+ layoutCache: /* @__PURE__ */ new Map()
37901
+ });
37902
+ }
37903
+ }
37904
+ /** Resolves the font resource a run uses and marks it as referenced. */
37905
+ resolveAndMarkFontName(options) {
37906
+ const fontResourceName = resolveFontName(options);
37907
+ this.usedFontResourceNames.add(fontResourceName);
37908
+ return fontResourceName;
37909
+ }
37910
+ getUnicodeState(resourceName) {
37911
+ return this.unicodeFontStates.get(resourceName);
37912
+ }
37913
+ /**
37914
+ * Builds the glyph-show operator (`<...> Tj` or `[...] TJ`) for an embedded
37915
+ * Unicode run, recording the glyphs used for subsetting. Returns `null` when
37916
+ * the run produced no glyphs so the caller can skip emission entirely.
37917
+ */
37918
+ buildUnicodeShowCommand(state, text) {
37919
+ const run = this.layoutUnicodeText(state, text);
37792
37920
  const encoded = this.encodeUnicodeGlyphRun(state, run);
37793
37921
  if (encoded.length === 0) {
37794
- return;
37922
+ return null;
37795
37923
  }
37796
37924
  const usesAdjustments = encoded.some(
37797
37925
  (glyph) => Math.abs(glyph.nominalWidth - glyph.desiredAdvance) > 0.01
37798
37926
  );
37799
- const textCommand = usesAdjustments ? `[${encoded.map((glyph) => {
37927
+ return usesAdjustments ? `[${encoded.map((glyph) => {
37800
37928
  const adjustment = glyph.nominalWidth - glyph.desiredAdvance;
37801
37929
  return adjustment === 0 ? `<${encodeGlyphHex(glyph.glyphId)}>` : `<${encodeGlyphHex(glyph.glyphId)}> ${formatNumber(adjustment)}`;
37802
37930
  }).join(" ")}] TJ` : `<${encoded.map((glyph) => encodeGlyphHex(glyph.glyphId)).join("")}> Tj`;
37803
- page.commands.push(
37804
- [
37805
- textMarkerComment(options.text),
37806
- "BT",
37807
- colorCommand(options.color, "rg", [0, 0, 0]),
37808
- `/${state.resource.resourceName} ${formatNumber(options.fontSize ?? 12)} Tf`,
37809
- ...options.horizontalScale && options.horizontalScale > 0 && options.horizontalScale !== 100 ? [`${formatNumber(options.horizontalScale)} Tz`] : [],
37810
- ...options.characterSpacing && options.characterSpacing !== 0 ? [`${formatNumber(options.characterSpacing)} Tc`] : [],
37811
- `${formatNumber(options.x)} ${formatNumber(page.height - options.y)} Td`,
37812
- textCommand,
37813
- "ET"
37814
- ].join("\n")
37815
- );
37816
- }
37817
- toArrayBuffer() {
37818
- const bytes = this.toUint8Array();
37819
- return Uint8Array.from(bytes).buffer;
37820
- }
37821
- toBlob() {
37822
- return new Blob([this.toArrayBuffer()], { type: "application/pdf" });
37823
37931
  }
37824
- toUint8Array() {
37825
- if (this.pages.length === 0) {
37826
- this.addPage({ width: 612, height: 792 });
37827
- }
37828
- const objects = [];
37829
- const addObject = (body2) => {
37830
- const id = objects.length + 1;
37831
- objects.push({ id, body: body2 });
37832
- return id;
37833
- };
37834
- const catalogObjectId = addObject("");
37835
- const pagesObjectId = addObject("");
37932
+ /**
37933
+ * Emits the font objects (base-14 dictionaries and embedded Unicode font
37934
+ * programs) for every referenced resource and returns the `/Font` resource
37935
+ * dictionary XML for page objects.
37936
+ */
37937
+ buildFontObjects(addObject) {
37836
37938
  const fontResourceEntries = Array.from(this.fontResources.values()).filter(
37837
37939
  (resource) => resource.kind === "base14" || this.usedFontResourceNames.has(resource.resourceName)
37838
37940
  );
@@ -37845,86 +37947,28 @@ class OasisPdfWriter {
37845
37947
  }
37846
37948
  return addObject(fontResourceObjectBody(font));
37847
37949
  });
37848
- const fontResourceXml = fontResourceEntries.map((font, index) => `/${font.resourceName} ${fontObjectIds[index]} 0 R`).join(" ");
37849
- const imageObjectIds = /* @__PURE__ */ new Map();
37850
- for (const image of this.imageResources.values()) {
37851
- imageObjectIds.set(
37852
- image.resourceName,
37853
- this.addImageObject(image, addObject)
37854
- );
37855
- }
37856
- const pageObjectIds = [];
37857
- for (const page of this.pages) {
37858
- const stream = `${page.commands.join("\n")}
37859
- `;
37860
- const contentObjectId = addObject(
37861
- `<< /Length ${byteLength(stream)} >>
37862
- stream
37863
- ${stream}endstream`
37864
- );
37865
- const imageResourceXml = Array.from(page.imageResourceNames).map((resourceName) => {
37866
- const objectId = imageObjectIds.get(resourceName);
37867
- return objectId ? `/${resourceName} ${objectId} 0 R` : "";
37868
- }).filter(Boolean).join(" ");
37869
- const xObjectResourceXml = imageResourceXml ? ` /XObject << ${imageResourceXml} >>` : "";
37870
- const pageObjectId = addObject(
37871
- [
37872
- "<< /Type /Page",
37873
- `/Parent ${pagesObjectId} 0 R`,
37874
- `/MediaBox [0 0 ${formatNumber(page.width)} ${formatNumber(page.height)}]`,
37875
- `/Resources << /Font << ${fontResourceXml} >>${xObjectResourceXml} >>`,
37876
- `/Contents ${contentObjectId} 0 R`,
37877
- ">>"
37878
- ].join("\n")
37879
- );
37880
- pageObjectIds.push(pageObjectId);
37881
- }
37882
- objects[catalogObjectId - 1].body = `<< /Type /Catalog /Pages ${pagesObjectId} 0 R >>`;
37883
- objects[pagesObjectId - 1].body = [
37884
- "<< /Type /Pages",
37885
- `/Kids [${pageObjectIds.map((id) => `${id} 0 R`).join(" ")}]`,
37886
- `/Count ${pageObjectIds.length}`,
37887
- ">>"
37888
- ].join("\n");
37889
- let body = PDF_HEADER;
37890
- const offsets = [0];
37891
- for (const object of objects) {
37892
- offsets[object.id] = byteLength(body);
37893
- body += `${object.id} 0 obj
37894
- ${object.body}
37895
- endobj
37896
- `;
37897
- }
37898
- const xrefOffset = byteLength(body);
37899
- body += `xref
37900
- 0 ${objects.length + 1}
37901
- `;
37902
- body += "0000000000 65535 f \n";
37903
- for (const object of objects) {
37904
- body += `${String(offsets[object.id] ?? 0).padStart(10, "0")} 00000 n
37905
- `;
37950
+ const resourceXml = fontResourceEntries.map((font, index) => `/${font.resourceName} ${fontObjectIds[index]} 0 R`).join(" ");
37951
+ return { resourceXml };
37952
+ }
37953
+ layoutUnicodeText(state, text) {
37954
+ const cached = state.layoutCache.get(text);
37955
+ if (cached) {
37956
+ return cached;
37906
37957
  }
37907
- body += [
37908
- "trailer",
37909
- `<< /Size ${objects.length + 1} /Root ${catalogObjectId} 0 R >>`,
37910
- "startxref",
37911
- String(xrefOffset),
37912
- "%%EOF",
37913
- ""
37914
- ].join("\n");
37915
- return new TextEncoder().encode(body);
37958
+ const run = state.font.layouter.layout(text);
37959
+ state.layoutCache.set(text, run);
37960
+ return run;
37916
37961
  }
37917
- addImageObject(resource, addObject) {
37918
- return addObject(
37919
- asciiHexImageStreamObjectBody(resource.data, [
37920
- "/Type /XObject",
37921
- "/Subtype /Image",
37922
- `/Width ${resource.width}`,
37923
- `/Height ${resource.height}`,
37924
- "/ColorSpace /DeviceRGB",
37925
- "/BitsPerComponent 8"
37926
- ])
37927
- );
37962
+ encodeUnicodeGlyphRun(state, run) {
37963
+ return run.glyphs.map((glyph, index) => {
37964
+ if (!state.usedGlyphs.has(glyph.id)) {
37965
+ state.usedGlyphs.set(glyph.id, glyph);
37966
+ }
37967
+ const position = run.positions[index];
37968
+ const nominalWidth = glyph.advanceWidth * state.scale;
37969
+ const desiredAdvance = ((position == null ? void 0 : position.xAdvance) ?? glyph.advanceWidth) * state.scale;
37970
+ return { glyphId: glyph.id, nominalWidth, desiredAdvance };
37971
+ });
37928
37972
  }
37929
37973
  addUnicodeFontObjects(state, addObject) {
37930
37974
  const subset = state.font.subsetter.createSubset(
@@ -38002,6 +38046,200 @@ endobj
38002
38046
  );
38003
38047
  }
38004
38048
  }
38049
+ class PdfImageTable {
38050
+ constructor() {
38051
+ __publicField(this, "imageResources", /* @__PURE__ */ new Map());
38052
+ }
38053
+ registerImageResource(resource) {
38054
+ const resourceName = resource.resourceName ?? `Im${this.imageResources.size + 1}`;
38055
+ if (!this.imageResources.has(resourceName)) {
38056
+ this.imageResources.set(resourceName, {
38057
+ resourceName,
38058
+ width: Math.max(1, Math.round(resource.width)),
38059
+ height: Math.max(1, Math.round(resource.height)),
38060
+ data: resource.data,
38061
+ filter: resource.filter
38062
+ });
38063
+ }
38064
+ return resourceName;
38065
+ }
38066
+ has(resourceName) {
38067
+ return this.imageResources.has(resourceName);
38068
+ }
38069
+ /** Emits each registered image object, keyed by resource name for page maps. */
38070
+ buildImageObjects(addObject) {
38071
+ const imageObjectIds = /* @__PURE__ */ new Map();
38072
+ for (const image of this.imageResources.values()) {
38073
+ imageObjectIds.set(
38074
+ image.resourceName,
38075
+ this.addImageObject(image, addObject)
38076
+ );
38077
+ }
38078
+ return imageObjectIds;
38079
+ }
38080
+ addImageObject(resource, addObject) {
38081
+ return addObject(
38082
+ asciiHexImageStreamObjectBody(resource.data, [
38083
+ "/Type /XObject",
38084
+ "/Subtype /Image",
38085
+ `/Width ${resource.width}`,
38086
+ `/Height ${resource.height}`,
38087
+ "/ColorSpace /DeviceRGB",
38088
+ "/BitsPerComponent 8"
38089
+ ])
38090
+ );
38091
+ }
38092
+ }
38093
+ function serializePdfDocument(pages, fonts, images) {
38094
+ const objects = [];
38095
+ const addObject = (body2) => {
38096
+ const id = objects.length + 1;
38097
+ objects.push({ id, body: body2 });
38098
+ return id;
38099
+ };
38100
+ const catalogObjectId = addObject("");
38101
+ const pagesObjectId = addObject("");
38102
+ const { resourceXml: fontResourceXml } = fonts.buildFontObjects(addObject);
38103
+ const imageObjectIds = images.buildImageObjects(addObject);
38104
+ const pageObjectIds = [];
38105
+ for (const page of pages) {
38106
+ const stream = `${page.commands.join("\n")}
38107
+ `;
38108
+ const contentObjectId = addObject(
38109
+ `<< /Length ${byteLength(stream)} >>
38110
+ stream
38111
+ ${stream}endstream`
38112
+ );
38113
+ const imageResourceXml = Array.from(page.imageResourceNames).map((resourceName) => {
38114
+ const objectId = imageObjectIds.get(resourceName);
38115
+ return objectId ? `/${resourceName} ${objectId} 0 R` : "";
38116
+ }).filter(Boolean).join(" ");
38117
+ const xObjectResourceXml = imageResourceXml ? ` /XObject << ${imageResourceXml} >>` : "";
38118
+ const pageObjectId = addObject(
38119
+ [
38120
+ "<< /Type /Page",
38121
+ `/Parent ${pagesObjectId} 0 R`,
38122
+ `/MediaBox [0 0 ${formatNumber(page.width)} ${formatNumber(page.height)}]`,
38123
+ `/Resources << /Font << ${fontResourceXml} >>${xObjectResourceXml} >>`,
38124
+ `/Contents ${contentObjectId} 0 R`,
38125
+ ">>"
38126
+ ].join("\n")
38127
+ );
38128
+ pageObjectIds.push(pageObjectId);
38129
+ }
38130
+ objects[catalogObjectId - 1].body = `<< /Type /Catalog /Pages ${pagesObjectId} 0 R >>`;
38131
+ objects[pagesObjectId - 1].body = [
38132
+ "<< /Type /Pages",
38133
+ `/Kids [${pageObjectIds.map((id) => `${id} 0 R`).join(" ")}]`,
38134
+ `/Count ${pageObjectIds.length}`,
38135
+ ">>"
38136
+ ].join("\n");
38137
+ let body = PDF_HEADER;
38138
+ const offsets = [0];
38139
+ for (const object of objects) {
38140
+ offsets[object.id] = byteLength(body);
38141
+ body += `${object.id} 0 obj
38142
+ ${object.body}
38143
+ endobj
38144
+ `;
38145
+ }
38146
+ const xrefOffset = byteLength(body);
38147
+ body += `xref
38148
+ 0 ${objects.length + 1}
38149
+ `;
38150
+ body += "0000000000 65535 f \n";
38151
+ for (const object of objects) {
38152
+ body += `${String(offsets[object.id] ?? 0).padStart(10, "0")} 00000 n
38153
+ `;
38154
+ }
38155
+ body += [
38156
+ "trailer",
38157
+ `<< /Size ${objects.length + 1} /Root ${catalogObjectId} 0 R >>`,
38158
+ "startxref",
38159
+ String(xrefOffset),
38160
+ "%%EOF",
38161
+ ""
38162
+ ].join("\n");
38163
+ return new TextEncoder().encode(body);
38164
+ }
38165
+ class OasisPdfWriter {
38166
+ constructor(fontResources = DEFAULT_PDF_FONT_RESOURCES) {
38167
+ __publicField(this, "pages", []);
38168
+ __publicField(this, "streams", []);
38169
+ __publicField(this, "fonts");
38170
+ __publicField(this, "images", new PdfImageTable());
38171
+ this.fonts = new PdfFontTable(fontResources);
38172
+ }
38173
+ registerFontResource(resource) {
38174
+ this.fonts.registerFontResource(resource);
38175
+ }
38176
+ addPage(size) {
38177
+ const page = {
38178
+ width: Math.max(1, size.width),
38179
+ height: Math.max(1, size.height),
38180
+ commands: [],
38181
+ imageResourceNames: /* @__PURE__ */ new Set()
38182
+ };
38183
+ this.pages.push(page);
38184
+ this.streams.push(new PdfContentStream(page, this.fonts, this.images));
38185
+ return this.pages.length - 1;
38186
+ }
38187
+ getPageCount() {
38188
+ return this.pages.length;
38189
+ }
38190
+ drawRect(pageIndex, options) {
38191
+ var _a;
38192
+ (_a = this.streams[pageIndex]) == null ? void 0 : _a.drawRect(options);
38193
+ }
38194
+ drawLine(pageIndex, options) {
38195
+ var _a;
38196
+ (_a = this.streams[pageIndex]) == null ? void 0 : _a.drawLine(options);
38197
+ }
38198
+ drawPath(pageIndex, options) {
38199
+ var _a;
38200
+ (_a = this.streams[pageIndex]) == null ? void 0 : _a.drawPath(options);
38201
+ }
38202
+ saveGraphicsState(pageIndex) {
38203
+ var _a;
38204
+ (_a = this.streams[pageIndex]) == null ? void 0 : _a.saveGraphicsState();
38205
+ }
38206
+ restoreGraphicsState(pageIndex) {
38207
+ var _a;
38208
+ (_a = this.streams[pageIndex]) == null ? void 0 : _a.restoreGraphicsState();
38209
+ }
38210
+ rotateAbout(pageIndex, centerX, centerY, degrees) {
38211
+ var _a;
38212
+ (_a = this.streams[pageIndex]) == null ? void 0 : _a.rotateAbout(centerX, centerY, degrees);
38213
+ }
38214
+ clipRect(pageIndex, x, y, width, height) {
38215
+ var _a;
38216
+ (_a = this.streams[pageIndex]) == null ? void 0 : _a.clipRect(x, y, width, height);
38217
+ }
38218
+ drawText(pageIndex, options) {
38219
+ var _a;
38220
+ (_a = this.streams[pageIndex]) == null ? void 0 : _a.drawText(options);
38221
+ }
38222
+ registerImageResource(resource) {
38223
+ return this.images.registerImageResource(resource);
38224
+ }
38225
+ drawImage(pageIndex, options) {
38226
+ var _a;
38227
+ (_a = this.streams[pageIndex]) == null ? void 0 : _a.drawImage(options);
38228
+ }
38229
+ toArrayBuffer() {
38230
+ const bytes = this.toUint8Array();
38231
+ return Uint8Array.from(bytes).buffer;
38232
+ }
38233
+ toBlob() {
38234
+ return new Blob([this.toArrayBuffer()], { type: "application/pdf" });
38235
+ }
38236
+ toUint8Array() {
38237
+ if (this.pages.length === 0) {
38238
+ this.addPage({ width: 612, height: 792 });
38239
+ }
38240
+ return serializePdfDocument(this.pages, this.fonts, this.images);
38241
+ }
38242
+ }
38005
38243
  const FOOTNOTE_BLOCK_GAP_PX = 2;
38006
38244
  async function exportEditorDocumentToPdf(document2) {
38007
38245
  document2 = renumberImageCaptionsInDocument(document2);
@@ -44776,7 +45014,9 @@ function createEditorTextDrag(deps) {
44776
45014
  current,
44777
45015
  (temp) => moveOrCopySelectionToPosition(temp, destination, { copy })
44778
45016
  ),
44779
- { mergeKey: copy ? MERGE_KEYS.copyTextByDrag : MERGE_KEYS.moveTextByDrag }
45017
+ {
45018
+ mergeKey: copy ? MERGE_KEYS.copyTextByDrag : MERGE_KEYS.moveTextByDrag
45019
+ }
44780
45020
  );
44781
45021
  (_b = deps.logger) == null ? void 0 : _b.info("text-drag:apply", {
44782
45022
  mode: copy ? "copy" : "move",
@@ -47150,7 +47390,12 @@ function collectTocHeadings(state, maxLevel = DEFAULT_TOC_MAX_LEVEL) {
47150
47390
  function makeRun(partial) {
47151
47391
  const id = createEditorRun(partial.text).id;
47152
47392
  if (partial.fieldChar) {
47153
- return { id, text: partial.text, kind: "fieldChar", fieldChar: partial.fieldChar };
47393
+ return {
47394
+ id,
47395
+ text: partial.text,
47396
+ kind: "fieldChar",
47397
+ fieldChar: partial.fieldChar
47398
+ };
47154
47399
  }
47155
47400
  if (partial.fieldInstruction !== void 0) {
47156
47401
  return {