@silurus/ooxml 0.71.0 → 0.72.1

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.
@@ -61,11 +61,18 @@ declare interface BlipBullet {
61
61
  /** MIME type of the blip at {@link BlipBullet.imagePath} (e.g. `image/png`). */
62
62
  mimeType: string;
63
63
  /**
64
- * `<a:buSzPct val>` (ECMA-376 §21.1.2.4.3) as a percentage of the text size
64
+ * `<a:buSzPct val>` (ECMA-376 §21.1.2.4.9) as a percentage of the text size
65
65
  * (100 = same size). `null` when no explicit `<a:buSzPct>` is present, in
66
66
  * which case the renderer uses the spec default of 100%.
67
67
  */
68
68
  sizePct: number | null;
69
+ /**
70
+ * `<a:buSzPts val>` (ECMA-376 §21.1.2.4.10) — an ABSOLUTE marker size in
71
+ * points, independent of the text size. Mutually exclusive with {@link
72
+ * BlipBullet.sizePct} (both are the one `EG_TextBulletSize` choice). Omitted
73
+ * when no explicit `<a:buSzPts>` is present; when present it takes precedence.
74
+ */
75
+ sizePts?: number;
69
76
  }
70
77
 
71
78
  declare type BodyElement = {
@@ -114,6 +121,14 @@ declare type BodyElement = {
114
121
  * separately from `geom` because a section may inherit its geometry yet
115
122
  * still restart / re-format its page numbers. */
116
123
  pageNumType?: PageNumType | null;
124
+ /** ECMA-376 §17.6.20 `<w:textDirection w:val>` — this ENDING section's
125
+ * flow direction (TRANSITIONAL ST_TextDirection, same enum and semantics
126
+ * as {@link SectionProps.textDirection}), so a vertical (tbRl/btLr)
127
+ * non-final section can coexist with a horizontal final section (issue
128
+ * #1000). Absent ⇒ horizontal ("lrTb" is collapsed by the parser).
129
+ * Carried separately from `geom` (like `pageNumType`) because a section
130
+ * may inherit its page geometry yet still set its own flow direction. */
131
+ textDirection?: string | null;
117
132
  };
118
133
 
119
134
  declare interface Border {
@@ -145,17 +160,23 @@ declare interface BorderSpec {
145
160
  /**
146
161
  * Populate a highlight overlay layer with one box per matched run-slice.
147
162
  *
148
- * @param layer the overlay div (cleared and re-sized to the canvas here).
163
+ * Every box is positioned as a PERCENTAGE of `cssWidth`/`cssHeight`, and the
164
+ * container's own size is left untouched (`width:100%;height:100%` from the
165
+ * caller), so the highlights track the canvas's ACTUAL rendered box even when a
166
+ * consumer scales the canvas down with external CSS — mirroring
167
+ * {@link buildDocxTextLayer}.
168
+ *
169
+ * @param layer the overlay div (cleared here; sized `100%` by the caller).
149
170
  * @param runs the page's runs (same array the page was rendered/text-layered from).
150
171
  * @param matches the page's matches (run-slices + active flag).
151
- * @param canvasCssWidth the rendered canvas's CSS width (e.g. `"700px"`).
152
- * @param canvasCssHeight the rendered canvas's CSS height.
172
+ * @param cssWidth the page's intended CSS width (px, number) — the x-axis % denominator.
173
+ * @param cssHeight the page's intended CSS height (px, number) — the y-axis % denominator.
153
174
  * @param measureForFont returns a width-measurer primed with a run's `font`
154
175
  * (the viewer closes over a canvas 2d context). Kept as a
155
176
  * factory so the font is set once per run, not per glyph.
156
177
  * @param colors optional colour overrides.
157
178
  */
158
- declare function buildDocxHighlightLayer(layer: HTMLDivElement, runs: DocxTextRunInfo[], matches: DocxHighlightMatch[], canvasCssWidth: string, canvasCssHeight: string, measureForFont: (font: string) => (s: string) => number, colors?: DocxHighlightColors): void;
179
+ declare function buildDocxHighlightLayer(layer: HTMLDivElement, runs: DocxTextRunInfo[], matches: DocxHighlightMatch[], cssWidth: number, cssHeight: number, measureForFont: (font: string) => (s: string) => number, colors?: DocxHighlightColors): void;
159
180
 
160
181
  /**
161
182
  * Build the transparent text-selection overlay for a rendered docx page: one
@@ -168,11 +189,21 @@ declare function buildDocxHighlightLayer(layer: HTMLDivElement, runs: DocxTextRu
168
189
  * the same `DocxTextRunInfo[]` off-thread and ships it back beside the bitmap, so
169
190
  * the overlay is built from identical geometry regardless of thread.
170
191
  *
171
- * @param layer the overlay div (position:relative parent expected).
192
+ * Every span is positioned as a PERCENTAGE of `cssWidth`/`cssHeight` (the page's
193
+ * intended CSS-px box), never literal px, and the container's own width/height are
194
+ * left untouched (the caller sizes it `width:100%;height:100%`). This lets the
195
+ * overlay track the canvas's ACTUAL rendered box even when a consumer scales the
196
+ * canvas down with external CSS (`width:100%!important; height:auto`): the
197
+ * `display:inline-block` wrapper shrinks with the canvas, the `100%` container
198
+ * follows, and every `%`-placed span scales with it, so nothing overflows the
199
+ * wrapper into an ancestor's scroll area.
200
+ *
201
+ * @param layer the overlay div (sized `width:100%;height:100%` by the caller).
172
202
  * @param runs per-run geometry from `renderPage({ onTextRun })`.
173
- * @param canvasCssWidth the rendered canvas's CSS width (e.g. `"700px"`), used
174
- * to size the overlay to match the canvas.
175
- * @param canvasCssHeight the rendered canvas's CSS height.
203
+ * @param cssWidth the page's intended CSS width (px, number) — the %
204
+ * denominator for the x axis.
205
+ * @param cssHeight the page's intended CSS height (px, number) — the %
206
+ * denominator for the y axis.
176
207
  * @param onHyperlinkClick IX1 — invoked when a run carrying a resolved
177
208
  * {@link HyperlinkTarget} is clicked. A hyperlink run's
178
209
  * span keeps its transparent glyphs (the visible link
@@ -192,18 +223,23 @@ declare function buildDocxHighlightLayer(layer: HTMLDivElement, runs: DocxTextRu
192
223
  * a 縦中横 span keeps the bare rotate (no regression for
193
224
  * callers that do not thread a measurer).
194
225
  */
195
- declare function buildDocxTextLayer(layer: HTMLDivElement, runs: DocxTextRunInfo[], canvasCssWidth: string, canvasCssHeight: string, onHyperlinkClick?: (target: HyperlinkTarget) => void, measureForFont?: (font: string) => (s: string) => number): void;
226
+ declare function buildDocxTextLayer(layer: HTMLDivElement, runs: DocxTextRunInfo[], cssWidth: number, cssHeight: number, onHyperlinkClick?: (target: HyperlinkTarget) => void, measureForFont?: (font: string) => (s: string) => number): void;
196
227
 
197
228
  /**
198
229
  * Populate a highlight overlay layer with a box per matched run-slice, grouped
199
230
  * by shape frame (with the shape's rotation) so each box lands on the drawn
200
231
  * glyphs.
201
232
  *
202
- * @param layer the overlay div (cleared + re-sized here).
233
+ * All coordinates are PERCENTAGES of `cssWidth`/`cssHeight`, and the container's
234
+ * own size is left untouched (`width:100%;height:100%` from the caller), so the
235
+ * highlights track the canvas's ACTUAL rendered box even when a consumer scales
236
+ * the canvas down with external CSS — mirroring {@link buildPptxTextLayer}.
237
+ *
238
+ * @param layer the overlay div (cleared here; sized `100%` by the caller).
203
239
  * @param runs the slide's runs (same array the slide was rendered from).
204
240
  * @param matches the slide's matches (run-slices + active flag).
205
- * @param cssWidth rendered canvas CSS width (px, number).
206
- * @param cssHeight rendered canvas CSS height (px, number).
241
+ * @param cssWidth the slide's intended CSS width (px, number) — the % denominator.
242
+ * @param cssHeight the slide's intended CSS height (px, number) — the % denominator.
207
243
  * @param measureForFont returns a width-measurer primed with a run's font.
208
244
  * @param colors optional colour overrides.
209
245
  */
@@ -228,16 +264,32 @@ declare function buildPptxHighlightLayer(layer: HTMLDivElement, runs: PptxTextRu
228
264
  * (no hyperlink) is byte-identical to before. A JS click handler is used rather
229
265
  * than an `<a href>` so the URL never bypasses the viewer's sanitisation.
230
266
  *
231
- * @param layer the overlay div.
267
+ * The overlay's coordinates are all PERCENTAGES of `cssWidth`/`cssHeight` (the
268
+ * slide's intended CSS-px box), never literal px, and the container's own
269
+ * `width`/`height` are left untouched (the caller sizes it `width:100%;
270
+ * height:100%` so it fills the wrapper). This lets the overlay track the canvas's
271
+ * ACTUAL rendered box even when a consumer scales the canvas down with external
272
+ * CSS (e.g. `width:100%!important;height:auto`): the wrapper (and therefore the
273
+ * `100%` container) shrinks with the canvas, and every `%`-placed child scales
274
+ * with it, so nothing overflows the wrapper into an ancestor's scroll area.
275
+ *
276
+ * @param layer the overlay div (sized `width:100%;height:100%` by the caller).
232
277
  * @param runs per-run + per-shape geometry from `renderSlide({ onTextRun })`.
233
- * @param cssWidth the rendered canvas's CSS width (px, number).
234
- * @param cssHeight the rendered canvas's CSS height (px, number).
278
+ * @param cssWidth the slide's intended CSS width (px, number) — the % denominator.
279
+ * @param cssHeight the slide's intended CSS height (px, number) — the % denominator.
235
280
  * @param onHyperlinkClick called with the run's resolved {@link HyperlinkTarget}
236
281
  * when a hyperlink span is clicked. Omit to leave links
237
282
  * non-interactive (spans stay plain, selectable text).
238
283
  */
239
284
  declare function buildPptxTextLayer(layer: HTMLDivElement, runs: PptxTextRunInfo[], cssWidth: number, cssHeight: number, onHyperlinkClick?: (target: HyperlinkTarget) => void): void;
240
285
 
286
+ /**
287
+ * A paragraph's bullet marker. For `char`, the marker size is EITHER `sizePct`
288
+ * (a percentage of the run size — ECMA-376 §21.1.2.4.9 `<a:buSzPct>`) OR `sizePts`
289
+ * (an absolute size in points — §21.1.2.4.10 `<a:buSzPts>`), never both: they are
290
+ * the one `EG_TextBulletSize` xsd:choice. `sizePts` is optional (absent when no
291
+ * `<a:buSzPts>` was declared); when present it takes precedence over `sizePct`.
292
+ */
241
293
  declare type Bullet = {
242
294
  type: 'none';
243
295
  } | {
@@ -247,11 +299,13 @@ declare type Bullet = {
247
299
  char: string;
248
300
  color: string | null;
249
301
  sizePct: number | null;
302
+ sizePts?: number;
250
303
  fontFamily: string | null;
251
304
  } | {
252
305
  type: 'autoNum';
253
306
  numType: string;
254
307
  startAt: number | null;
308
+ color: string | null;
255
309
  };
256
310
 
257
311
  /**
@@ -565,6 +619,9 @@ declare interface ChartElement {
565
619
  y: number;
566
620
  width: number;
567
621
  height: number;
622
+ rotation: number;
623
+ flipH: boolean;
624
+ flipV: boolean;
568
625
  /**
569
626
  * The chart payload, already in the canonical {@link ChartModel} shape emitted
570
627
  * by the Rust parser (`ooxml_common::chart::ChartModel`). Passed straight to
@@ -678,6 +735,14 @@ declare interface ChartModel {
678
735
  title: string | null;
679
736
  categories: string[];
680
737
  series: ChartSeries[];
738
+ /**
739
+ * §21.2.2.227 `<c:varyColors val="1"/>` on a SINGLE-series bar/column chart:
740
+ * color each data point (bar) from the theme/palette sequence and list one
741
+ * legend entry per point, matching Office. Set by the shared parser ONLY for
742
+ * that non-pie, single-series case (pie/doughnut already vary by point via
743
+ * `chartType` + `dataPointColors`); absent/false otherwise.
744
+ */
745
+ varyColors?: boolean | null;
681
746
  /** Show data labels on bars / points / slices. */
682
747
  showDataLabels: boolean;
683
748
  /** Explicit Y-axis minimum (OOXML `<c:valAx><c:min>`). */
@@ -1056,8 +1121,9 @@ declare interface ChartModel {
1056
1121
  * core `renderChart` consumes (identical to what pptx/xlsx pass), so a docx
1057
1122
  * chart draws at the same quality through the same code path. `widthPt`/
1058
1123
  * `heightPt` are the `<wp:extent>` natural size. An inline chart flows as an
1059
- * inline box of that size; an anchored chart (§20.4.2.3) is painted at its
1060
- * absolute page box by `renderAnchorImages` — both via `renderChart`. */
1124
+ * inline box of that size; an anchored chart (§20.4.2.3) is painted via
1125
+ * `registerAnchorFloats` when it wraps text, or by `renderAnchorImages` for
1126
+ * wrapNone/no-wrap anchors — all paths use `renderChart`. */
1061
1127
  declare interface ChartRun {
1062
1128
  chart: ChartModel;
1063
1129
  widthPt: number;
@@ -1069,6 +1135,39 @@ declare interface ChartRun {
1069
1135
  anchorYPt?: number;
1070
1136
  anchorXFromMargin?: boolean;
1071
1137
  anchorYFromPara?: boolean;
1138
+ /**
1139
+ * Wrap mode for anchored charts (ECMA-376 §20.4.2.16/.17):
1140
+ * "square" | "topAndBottom" | "none" | "tight" | "through"
1141
+ * Inline charts and undetermined cases leave this undefined. The renderer
1142
+ * treats "tight" and "through" as "square", matching anchored images.
1143
+ */
1144
+ wrapMode?: string;
1145
+ /** Padding top (pt). Anchor-only (ECMA-376 §20.4.2.16/.17). */
1146
+ distTop?: number;
1147
+ /** Padding bottom (pt). Anchor-only (ECMA-376 §20.4.2.16/.17). */
1148
+ distBottom?: number;
1149
+ /** Padding left (pt). Anchor-only (ECMA-376 §20.4.2.16/.17). */
1150
+ distLeft?: number;
1151
+ /** Padding right (pt). Anchor-only (ECMA-376 §20.4.2.16/.17). */
1152
+ distRight?: number;
1153
+ /** wrapText attribute: "bothSides" | "left" | "right" | "largest". */
1154
+ wrapSide?: string;
1155
+ /**
1156
+ * ECMA-376 §20.4.2.3 `wp:anchor/@allowOverlap`. The parser omits this
1157
+ * field when true, so renderers must read it as `allowOverlap ?? true`.
1158
+ */
1159
+ allowOverlap?: boolean;
1160
+ /** ECMA-376 §20.4.3.1 wp:align horizontal: "left" | "center" | "right" |
1161
+ * "inside" | "outside". */
1162
+ anchorXAlign?: string | null;
1163
+ /** Vertical equivalent of anchorXAlign: "top" | "center" | "bottom". */
1164
+ anchorYAlign?: string | null;
1165
+ /**
1166
+ * ECMA-376 §20.4.3.2 `<wp:positionH/@relativeFrom>` / §20.4.3.5
1167
+ * `<wp:positionV/@relativeFrom>` — the raw anchor placement containers.
1168
+ */
1169
+ anchorXRelativeFrom?: string | null;
1170
+ anchorYRelativeFrom?: string | null;
1072
1171
  }
1073
1172
 
1074
1173
  declare interface ChartSeries {
@@ -1393,12 +1492,20 @@ declare interface DocParagraph {
1393
1492
  shading?: string | null;
1394
1493
  /** Force a page break before this paragraph (w:pageBreakBefore) */
1395
1494
  pageBreakBefore?: boolean;
1396
- /** Suppress spacing between adjacent same-style paragraphs (w:contextualSpacing) */
1495
+ /** ECMA-376 §17.3.1.9 `<w:contextualSpacing>` — between adjacent SAME-style
1496
+ * paragraphs, a toggling paragraph drops its OWN contribution to the
1497
+ * collapsed inter-paragraph gap (per-side, Word-adjudicated — issue #1015;
1498
+ * see the renderer's `contextualSpacingAdjust`). */
1397
1499
  contextualSpacing?: boolean;
1398
1500
  /** Keep paragraph on same page as the next paragraph (w:keepNext) */
1399
1501
  keepNext?: boolean;
1400
1502
  /** Keep all lines of this paragraph on the same page (w:keepLines) */
1401
1503
  keepLines?: boolean;
1504
+ /** ECMA-376 §17.3.1.29 + §17.3.2.41 — the paragraph MARK's resolved `w:vanish`
1505
+ * (hidden text). An inkless paragraph whose mark is vanished collapses to zero
1506
+ * height in the normal/print view (hidden-text off), the same way the parser
1507
+ * strips hidden runs; the paginator drops it whole. Absent = mark is visible. */
1508
+ markVanish?: boolean;
1402
1509
  /** Widow/orphan control (w:widowControl). ECMA-376 default is true. */
1403
1510
  widowControl?: boolean;
1404
1511
  /** Paragraph borders (w:pBdr) */
@@ -1410,6 +1517,17 @@ declare interface DocParagraph {
1410
1517
  /** Default font family resolved from the style chain. Used to size empty
1411
1518
  * paragraphs (no runs) with the intended font's line metrics. */
1412
1519
  defaultFontFamily?: string | null;
1520
+ /** Default East Asian font family resolved from the style chain. Empty /
1521
+ * anchor-only paragraph marks in East Asian documents use this axis for line
1522
+ * metrics instead of the ASCII fallback. */
1523
+ defaultFontFamilyEastAsia?: string | null;
1524
+ /** ECMA-376 §17.3.1.29 — the paragraph MARK run's resolved `w:color` (direct
1525
+ * pPr/rPr → pStyle chain → docDefaults; hex 6 without `#`, lowercased; an
1526
+ * explicit `auto` surfaces as absent, §17.3.2.6). Word formats a numbering
1527
+ * marker with the level rPr (§17.9.24) layered over the mark's run
1528
+ * properties, so the renderer uses this as the marker-color fallback when
1529
+ * {@link NumberingInfo.color} is absent. */
1530
+ paragraphMarkColor?: string | null;
1413
1531
  /**
1414
1532
  * ECMA-376 §17.3.1.6 `<w:bidi>` — right-to-left paragraph. `true` = RTL,
1415
1533
  * `false` = explicitly LTR, absent = unspecified (inherit). The renderer uses
@@ -1487,6 +1605,17 @@ declare interface DocSettings {
1487
1605
  * tab stops generated after all custom stops. `undefined` ⇒ the renderer
1488
1606
  * uses the spec default of 720 twips (36pt). */
1489
1607
  defaultTabStop?: number;
1608
+ /** §17.15.1.18 `w:characterSpacingControl@w:val` — East Asian punctuation /
1609
+ * character-spacing control. */
1610
+ characterSpacingControl?: string;
1611
+ /** §17.15.3.1 `w:compat/w:useFELayout` — Far East layout compatibility. */
1612
+ useFeLayout?: boolean;
1613
+ /** §17.15.3.1 `w:compat/w:balanceSingleByteDoubleByteWidth` — balance
1614
+ * single-byte and double-byte widths for East Asian layout. */
1615
+ balanceSingleByteDoubleByteWidth?: boolean;
1616
+ /** §17.15.3.1 `w:compat/w:adjustLineHeightInTable` — apply the section
1617
+ * document-grid line pitch to text in table cells. */
1618
+ adjustLineHeightInTable?: boolean;
1490
1619
  }
1491
1620
 
1492
1621
  declare interface DocTable {
@@ -1563,11 +1692,20 @@ declare interface DocTableCell {
1563
1692
 
1564
1693
  declare interface DocTableRow {
1565
1694
  cells: DocTableCell[];
1695
+ /** ECMA-376 §17.4.15 `<w:gridBefore>` — shared table-grid columns skipped
1696
+ * before placing this row's first real cell. Omitted/zero means none. */
1697
+ gridBefore?: number;
1698
+ /** ECMA-376 §17.4.14 `<w:gridAfter>` — shared table-grid columns skipped
1699
+ * after this row's last real cell. Omitted/zero means none. */
1700
+ gridAfter?: number;
1566
1701
  rowHeight: number | null;
1567
1702
  /** ECMA-376 §17.4.80 hRule. "auto" (default) = informational; "atLeast" =
1568
1703
  * lower bound; "exact" = fixed clip. */
1569
1704
  rowHeightRule: 'auto' | 'atLeast' | 'exact' | string;
1570
1705
  isHeader: boolean;
1706
+ /** ECMA-376 §17.4.6 `<w:cantSplit>` — when true, the row must not be split
1707
+ * across page boundaries. Omitted/false rows may split at page boundaries. */
1708
+ cantSplit?: boolean;
1571
1709
  }
1572
1710
 
1573
1711
  export declare namespace docx {
@@ -1829,6 +1967,16 @@ declare interface DocxDocumentModel {
1829
1967
  * entry is absent or classified as "auto".
1830
1968
  */
1831
1969
  fontFamilyClasses?: Record<string, string>;
1970
+ /**
1971
+ * ECMA-376 §17.8.3.29 — per-font pitch from `word/fontTable.xml`
1972
+ * (`<w:pitch>`, ST_Pitch §17.18.66): font name → "fixed" | "variable" |
1973
+ * "default". Present only for fonts that declare `<w:pitch>`. The renderer
1974
+ * pairs this with {@link fontFamilyClasses}: a `family="modern"` face is
1975
+ * treated as monospace ONLY when its pitch is "fixed"; "variable" /
1976
+ * "default" / absent fall through to name-pattern / CJK-sans classification
1977
+ * (§17.8.3.10 `family` classifies the design, not the pitch — issue #855).
1978
+ */
1979
+ fontFamilyPitches?: Record<string, string>;
1832
1980
  /** ECMA-376 §17.8.3.3-.6 — embedded fonts from `word/fontTable.xml`, resolved
1833
1981
  * to their `.odttf` part paths + fontKey. The viewer de-obfuscates (§17.8.1)
1834
1982
  * and registers each as a FontFace before pagination so text measures/draws
@@ -2131,6 +2279,12 @@ declare class DocxScrollViewer implements ZoomableViewer {
2131
2279
  * {@link DocxDocument.getBookmarkPage} (ECMA-376 §17.16.23) and scrolls there
2132
2280
  * with {@link scrollToPage}. An anchor naming no known bookmark is a safe no-op
2133
2281
  * rather than a scroll to a guessed page.
2282
+ *
2283
+ * IX1 — returns `undefined` when `enableHyperlinks` is `false`, the single gate
2284
+ * that disables hyperlink interactivity: {@link buildDocxTextLayer} treats a
2285
+ * missing handler as "render link runs like plain runs", so no hit region,
2286
+ * cursor, tooltip, listener, or navigation is wired (a custom
2287
+ * `onHyperlinkClick` is suppressed too).
2134
2288
  */
2135
2289
  private _hyperlinkHandler;
2136
2290
  /** A width-measurer primed with a run's `font` — used ONLY to clamp a §17.3.2.10
@@ -2139,6 +2293,10 @@ declare class DocxScrollViewer implements ZoomableViewer {
2139
2293
  * unavailable so the caller still gets a callable (the overlay then sees scale
2140
2294
  * 1 and leaves the span un-clamped). */
2141
2295
  private _measureForFont;
2296
+ /** A canvas's intended CSS box in px (the % denominators the overlay builders
2297
+ * expect). Reads the inline `style.width`/`height` set by the render path,
2298
+ * falling back to the backing-store size when unset; tolerates the `px` suffix. */
2299
+ private _canvasCssPx;
2142
2300
  /** Route an async render failure to `onError`, or `console.error` when none is
2143
2301
  * set (so failures are never fully silent), and never after teardown. */
2144
2302
  private _reportRenderError;
@@ -2435,6 +2593,13 @@ declare interface DocxScrollViewerOptions extends Omit<RenderPageOptions, 'onTex
2435
2593
  * new tab via core `openExternalHyperlink` (sanitised, noopener,noreferrer);
2436
2594
  * internal → jump to the page whose text contains the bookmark (best-effort). */
2437
2595
  onHyperlinkClick?: (target: HyperlinkTarget) => void;
2596
+ /** IX1 — master switch for hyperlink interactivity. Default `true`. When
2597
+ * `false`, the hyperlink machinery is not wired at all: no overlay hit region
2598
+ * is installed for link runs, so there is no pointer cursor, no title tooltip,
2599
+ * no default navigation (external new-tab / internal bookmark jump), and
2600
+ * `onHyperlinkClick` is never called. Links still render exactly as authored
2601
+ * but are inert, like plain text. */
2602
+ enableHyperlinks?: boolean;
2438
2603
  /** Error callback. When set, `load()` invokes it and resolves (otherwise the
2439
2604
  * error is rethrown — shared viewer error contract). It ALSO fires for async
2440
2605
  * per-slot render failures (both main `renderPage` and worker
@@ -2533,12 +2698,22 @@ declare interface DocxTextRun {
2533
2698
  /** ECMA-376 §17.3.2.20 `<w:lang w:bidi>` — complex-script (RTL) language tag,
2534
2699
  * lower-cased (e.g. "ar-sa", "ae-ar"). Drives Word's AN digit ordering. */
2535
2700
  langBidi?: string;
2701
+ /** ECMA-376 §17.3.2.34 `<w:snapToGrid>` — false opts this run out of the
2702
+ * section character grid; absent inherits participation. */
2703
+ snapToGrid?: boolean;
2536
2704
  /** ECMA-376 §17.3.2.35 `<w:spacing w:val>` — character-spacing adjustment in
2537
2705
  * POINTS (signed): the extra pitch added after each character before the next
2538
2706
  * is rendered. The renderer feeds it to `ctx.letterSpacing` on BOTH the
2539
2707
  * measure and paint passes so line breaking / pagination stay consistent.
2540
2708
  * Absent ⇒ no extra pitch. */
2541
2709
  charSpacing?: number;
2710
+ /** ECMA-376 §17.3.2.14 `<w:fitText>` — manual run-width target in TWIPS
2711
+ * (`w:val`, 1/20 pt) plus the optional `w:id` that links consecutive runs
2712
+ * into one region. The arbitrary-precision XSD integer id is serialized as a
2713
+ * string; numeric synthetic inputs remain supported for layout tests and
2714
+ * direct model construction. An id-less run is always standalone. */
2715
+ fitTextVal?: number;
2716
+ fitTextId?: string | number;
2542
2717
  /** ECMA-376 §17.3.2.43 `<w:w w:val>` — horizontal text scale as a FRACTION of
2543
2718
  * normal character width (0.67 = 67%, 2.0 = 200%). Stretches each glyph's
2544
2719
  * width, not the gap between glyphs. Absent ⇒ 100%. */
@@ -2592,6 +2767,9 @@ declare interface DocxTextRunInfo {
2592
2767
  fontSize: number;
2593
2768
  /** CSS `font` shorthand used for canvas drawing (e.g. `"bold 16px Arial"`). */
2594
2769
  font: string;
2770
+ /** Uniform per-code-point pitch in CSS px used to draw a horizontal run.
2771
+ * Absent when the pitch is zero or the run uses vertical / 縦中横 paint. */
2772
+ letterSpacingPx?: number;
2595
2773
  /** ECMA-376 §17.6.20 (tbRl) — when the page is vertical the canvas is the
2596
2774
  * physical landscape page rotated +90° at paint, so this run's `x`/`y` are the
2597
2775
  * PHYSICAL top-left the overlay span must sit at, and `transform` is the CSS
@@ -2801,6 +2979,11 @@ declare class DocxViewer implements ZoomableViewer {
2801
2979
  /** Draw the find-highlight boxes for the current page from its runs. Clears
2802
2980
  * the overlay when there is no active find. */
2803
2981
  private _buildHighlightLayer;
2982
+ /** The canvas's intended CSS box in px (the % denominators the overlay builders
2983
+ * expect). Reads the inline `style.width`/`height` set by the render path
2984
+ * (which mirror the render's logical size), falling back to the backing-store
2985
+ * dimensions when unset. Parsing tolerates the trailing `px`. */
2986
+ private _canvasCssPx;
2804
2987
  /** A width-measurer primed with `font`, backed by a private 1×1 canvas so it
2805
2988
  * never disturbs the visible canvas's context state. */
2806
2989
  private _measureForFont;
@@ -2819,6 +3002,12 @@ declare class DocxViewer implements ZoomableViewer {
2819
3002
  * {@link DocxDocument.getBookmarkPage} (ECMA-376 §17.16.23) and jumps there
2820
3003
  * with {@link goToPage}. An anchor naming no known bookmark is a safe no-op
2821
3004
  * rather than a jump to a guessed page.
3005
+ *
3006
+ * IX1 — returns `undefined` when `enableHyperlinks` is `false`, the single gate
3007
+ * that disables hyperlink interactivity: {@link buildDocxTextLayer} treats a
3008
+ * missing handler as "render link runs like plain runs", so no hit region,
3009
+ * cursor, tooltip, listener, or navigation is wired (a custom
3010
+ * `onHyperlinkClick` is suppressed too).
2822
3011
  */
2823
3012
  private _hyperlinkHandler;
2824
3013
  }
@@ -2848,6 +3037,15 @@ declare interface DocxViewerOptions extends RenderPageOptions, LoadOptions_4 {
2848
3037
  * new tab via core `openExternalHyperlink` (sanitised, noopener,noreferrer);
2849
3038
  * internal → jump to the page whose text contains the bookmark (best-effort). */
2850
3039
  onHyperlinkClick?: (target: HyperlinkTarget) => void;
3040
+ /** IX1 — master switch for hyperlink interactivity. Default `true`. When
3041
+ * `false`, the hyperlink machinery is not wired at all: no overlay hit region
3042
+ * is installed for link runs, so there is no pointer cursor, no title tooltip,
3043
+ * no default navigation (external new-tab / internal bookmark jump), and
3044
+ * `onHyperlinkClick` is never called. Links still render exactly as authored
3045
+ * (their colour/underline are painted on the canvas) but are inert, like plain
3046
+ * text. Set it to disable clickable links entirely — e.g. in a preview where
3047
+ * navigation must not leave the current view. */
3048
+ enableHyperlinks?: boolean;
2851
3049
  /** Called on parse or render errors. */
2852
3050
  onError?: (err: Error) => void;
2853
3051
  }
@@ -3245,6 +3443,14 @@ declare interface ImageFill {
3245
3443
  tile?: TileInfo;
3246
3444
  /** `a:blip > a:alphaModFix@amt` as a fraction (0.0–1.0). Absent = opaque. */
3247
3445
  alpha?: number;
3446
+ /**
3447
+ * ECMA-376 §20.1.8.23 `<a:duotone>` recolour, resolved to its two endpoint
3448
+ * colours (through the slide theme). Absent ⇒ no duotone. When present the
3449
+ * renderer maps the blip's luminance ramp between the two colours (core
3450
+ * `applyDuotone`) — the same recolour a `<p:pic>` duotone applies, wired onto
3451
+ * the picture-FILL path (§20.1.8.14) by issue #889.
3452
+ */
3453
+ duotone?: Duotone;
3248
3454
  }
3249
3455
 
3250
3456
  declare interface ImageRun {
@@ -3283,6 +3489,10 @@ declare interface ImageRun {
3283
3489
  } | null;
3284
3490
  widthPt: number;
3285
3491
  heightPt: number;
3492
+ /** Effective DrawingML transform for grouped pictures. */
3493
+ rotation?: number;
3494
+ flipH?: boolean;
3495
+ flipV?: boolean;
3286
3496
  /** true = wp:anchor (absolute positioned), false/undefined = wp:inline (flows with text) */
3287
3497
  anchor?: boolean;
3288
3498
  /** X offset in pt (anchor only) */
@@ -3782,6 +3992,9 @@ declare interface MediaElement {
3782
3992
  y: number;
3783
3993
  width: number;
3784
3994
  height: number;
3995
+ rotation: number;
3996
+ flipH: boolean;
3997
+ flipV: boolean;
3785
3998
  /** "audio" or "video" */
3786
3999
  mediaKind: 'audio' | 'video';
3787
4000
  /** Poster image zip path (e.g. "ppt/media/image2.png"). Empty when no poster. */
@@ -3846,6 +4059,19 @@ declare interface NumberingInfo {
3846
4059
  * this family. Absent ⇒ the renderer falls back to
3847
4060
  * {@link NumberingInfo.fontFamily}. */
3848
4061
  fontFamilyEastAsia?: string | null;
4062
+ /** ECMA-376 §17.9.24 — the numbering level rPr's `w:color` (hex 6 without
4063
+ * `#`, lowercased). Colors the marker glyph only, never the paragraph's
4064
+ * runs. Absent ⇒ the renderer falls back to
4065
+ * {@link DocParagraph.paragraphMarkColor} (§17.3.1.29 — Word layers the
4066
+ * level rPr over the paragraph mark's run properties) and finally to its
4067
+ * default ink. An explicit `w:val="auto"` is absent here + {@link colorAuto}. */
4068
+ color?: string | null;
4069
+ /** ECMA-376 §17.3.2.6 / ST_HexColorAuto (§17.18.39) — true when the level
4070
+ * rPr carries an EXPLICIT `w:color w:val="auto"`. Auto names no concrete
4071
+ * color but is not "unset": it breaks the paragraph-mark fallback, so the
4072
+ * marker draws the automatic (default) ink instead of
4073
+ * {@link DocParagraph.paragraphMarkColor}. */
4074
+ colorAuto?: boolean;
3849
4075
  /** ECMA-376 §17.9.9/§17.9.20 — when the level uses a `<w:lvlPicBulletId>`,
3850
4076
  * the marker is this image (zip path, e.g. `word/media/image1.gif`), drawn in
3851
4077
  * place of {@link NumberingInfo.text}. Absent ⇒ ordinary text/glyph marker. */
@@ -4043,6 +4269,14 @@ declare interface Paragraph_2 extends Paragraph {
4043
4269
  * emits an effective boolean.
4044
4270
  */
4045
4271
  eaLnBrk: boolean;
4272
+ /**
4273
+ * `<a:pPr defTabSz>` (ECMA-376 §21.1.2.2.7) — the default tab-stop interval in
4274
+ * EMU. When a `\t` has no reachable explicit `a:tabLst` stop, it advances to
4275
+ * the next multiple of this grid (issue #1006). Absent ⇒ the renderer uses the
4276
+ * PowerPoint universal default of 914400 EMU (1 inch). Omitted from JSON when
4277
+ * the parser found no explicit value.
4278
+ */
4279
+ defTabSz?: number;
4046
4280
  }
4047
4281
 
4048
4282
  declare interface ParagraphBorders {
@@ -5007,6 +5241,15 @@ declare class PptxScrollViewer implements ZoomableViewer {
5007
5241
  * to the target slide via {@link scrollToSlide} once the action resolves to a
5008
5242
  * slide index (a jump resolving to no reachable slide is a safe no-op).
5009
5243
  */
5244
+ /**
5245
+ * IX1 — the click handler passed to the text-layer overlay, or `undefined` when
5246
+ * `enableHyperlinks` is `false`. This is the single gate that disables hyperlink
5247
+ * interactivity: {@link buildPptxTextLayer} renders link runs exactly like plain
5248
+ * runs when no handler is supplied, so no hit region, cursor, tooltip, listener,
5249
+ * or navigation is wired (a custom `onHyperlinkClick` is suppressed too). When
5250
+ * enabled, the returned handler dispatches through {@link _onHyperlinkClick}.
5251
+ */
5252
+ private _hyperlinkHandler;
5010
5253
  private _onHyperlinkClick;
5011
5254
  /** Populate an internal {@link HyperlinkTarget}'s `slideIndex` from its `ref`
5012
5255
  * via the engine's stamped part names. Relative `hlinkshowjump` verbs are
@@ -5173,6 +5416,13 @@ declare interface PptxScrollViewerOptions extends Omit<RenderSlideOptions, 'onTe
5173
5416
  * instead and takes NO default action.
5174
5417
  */
5175
5418
  onHyperlinkClick?: (target: HyperlinkTarget) => void;
5419
+ /** IX1 — master switch for hyperlink interactivity. Default `true`. When
5420
+ * `false`, the hyperlink machinery is not wired at all: the overlay's link
5421
+ * spans are non-interactive, so there is no pointer cursor, no title tooltip,
5422
+ * no default navigation (external new-tab / internal slide jump), and
5423
+ * `onHyperlinkClick` is never called. Links still render exactly as authored
5424
+ * but are inert, like plain text. */
5425
+ enableHyperlinks?: boolean;
5176
5426
  }
5177
5427
 
5178
5428
  /** Information about a rendered text segment for building a transparent selection overlay. */
@@ -5412,6 +5662,15 @@ declare class PptxViewer implements ZoomableViewer {
5412
5662
  /** Rebuild the highlight overlay for the current slide from cached runs. */
5413
5663
  private _redrawHighlights;
5414
5664
  private _buildTextLayer;
5665
+ /**
5666
+ * IX1 — the click handler passed to the text-layer overlay, or `undefined` when
5667
+ * `enableHyperlinks` is `false`. This is the single gate that disables hyperlink
5668
+ * interactivity: {@link buildPptxTextLayer} renders link runs exactly like plain
5669
+ * runs when no handler is supplied, so no hit region, cursor, tooltip, listener,
5670
+ * or navigation is wired (a custom `onHyperlinkClick` is suppressed too). When
5671
+ * enabled, the returned handler dispatches through {@link _onHyperlinkClick}.
5672
+ */
5673
+ private _hyperlinkHandler;
5415
5674
  /**
5416
5675
  * IX1/IX-nav hyperlink click dispatch. An internal target is first *enriched*
5417
5676
  * with its resolved 0-based `slideIndex` (via
@@ -5508,6 +5767,14 @@ declare interface PptxViewerOptions extends RenderOptions, LoadOptions {
5508
5767
  * viewer calls this instead and takes NO default action.
5509
5768
  */
5510
5769
  onHyperlinkClick?: (target: HyperlinkTarget) => void;
5770
+ /** IX1 — master switch for hyperlink interactivity. Default `true`. When
5771
+ * `false`, the hyperlink machinery is not wired at all: the overlay's link
5772
+ * spans are non-interactive, so there is no pointer cursor, no title tooltip,
5773
+ * no default navigation (external new-tab / internal slide jump), and
5774
+ * `onHyperlinkClick` is never called. Links still render exactly as authored
5775
+ * (theme `hlink` colour + underline are painted on the canvas) but are inert,
5776
+ * like plain text. */
5777
+ enableHyperlinks?: boolean;
5511
5778
  }
5512
5779
 
5513
5780
  declare interface Presentation {
@@ -5794,6 +6061,10 @@ declare interface RubyAnnotation {
5794
6061
  text: string;
5795
6062
  /** Annotation font size in pt. Word stores this as half-points in `<w:hps>`. */
5796
6063
  fontSizePt: number;
6064
+ /** Distance “between the phonetic guide base text and the phonetic guide
6065
+ * text” in pt. Word stores this as half-points in `<w:hpsRaise>`
6066
+ * (ECMA-376 §17.3.3.12). */
6067
+ hpsRaisePt?: number;
5797
6068
  }
5798
6069
 
5799
6070
  declare interface Run {
@@ -6067,6 +6338,14 @@ declare interface ShapeElement {
6067
6338
  /** `<a:sp3d>` 3D shape properties (ECMA-376 §20.1.5.12). Parsed but not
6068
6339
  * rendered in Phase A. */
6069
6340
  sp3d?: Sp3d;
6341
+ /** `<p:nvSpPr><p:cNvPr @id>` — DrawingML cNvPr id. Present for file-authored
6342
+ * shapes (the attribute is schema-required); absent on parser-synthesized
6343
+ * shapes such as the SmartArt data-model fallback. */
6344
+ id?: string;
6345
+ /** `<p:nvSpPr><p:cNvPr @name>` — author-visible shape name (e.g. "Title 1").
6346
+ * The SmartArt data-model fallback synthesizes `name: "SmartArt"` with no
6347
+ * {@link ShapeElement.id} (see smartart-fallback-contrast.ts). */
6348
+ name?: string;
6070
6349
  /** Shape-level hyperlink target resolved from `<p:cNvPr><a:hlinkClick @r:id>`
6071
6350
  * via slide _rels (ECMA-376 §21.1.2.3.5). For an external link this is the
6072
6351
  * URL; for an internal slide jump it is the resolved internal part name.
@@ -6142,6 +6421,9 @@ declare interface ShapeInfo {
6142
6421
  h: number;
6143
6422
  /** Rotation in degrees, clockwise. */
6144
6423
  rot: number;
6424
+ /** Effective DrawingML reflection after composing parent groups. */
6425
+ flipH?: boolean;
6426
+ flipV?: boolean;
6145
6427
  fillColor?: string;
6146
6428
  strokeColor?: string;
6147
6429
  /** Stroke width in EMU. 0 = no stroke. */
@@ -6216,7 +6498,7 @@ declare interface ShapeRun {
6216
6498
  groupHeightPt?: number | null;
6217
6499
  /** Draw behind text when true (wp:anchor behindDoc="1"). */
6218
6500
  behindDoc?: boolean;
6219
- /** Document-order index within a group; lower values render first. */
6501
+ /** ECMA-376 §20.4.2.3 `wp:anchor/@relativeHeight`: lower values render first. */
6220
6502
  zOrder: number;
6221
6503
  /** Normalized [0,1] custom-geometry sub-paths. Empty when `presetGeometry`
6222
6504
  * is set; the renderer chooses between buildCustomPath and buildShapePath. */
@@ -6224,13 +6506,17 @@ declare interface ShapeRun {
6224
6506
  /** OOXML <a:prstGeom prst> name (e.g. "rect", "ellipse", "rtTriangle").
6225
6507
  * When set the renderer calls core's buildShapePath with `adjValues`. */
6226
6508
  presetGeometry?: string | null;
6227
- /** Up to four <a:gd name="adj{n}"> values from prstGeom/avLst (0–100000). */
6228
- adjValues?: number[];
6509
+ /** <a:gd name="adj{n}"> values from prstGeom/avLst in adj1..adj8 order.
6510
+ * `null` preserves omitted named guides so the preset engine can use the
6511
+ * geometry's default for that index. */
6512
+ adjValues?: Array<number | null>;
6229
6513
  fill: ShapeFill | null;
6230
6514
  stroke: string | null;
6231
6515
  strokeWidth?: number;
6232
6516
  /** `<a:ln><a:prstDash val>` — ECMA-376 §20.1.8.48. Absent = solid. */
6233
6517
  strokeDash?: string | null;
6518
+ /** Normalized line cap: `butt` | `round` | `square`. */
6519
+ strokeCap?: CanvasLineCap | null;
6234
6520
  /** `<a:ln><a:headEnd>` line-start decoration (ECMA-376 §20.1.8.3). */
6235
6521
  headEnd?: LineEnd | null;
6236
6522
  /** `<a:ln><a:tailEnd>` line-end decoration (ECMA-376 §20.1.8.3). */
@@ -6275,6 +6561,14 @@ declare interface ShapeRun {
6275
6561
  textInsetT?: number;
6276
6562
  textInsetR?: number;
6277
6563
  textInsetB?: number;
6564
+ /** ECMA-376 §20.1.10.83 ST_TextVerticalType — the text-body flow direction from
6565
+ * `<wps:bodyPr vert>` / `<a:bodyPr vert>`. Recognised vertical values:
6566
+ * "vert" (all glyphs 90° CW, chars T→B, lines R→L), "vert270" (all glyphs 270°
6567
+ * CW = 90° CCW, chars B→T, lines L→R), and "eaVert" (East-Asian upright: CJK
6568
+ * stands upright, non-EA rotated 90°, chars T→B, lines R→L). "horz"/absent ⇒
6569
+ * horizontal (unchanged). Unrecognised values ("mongolianVert", "wordArtVert",
6570
+ * …) fall back to horizontal until implemented. */
6571
+ textVert?: string | null;
6278
6572
  /** ECMA-376 Part 4 §19.1.2.23 `<v:textpath>` — WordArt text laid on the
6279
6573
  * shape path (a text watermark). When set the renderer draws this string,
6280
6574
  * scaled to fill the box (`fitshape`), rotated by {@link ShapeRun.rotation},
@@ -6330,6 +6624,8 @@ declare interface ShapeText_2 {
6330
6624
  * (image blocks / legacy single-format paragraphs). Absent for image-only
6331
6625
  * paragraphs. */
6332
6626
  runs?: ShapeTextRun_2[];
6627
+ /** ECMA-376 §17.9 paragraph numbering for text-box paragraphs. */
6628
+ numbering?: NumberingInfo | null;
6333
6629
  alignment: string;
6334
6630
  /** ECMA-376 §17.3.1.33 `<w:spacing w:before>` of this text-box paragraph, in
6335
6631
  * pt — reserved ABOVE the paragraph inside the box. Absent/0 ⇒ no offset. */
@@ -6367,6 +6663,19 @@ declare interface ShapeText_2 {
6367
6663
  * base direction for the UAX#9 reordering pass (the body renderer reads the
6368
6664
  * identical field). */
6369
6665
  bidi?: boolean;
6666
+ /** ECMA-376 §17.3.1.9 `<w:contextualSpacing>` — resolved through the style
6667
+ * chain in the parser. When set, this text-box paragraph drops its OWN
6668
+ * contribution to the collapsed gap against an ADJACENT paragraph that
6669
+ * shares its {@link ShapeText.styleId} (per-side, Word-adjudicated — issue
6670
+ * #1015; identical to {@link DocParagraph.contextualSpacing} via the
6671
+ * renderer's `contextualSpacingAdjust`). Absent ⇒ no suppression. */
6672
+ contextualSpacing?: boolean;
6673
+ /** Resolved paragraph style id of this text-box paragraph — the explicit
6674
+ * `<w:pStyle>`, else the document default paragraph style, else "Normal" (the
6675
+ * same stable id {@link DocParagraph.styleId} carries). Paired with
6676
+ * {@link ShapeText.contextualSpacing} to group adjacent same-style paragraphs
6677
+ * for §17.3.1.9. */
6678
+ styleId?: string | null;
6370
6679
  /** Zip path of an inline image inside this text-box paragraph
6371
6680
  * (`<w:drawing><wp:inline><a:blip r:embed>`), e.g. `word/media/image1.emf`.
6372
6681
  * Absent for a text-only paragraph. */
@@ -6438,6 +6747,8 @@ declare interface ShapeTextRun_2 {
6438
6747
  fontFamilyEastAsia?: string | null;
6439
6748
  bold?: boolean;
6440
6749
  italic?: boolean;
6750
+ /** ECMA-376 §17.3.3.25 ruby annotation (furigana) for text-box runs. */
6751
+ ruby?: RubyAnnotation | null;
6441
6752
  }
6442
6753
 
6443
6754
  declare interface SharedString {
@@ -6640,6 +6951,8 @@ declare interface Stroke {
6640
6951
  width: number;
6641
6952
  /** OOXML prstDash value: "dash", "dot", "dashDot", "lgDash", "lgDashDot", etc. */
6642
6953
  dashStyle?: string;
6954
+ /** Canvas line cap normalized from DrawingML/VML (`flat` → `butt`). */
6955
+ lineCap?: CanvasLineCap;
6643
6956
  /** Arrow head at the start of the line */
6644
6957
  headEnd?: ArrowEnd;
6645
6958
  /** Arrow head at the end of the line */
@@ -6709,6 +7022,9 @@ declare interface TableElement {
6709
7022
  y: number;
6710
7023
  width: number;
6711
7024
  height: number;
7025
+ rotation: number;
7026
+ flipH: boolean;
7027
+ flipV: boolean;
6712
7028
  /** Column widths in EMU */
6713
7029
  cols: number[];
6714
7030
  rows: TableRow[];
@@ -6766,7 +7082,10 @@ declare interface TableRow {
6766
7082
  }
6767
7083
 
6768
7084
  declare interface TabStop {
6769
- /** Position in EMU from the left edge of the text area (after lIns) */
7085
+ /** Position in EMU from the LEADING text-inset edge of the text area
7086
+ * logical, not physical (ECMA-376 §21.1.2.1): the left edge (after lIns)
7087
+ * in an LTR paragraph, the right edge (before rIns) in an RTL
7088
+ * (`<a:pPr rtl="1">`) paragraph. */
6770
7089
  pos: number;
6771
7090
  /** Alignment: "l" | "r" | "ctr" | "dec" */
6772
7091
  algn: string;
@@ -7803,7 +8122,13 @@ declare class XlsxViewer implements ZoomableViewer {
7803
8122
  * match the renderer's `hyperlinkMap` exactly (`${hl.row}:${hl.col}`). */
7804
8123
  private buildHyperlinkMap;
7805
8124
  /** IX1 — the hyperlink at a cell, or null. `getCellAt` returns 1-based
7806
- * {row,col}, matching the parser/renderer keying. */
8125
+ * {row,col}, matching the parser/renderer keying.
8126
+ *
8127
+ * Returns null unconditionally when `enableHyperlinks` is `false`: this is the
8128
+ * single gate that disables hyperlink interactivity. Both consumers — the
8129
+ * pointermove pointer-cursor affordance and the click dispatch
8130
+ * ({@link dispatchHyperlink}) — funnel through this hit-test, so a null result
8131
+ * means no cursor change, no default navigation, and no `onHyperlinkClick`. */
7807
8132
  private hyperlinkAtCell;
7808
8133
  /**
7809
8134
  * IX1 — dispatch a click on a hyperlinked cell. Builds a
@@ -7990,6 +8315,13 @@ declare interface XlsxViewerOptions extends LoadOptions_2 {
7990
8315
  * default handler's job, so a blocked scheme still reaches a custom callback).
7991
8316
  */
7992
8317
  onHyperlinkClick?: (target: HyperlinkTarget) => void;
8318
+ /** IX1 — master switch for hyperlink interactivity. Default `true`. When
8319
+ * `false`, the cell hit-test reports no hyperlink under any cell, so hyperlink
8320
+ * interactivity is disabled entirely: no pointer cursor over a link, no default
8321
+ * navigation (external new-tab / internal sheet jump), and `onHyperlinkClick`
8322
+ * is never called. Hyperlinked cells still render exactly as authored but are
8323
+ * inert. */
8324
+ enableHyperlinks?: boolean;
7993
8325
  /**
7994
8326
  * Color of the cell-selection highlight. A single CSS color drives both the
7995
8327
  * selection rectangle's border (drawn in this color) and its fill (the same
@@ -8135,6 +8467,14 @@ declare class XlsxWorkbook {
8135
8467
  * validation-list expansion use). Returns `''` before the workbook is loaded.
8136
8468
  */
8137
8469
  cellText(ws: Worksheet, cell: Cell): string;
8470
+ /**
8471
+ * Render a sheet viewport into `target`. Note: `opts.fetchImage` is ignored
8472
+ * here — image bytes always come from this workbook's own archive through its
8473
+ * stable per-instance loader, whose closure identity keys the shared decoded
8474
+ * caches, the render-pass lease, and {@link destroy}'s cache drops. Callers
8475
+ * needing a custom byte source should use the standalone
8476
+ * `renderWorksheetViewport` orchestrator directly.
8477
+ */
8138
8478
  renderViewport(target: HTMLCanvasElement | OffscreenCanvas, sheetIndex: number, viewport: ViewportRange, opts?: RenderViewportOptions): Promise<void>;
8139
8479
  /**
8140
8480
  * Render a sheet viewport and return it as an ImageBitmap (both modes; in