@silurus/ooxml 0.57.0 → 0.59.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -251,6 +251,8 @@ declare type CfRule = {
251
251
  } | {
252
252
  type: 'aboveAverage';
253
253
  aboveAverage: boolean;
254
+ equalAverage?: boolean;
255
+ stdDev?: number;
254
256
  dxfId: number | null;
255
257
  priority: number;
256
258
  } | {
@@ -848,6 +850,28 @@ declare interface DataPointOverride {
848
850
  markerLine?: string;
849
851
  }
850
852
 
853
+ /** One `<dataValidation>` rule (ECMA-376 §18.3.1.33). `type` is the constraint
854
+ * class (`list` | `whole` | `decimal` | `date` | `time` | `textLength` |
855
+ * `custom`); `operator` qualifies it (`between` | `notBetween` | `equal` | …).
856
+ * `formula1` / `formula2` are the operands (for `list`, `formula1` is the
857
+ * comma-separated literal list or a range/named reference). 1:1 with the Rust
858
+ * `DataValidation` (serde camelCase). */
859
+ declare interface DataValidation {
860
+ /** Affected cell ranges, verbatim from `@sqref` (space-separated A1 refs). */
861
+ sqref: string;
862
+ /** Constraint class. Absent means the spec default (`none`, no constraint). */
863
+ validationType?: string;
864
+ operator?: string;
865
+ formula1?: string;
866
+ formula2?: string;
867
+ /** `@allowBlank` — empty input is permitted. */
868
+ allowBlank?: boolean;
869
+ promptTitle?: string;
870
+ prompt?: string;
871
+ errorTitle?: string;
872
+ errorMessage?: string;
873
+ }
874
+
851
875
  declare interface DefinedName {
852
876
  name: string;
853
877
  formula: string;
@@ -863,7 +887,12 @@ declare interface DocComment {
863
887
 
864
888
  declare interface DocNote {
865
889
  id: string;
866
- text: string;
890
+ /** ECMA-376 §17.11.2 / §17.11.10 — the note's block-level content
891
+ * (paragraphs / nested tables), parsed with the document's styles +
892
+ * numbering. The leading run is the `<w:footnoteRef/>` auto-number marker
893
+ * (carries a {@link DocxTextRun.noteRef}). Use {@link noteText} to extract
894
+ * the plain-text body without the marker. */
895
+ content: BodyElement[];
867
896
  }
868
897
 
869
898
  declare interface DocParagraph {
@@ -905,10 +934,21 @@ declare interface DocParagraph {
905
934
  defaultFontFamily?: string | null;
906
935
  /**
907
936
  * ECMA-376 §17.3.1.6 `<w:bidi>` — right-to-left paragraph. `true` = RTL,
908
- * `false` = explicitly LTR, absent = unspecified (inherit). Phase 0 of RTL
909
- * support: recorded only; alignment/column-order resolution is deferred.
937
+ * `false` = explicitly LTR, absent = unspecified (inherit). The renderer uses
938
+ * this as the paragraph base direction: it seeds the UAX#9 reordering pass
939
+ * (`computeLineVisualOrder`), swaps the left/right indents, resolves the
940
+ * `w:jc` start/end edges (`resolveAlignEdge`), and lays out lines from the
941
+ * right.
910
942
  */
911
943
  bidi?: boolean;
944
+ /**
945
+ * ECMA-376 §17.3.1.32 `<w:snapToGrid>` — when `false`, this paragraph opts out
946
+ * of the section's document grid (`w:docGrid`): its lines use natural font
947
+ * metrics / the line-spacing multiplier directly instead of snapping to the
948
+ * grid pitch. `undefined` = inherit (default on). Set on Word's "Footnote
949
+ * Text" style, so footnote bodies use compact natural line height.
950
+ */
951
+ snapToGrid?: boolean;
912
952
  }
913
953
 
914
954
  declare interface DocRevision {
@@ -936,6 +976,7 @@ declare type DocRun = {
936
976
  nodes: MathNode[];
937
977
  display: boolean;
938
978
  fontSize: number;
979
+ jc?: string;
939
980
  };
940
981
 
941
982
  declare interface DocSettings {
@@ -949,6 +990,10 @@ declare interface DocSettings {
949
990
  /** §17.15.1.59 `w:noLineBreaksAfter@w:val` — custom set of characters that
950
991
  * cannot end a line (行末禁則). Replaces the default when present. */
951
992
  noLineBreaksAfter?: string;
993
+ /** §22.1.2.30 `m:mathPr/m:defJc@m:val` — document-wide default math
994
+ * justification (ST_Jc math: left|right|center|centerGroup). `undefined`
995
+ * ⇒ the renderer uses the spec default `centerGroup`. */
996
+ mathDefJc?: string;
952
997
  }
953
998
 
954
999
  declare interface DocTable {
@@ -973,8 +1018,8 @@ declare interface DocTable {
973
1018
  /**
974
1019
  * ECMA-376 §17.4.1 `<w:bidiVisual>` — render columns in right-to-left
975
1020
  * (visual) order. `true` = RTL columns, `false` = explicitly LTR, absent =
976
- * unspecified. Phase 0 of RTL support: recorded only; column-order
977
- * resolution is deferred.
1021
+ * unspecified. When `true` the renderer mirrors the grid so logical column 0
1022
+ * is placed rightmost, and flips per-cell left/right borders accordingly.
978
1023
  */
979
1024
  bidiVisual?: boolean;
980
1025
  }
@@ -1015,10 +1060,12 @@ export declare namespace docx {
1015
1060
  export {
1016
1061
  DocxDocument,
1017
1062
  LoadOptions_4 as LoadOptions,
1063
+ WireRenderPageOptions,
1018
1064
  DocxViewer,
1019
1065
  DocxViewerOptions,
1020
1066
  autoResize,
1021
1067
  AutoResizeOptions,
1068
+ noteText,
1022
1069
  DocxDocumentModel,
1023
1070
  DocSettings,
1024
1071
  SectionProps,
@@ -1039,6 +1086,7 @@ export declare namespace docx {
1039
1086
  DocRevision,
1040
1087
  DocComment,
1041
1088
  DocNote,
1089
+ NoteRef,
1042
1090
  LineSpacing,
1043
1091
  TabStop_2 as TabStop,
1044
1092
  ParagraphBorders,
@@ -1058,7 +1106,9 @@ export declare namespace docx {
1058
1106
 
1059
1107
  declare class DocxDocument {
1060
1108
  private _document;
1109
+ private _meta;
1061
1110
  private _pages;
1111
+ private _mode;
1062
1112
  private _worker;
1063
1113
  private _bridge;
1064
1114
  private constructor();
@@ -1066,9 +1116,46 @@ declare class DocxDocument {
1066
1116
  private _parse;
1067
1117
  destroy(): void;
1068
1118
  get pageCount(): number;
1119
+ /**
1120
+ * The raw parsed document model. Available only in `mode: 'main'`; in
1121
+ * `mode: 'worker'` the model stays in the worker and this throws.
1122
+ */
1069
1123
  get document(): DocxDocumentModel;
1124
+ /**
1125
+ * ECMA-376 §17.13.4 — the document's comments (`word/comments.xml`), each with
1126
+ * id / author / initials / date / plain-text body. Comments are a data-only
1127
+ * API: they are NOT drawn on the page (Word renders them in a margin pane /
1128
+ * balloons, which this viewer does not reproduce). Use this to build a review
1129
+ * panel, export an annotation list, etc. Returns `[]` when the document has no
1130
+ * comments part. The same data is also reachable via `document.comments`.
1131
+ */
1132
+ get comments(): DocComment[];
1133
+ /**
1134
+ * ECMA-376 §17.11.10 — the document's footnotes (`word/footnotes.xml`),
1135
+ * excluding the reserved separator entries. Each note carries its `id` and
1136
+ * block-level `content`; use {@link noteText} for the plain-text body. These
1137
+ * ARE drawn at the bottom of the page that holds their reference; this getter
1138
+ * additionally exposes them as data. Returns `[]` when absent.
1139
+ */
1140
+ get footnotes(): DocNote[];
1141
+ /**
1142
+ * ECMA-376 §17.11.4 — the document's endnotes (`word/endnotes.xml`). Same
1143
+ * shape as {@link footnotes}; rendered at the end of the document. Returns
1144
+ * `[]` when absent.
1145
+ */
1146
+ get endnotes(): DocNote[];
1070
1147
  private _getPages;
1071
1148
  renderPage(target: HTMLCanvasElement | OffscreenCanvas, pageIndex: number, opts?: RenderPageOptions): Promise<void>;
1149
+ /**
1150
+ * Render a page and return it as an ImageBitmap. Works in both modes; in
1151
+ * worker mode the render runs entirely off the main thread. Paint with:
1152
+ * `canvas.getContext('bitmaprenderer').transferFromImageBitmap(bitmap)`.
1153
+ *
1154
+ * The returned ImageBitmap is owned by the caller: pass it to
1155
+ * `transferFromImageBitmap` (which consumes it) or call `bitmap.close()`
1156
+ * when done, or its backing memory is held until GC.
1157
+ */
1158
+ renderPageToBitmap(pageIndex: number, opts?: WireRenderPageOptions): Promise<ImageBitmap>;
1072
1159
  }
1073
1160
 
1074
1161
  declare interface DocxDocumentModel {
@@ -1137,8 +1224,10 @@ declare interface DocxTextRun {
1137
1224
  * tracked changes appear inline. */
1138
1225
  revision?: RunRevision;
1139
1226
  /** ECMA-376 §17.3.2.30 `<w:rtl>` — complex-script / right-to-left run.
1140
- * `true` = RTL, `false` = explicitly LTR, absent = unspecified.
1141
- * Phase 0: recorded only; glyph-order resolution is deferred. */
1227
+ * `true` = RTL, `false` = explicitly LTR, absent = unspecified. The renderer
1228
+ * treats a `true` run as RTL for the UAX#9 pass (it forces complex-script
1229
+ * shaping and marks the segment so `computeLineVisualOrder` reorders it), and
1230
+ * draws the slice with `ctx.direction = 'rtl'` so Canvas mirrors the glyphs. */
1142
1231
  rtl?: boolean;
1143
1232
  /** ECMA-376 §17.3.2.7 `<w:cs/>` — complex-script run toggle: cs formatting
1144
1233
  * applies to ALL characters of the run (§17.3.2.26). Distinct from
@@ -1157,6 +1246,12 @@ declare interface DocxTextRun {
1157
1246
  /** ECMA-376 §17.3.2.20 `<w:lang w:bidi>` — complex-script (RTL) language tag,
1158
1247
  * lower-cased (e.g. "ar-sa", "ae-ar"). Drives Word's AN digit ordering. */
1159
1248
  langBidi?: string;
1249
+ /** ECMA-376 §17.11.6/.7/.16/.17 — set when this run is a footnote/endnote
1250
+ * reference marker (`<w:footnoteReference>` in the body, `<w:footnoteRef>` at
1251
+ * the start of the note's content, and the endnote equivalents). `text` holds
1252
+ * the raw `@w:id`; the renderer overrides the displayed glyph with the note's
1253
+ * sequential number. */
1254
+ noteRef?: NoteRef;
1160
1255
  }
1161
1256
 
1162
1257
  /** Information about a rendered text segment for building a transparent selection overlay. */
@@ -1183,6 +1278,12 @@ declare class DocxViewer {
1183
1278
  private _wrapper;
1184
1279
  private _textLayer;
1185
1280
  private _opts;
1281
+ private readonly _mode;
1282
+ /** The canvas's bitmaprenderer context, used only in worker mode (a canvas
1283
+ * holds one context type for its lifetime; the main-mode 2d render path is
1284
+ * never used on the same canvas). */
1285
+ private _bitmapCtx;
1286
+ private _warnedNoTextSelection;
1186
1287
  constructor(canvas: HTMLCanvasElement, opts?: DocxViewerOptions);
1187
1288
  /**
1188
1289
  * Load a DOCX from URL or ArrayBuffer and render the first page.
@@ -1280,7 +1381,20 @@ declare interface FieldRun {
1280
1381
  highlight?: string | null;
1281
1382
  }
1282
1383
 
1283
- declare type Fill = SolidFill | NoFill | GradientFill | PatternFill;
1384
+ declare type Fill = SolidFill | NoFill | GradientFill | PatternFill | ImageFill;
1385
+
1386
+ /**
1387
+ * ECMA-376 §20.1.8.30 (CT_RelativeRect) — the destination rectangle a stretched
1388
+ * blip is mapped into, as edge insets relative to the fill region. Values are
1389
+ * fractions (ST_Percentage / 100000); **negative values let the image bleed
1390
+ * past the box (overscan)**. Absent edges default to 0.
1391
+ */
1392
+ declare interface FillRect {
1393
+ l?: number;
1394
+ t?: number;
1395
+ r?: number;
1396
+ b?: number;
1397
+ }
1284
1398
 
1285
1399
  /** ECMA-376 §20.1.8.17 (CT_GlowEffect) — coloured halo with blur radius. */
1286
1400
  declare interface Glow {
@@ -1369,6 +1483,30 @@ declare interface ImageAnchor {
1369
1483
  dataUrl: string;
1370
1484
  }
1371
1485
 
1486
+ /**
1487
+ * Image fill — ECMA-376 §20.1.8.14 (CT_BlipFillProperties). The embedded blip
1488
+ * is resolved to a base64 data URL at parse time. Both fill-modes are modelled
1489
+ * and mutually exclusive: `stretch` (§20.1.8.56) carries {@link ImageFill.fillRect};
1490
+ * `tile` (§20.1.8.58) carries {@link ImageFill.tile}.
1491
+ */
1492
+ declare interface ImageFill {
1493
+ fillType: 'image';
1494
+ /** `data:<mime>;base64,…` of the embedded blip. */
1495
+ dataUrl: string;
1496
+ /**
1497
+ * `<a:stretch><a:fillRect>` insets. Absent → fills the whole box (or the
1498
+ * fill is tiled — see {@link ImageFill.tile}).
1499
+ */
1500
+ fillRect?: FillRect;
1501
+ /**
1502
+ * `<a:tile>` descriptor. Present only when the blipFill is tiled; mutually
1503
+ * exclusive with {@link ImageFill.fillRect}.
1504
+ */
1505
+ tile?: TileInfo;
1506
+ /** `a:blip > a:alphaModFix@amt` as a fraction (0.0–1.0). Absent = opaque. */
1507
+ alpha?: number;
1508
+ }
1509
+
1372
1510
  declare interface ImageRun {
1373
1511
  dataUrl: string;
1374
1512
  widthPt: number;
@@ -1435,8 +1573,8 @@ declare interface LegendManualLayout_2 {
1435
1573
  }
1436
1574
 
1437
1575
  /**
1438
- * `<a:lightRig>` — ECMA-376 §20.1.5.9 (`CT_LightRig`). Parsed for Phase B
1439
- * (lighting/bevel shading); the Phase A camera renderer ignores it.
1576
+ * `<a:lightRig>` — ECMA-376 §20.1.5.9 (`CT_LightRig`). Drives the bevel-lip
1577
+ * lighting (Phase B): `dir` selects the key-light octant.
1440
1578
  */
1441
1579
  declare interface LightRig {
1442
1580
  /** Light-rig preset (`ST_LightRigType`), e.g. "threePt". */
@@ -1461,9 +1599,16 @@ declare interface LineSpacing {
1461
1599
  explicit?: boolean;
1462
1600
  }
1463
1601
 
1464
- /** Options for {@link PptxPresentation.load}. The shared load-options type
1465
- * from `@silurus/ooxml-core` (`useGoogleFonts`, `maxZipEntryBytes`). */
1466
- declare type LoadOptions = LoadOptions_2;
1602
+ /** Options for {@link PptxPresentation.load}. */
1603
+ declare type LoadOptions = LoadOptions_2 & {
1604
+ /**
1605
+ * 'main' (default): parse in a worker, render on the main thread (current
1606
+ * behaviour). 'worker': parse AND render inside the worker; use
1607
+ * {@link PptxPresentation.renderSlideToBitmap} and paint the returned
1608
+ * ImageBitmap via an `ImageBitmapRenderingContext`. Requires OffscreenCanvas.
1609
+ */
1610
+ mode?: 'main' | 'worker';
1611
+ };
1467
1612
 
1468
1613
  /**
1469
1614
  * Common load-time options shared by the docx / pptx / xlsx
@@ -1505,9 +1650,19 @@ declare interface LoadOptions_2 {
1505
1650
  math?: MathRenderer;
1506
1651
  }
1507
1652
 
1508
- /** Options for {@link XlsxWorkbook.load}. The shared load-options type from
1509
- * `@silurus/ooxml-core` (`useGoogleFonts`, `maxZipEntryBytes`). */
1510
- declare type LoadOptions_3 = LoadOptions_2;
1653
+ /** Options for {@link XlsxWorkbook.load}. Extends the shared load-options type
1654
+ * from `@silurus/ooxml-core` (`useGoogleFonts`, `maxZipEntryBytes`, `math`)
1655
+ * with the worker-rendering mode. */
1656
+ declare interface LoadOptions_3 extends LoadOptions_2 {
1657
+ /**
1658
+ * 'main' (default): parse in a worker, render on the main thread (current
1659
+ * behaviour). 'worker': parse AND render inside the worker; use
1660
+ * {@link XlsxWorkbook.renderViewportToBitmap} and paint the returned
1661
+ * ImageBitmap via an `ImageBitmapRenderingContext`. Requires OffscreenCanvas.
1662
+ * The math engine is unavailable in this mode (equations are skipped).
1663
+ */
1664
+ mode?: 'main' | 'worker';
1665
+ }
1511
1666
 
1512
1667
  /** Options for {@link DocxDocument.load}. Extends the shared load-options type
1513
1668
  * from `@silurus/ooxml-core` (`useGoogleFonts`, `maxZipEntryBytes`) with the
@@ -1519,6 +1674,14 @@ declare interface LoadOptions_4 extends LoadOptions_2 {
1519
1674
  * omitted, equations are skipped and the ~3 MB engine never enters the bundle.
1520
1675
  */
1521
1676
  math?: MathRenderer;
1677
+ /**
1678
+ * 'main' (default): parse in a worker, render on the main thread (current
1679
+ * behaviour). 'worker': parse, paginate AND render inside the worker; use
1680
+ * {@link DocxDocument.renderPageToBitmap} and paint the returned ImageBitmap
1681
+ * via an `ImageBitmapRenderingContext`. Requires OffscreenCanvas. The math
1682
+ * engine is unavailable in this mode (equations are skipped).
1683
+ */
1684
+ mode?: 'main' | 'worker';
1522
1685
  }
1523
1686
 
1524
1687
  declare interface ManualLayout {
@@ -1693,6 +1856,20 @@ declare interface NoFill {
1693
1856
  fillType: 'none';
1694
1857
  }
1695
1858
 
1859
+ /** A footnote / endnote reference marker (ECMA-376 §17.11). */
1860
+ declare interface NoteRef {
1861
+ /** "footnote" | "endnote" */
1862
+ kind: 'footnote' | 'endnote' | string;
1863
+ /** `@w:id` linking the marker to its note. Empty for the in-note
1864
+ * `<w:footnoteRef/>` placeholder (the renderer uses the enclosing note). */
1865
+ id: string;
1866
+ }
1867
+
1868
+ /** Flatten a footnote/endnote's content to its plain-text body, excluding the
1869
+ * auto-number reference marker. Convenience for data-only consumers
1870
+ * (the renderer draws {@link DocNote.content} directly). */
1871
+ declare function noteText(note: DocNote): string;
1872
+
1696
1873
  declare interface NumberingInfo {
1697
1874
  numId: number;
1698
1875
  level: number;
@@ -1952,6 +2129,7 @@ export declare namespace pptx {
1952
2129
  PptxPresentation,
1953
2130
  LoadOptions,
1954
2131
  RenderSlideOptions,
2132
+ RenderSlideToBitmapOptions,
1955
2133
  renderSlide,
1956
2134
  RenderOptions,
1957
2135
  PptxTextRunInfo,
@@ -1961,6 +2139,7 @@ export declare namespace pptx {
1961
2139
  AutoResizeOptions,
1962
2140
  Presentation,
1963
2141
  Slide,
2142
+ PptxComment,
1964
2143
  SlideElement,
1965
2144
  ShapeElement,
1966
2145
  PictureElement,
@@ -1981,6 +2160,9 @@ export declare namespace pptx {
1981
2160
  NoFill,
1982
2161
  GradientFill,
1983
2162
  GradientStop,
2163
+ ImageFill,
2164
+ FillRect,
2165
+ TileInfo,
1984
2166
  Stroke,
1985
2167
  Shadow,
1986
2168
  Glow,
@@ -2000,6 +2182,17 @@ export declare namespace pptx {
2000
2182
  }
2001
2183
  }
2002
2184
 
2185
+ /** A single legacy slide comment (`<p:cm>` in `ppt/comments/commentN.xml`). */
2186
+ declare interface PptxComment {
2187
+ /** Resolved author name from `ppt/commentAuthors.xml`. Absent when the
2188
+ * authors file is missing or the `authorId` is out of range. */
2189
+ author?: string;
2190
+ /** `<p:cm @dt>` — ISO-8601 timestamp the comment was authored. */
2191
+ date?: string;
2192
+ /** Plain-text comment body (`<p:text>`). */
2193
+ text: string;
2194
+ }
2195
+
2003
2196
  /**
2004
2197
  * Headless PPTX rendering engine.
2005
2198
  *
@@ -2018,7 +2211,9 @@ export declare namespace pptx {
2018
2211
  declare class PptxPresentation {
2019
2212
  private readonly _worker;
2020
2213
  private readonly _bridge;
2214
+ private _mode;
2021
2215
  private _presentation;
2216
+ private _meta;
2022
2217
  private _mediaCache;
2023
2218
  private _workerReady;
2024
2219
  private _workerReadyCallbacks;
@@ -2037,8 +2232,38 @@ declare class PptxPresentation {
2037
2232
  get slideWidth(): number;
2038
2233
  /** Slide height in EMU. */
2039
2234
  get slideHeight(): number;
2235
+ /**
2236
+ * Speaker-notes text for a slide (`ppt/notesSlides/notesSlideN.xml`,
2237
+ * ECMA-376 §13.3.5 — Notes Slide). Returns the notes-body text as a single
2238
+ * string (paragraphs joined with `\n`), or `null` when the slide has no
2239
+ * notes part. The notes are parsed at {@link load} time, so this is a
2240
+ * synchronous lookup.
2241
+ *
2242
+ * `slideIndex` is 0-based. Unlike navigation methods it is *not* clamped:
2243
+ * an out-of-range or non-integer index returns `null` rather than the notes
2244
+ * of the nearest slide (so a tool iterating by index gets an honest "no
2245
+ * notes" instead of a duplicated neighbour).
2246
+ *
2247
+ * @example
2248
+ * const pres = await PptxPresentation.load(buffer);
2249
+ * for (let i = 0; i < pres.slideCount; i++) {
2250
+ * const notes = pres.getNotes(i);
2251
+ * if (notes) console.log(`Slide ${i + 1} notes:`, notes);
2252
+ * }
2253
+ */
2254
+ getNotes(slideIndex: number): string | null;
2040
2255
  /** Render a slide onto the given canvas. */
2041
- renderSlide(canvas: HTMLCanvasElement, slideIndex: number, opts?: RenderSlideOptions): Promise<void>;
2256
+ renderSlide(canvas: HTMLCanvasElement | OffscreenCanvas, slideIndex: number, opts?: RenderSlideOptions): Promise<void>;
2257
+ /**
2258
+ * Render a slide and return it as an ImageBitmap. Works in both modes; in
2259
+ * worker mode the entire render runs off the main thread. Paint with:
2260
+ * `canvas.getContext('bitmaprenderer').transferFromImageBitmap(bitmap)`.
2261
+ *
2262
+ * The returned ImageBitmap is owned by the caller: pass it to
2263
+ * `transferFromImageBitmap` (which consumes it) or call `bitmap.close()`
2264
+ * when done, or its backing memory is held until GC.
2265
+ */
2266
+ renderSlideToBitmap(slideIndex: number, opts?: RenderSlideToBitmapOptions): Promise<ImageBitmap>;
2042
2267
  /**
2043
2268
  * Extract raw media bytes for a zip path referenced by {@link MediaElement}.
2044
2269
  * Results are cached by path for the lifetime of this instance.
@@ -2106,6 +2331,12 @@ declare class PptxViewer {
2106
2331
  private readonly opts;
2107
2332
  private currentSlide;
2108
2333
  private handle;
2334
+ private readonly _mode;
2335
+ /** The canvas's bitmaprenderer context, used only by the static worker-mode
2336
+ * render path. The media-playback path keeps a 2d context (via presentSlide),
2337
+ * so this is obtained only when worker mode renders without media playback. */
2338
+ private _bitmapCtx;
2339
+ private _warnedNoTextSelection;
2109
2340
  constructor(canvas: HTMLCanvasElement, opts?: PptxViewerOptions);
2110
2341
  /**
2111
2342
  * Load a PPTX from URL or ArrayBuffer and render the first slide.
@@ -2121,6 +2352,13 @@ declare class PptxViewer {
2121
2352
  prevSlide(): Promise<void>;
2122
2353
  get slideIndex(): number;
2123
2354
  get slideCount(): number;
2355
+ /**
2356
+ * Speaker-notes text for a slide (`ppt/notesSlides/notesSlideN.xml`,
2357
+ * ECMA-376 §13.3.5). Passthrough to {@link PptxPresentation.getNotes}:
2358
+ * 0-based index, returns `null` when the slide has no notes part, the index
2359
+ * is out of range, or nothing is loaded yet.
2360
+ */
2361
+ getNotes(slideIndex: number): string | null;
2124
2362
  /** The underlying <canvas> element. */
2125
2363
  get canvasElement(): HTMLCanvasElement;
2126
2364
  private renderCurrentSlide;
@@ -2265,6 +2503,15 @@ declare interface RenderSlideOptions {
2265
2503
  skipMediaControls?: boolean;
2266
2504
  }
2267
2505
 
2506
+ /** Options for {@link PptxPresentation.renderSlideToBitmap}. */
2507
+ declare interface RenderSlideToBitmapOptions {
2508
+ /** Slide width in CSS pixels. Defaults to 960. */
2509
+ width?: number;
2510
+ /** Device pixel ratio. Defaults to window.devicePixelRatio (workers have none). */
2511
+ dpr?: number;
2512
+ /* Excluded from this release type: skipMediaControls */
2513
+ }
2514
+
2268
2515
  declare interface RenderViewportOptions {
2269
2516
  width?: number;
2270
2517
  height?: number;
@@ -2277,8 +2524,8 @@ declare interface RenderViewportOptions {
2277
2524
  freezeCols?: number;
2278
2525
  /** Scale factor applied to all cell/header dimensions (default 1). */
2279
2526
  cellScale?: number;
2280
- /** Pre-loaded Image elements keyed by their dataUrl (for ImageAnchor rendering). */
2281
- loadedImages?: Map<string, HTMLImageElement>;
2527
+ /** Pre-decoded image sources keyed by their dataUrl (for ImageAnchor rendering). */
2528
+ loadedImages?: Map<string, CanvasImageSource>;
2282
2529
  /** Called once per cell that contains text, with canvas-pixel position and cell address. */
2283
2530
  onTextRun?: (info: XlsxTextRunInfo) => void;
2284
2531
  /** Highlighted row range for selected row headers (1-indexed inclusive).
@@ -2297,6 +2544,20 @@ declare interface RenderViewportOptions {
2297
2544
  } | null;
2298
2545
  }
2299
2546
 
2547
+ /**
2548
+ * Resolved allowed-value set for a list validation. Either concrete display
2549
+ * `values` (inline list or expanded range), or — when the operand is a defined
2550
+ * name / complex formula we cannot expand — the raw `formula` text so the panel
2551
+ * can disclose it instead of showing nothing.
2552
+ */
2553
+ declare type ResolvedList = {
2554
+ kind: 'values';
2555
+ values: string[];
2556
+ } | {
2557
+ kind: 'formula';
2558
+ formula: string;
2559
+ };
2560
+
2300
2561
  /**
2301
2562
  * 3D rotation in sphere coordinates — ECMA-376 §20.1.5.11 (`CT_SphereCoords`).
2302
2563
  * Angles are in **degrees** (the XML carries 60000ths of a degree; the parser
@@ -2698,6 +2959,20 @@ declare interface Slide {
2698
2959
  slideNumber: number;
2699
2960
  background: Fill | null;
2700
2961
  elements: SlideElement[];
2962
+ /**
2963
+ * Speaker-notes pane text from `ppt/notesSlides/notesSlideN.xml`
2964
+ * (ECMA-376 §13.3.5 — Notes Slide). The full notes-body text as a single
2965
+ * string, paragraphs joined with `\n`. Absent (`undefined`) when the slide
2966
+ * has no notes part. The renderer ignores this — it is surfaced for tools;
2967
+ * read it via {@link PptxPresentation.getNotes}.
2968
+ */
2969
+ notes?: string;
2970
+ /**
2971
+ * Legacy slide comments (`ppt/comments/commentN.xml`, ECMA-376 §13.3.4).
2972
+ * Modern Office 365 threaded comments are not parsed. Omitted from the JSON
2973
+ * when the slide has no comments.
2974
+ */
2975
+ comments?: PptxComment[];
2701
2976
  }
2702
2977
 
2703
2978
  declare type SlideElement = ShapeElement | PictureElement | TableElement | ChartElement | MediaElement;
@@ -2723,9 +2998,10 @@ declare interface SolidFill {
2723
2998
  }
2724
2999
 
2725
3000
  /**
2726
- * `<a:sp3d>` — ECMA-376 §20.1.5.12 (`CT_Shape3D`). Parsed in full but **not
2727
- * rendered in Phase A** (camera-only). bevel/contour/extrusion are Phase B.
2728
- * Numeric fields are omitted from JSON when zero.
3001
+ * `<a:sp3d>` — ECMA-376 §20.1.5.12 (`CT_Shape3D`). Rendered in Phase B: bevelT/
3002
+ * bevelB are shaded as a lit lip (distance-field + lightRig), extrusionH as a
3003
+ * swept side wall, and contour as a flat outline approximation. Numeric fields
3004
+ * are omitted from JSON when zero.
2729
3005
  */
2730
3006
  declare interface Sp3d {
2731
3007
  /** Z position of the front face in EMU (default 0). */
@@ -3092,6 +3368,29 @@ declare interface TextRunData {
3092
3368
  outline?: TextOutline;
3093
3369
  }
3094
3370
 
3371
+ /**
3372
+ * ECMA-376 §20.1.8.58 (CT_TileInfoProperties) — tiled blip-fill placement.
3373
+ * The blip repeats at its native size (scaled by sx/sy) across the fill box.
3374
+ * Mutually exclusive with {@link ImageFill.fillRect} (the `stretch` mode).
3375
+ */
3376
+ declare interface TileInfo {
3377
+ /** Horizontal offset of the first tile, in EMU (`tx`). Default 0. */
3378
+ tx: number;
3379
+ /** Vertical offset of the first tile, in EMU (`ty`). Default 0. */
3380
+ ty: number;
3381
+ /** Horizontal tile scale as a fraction (`sx` / 100000). Default 1.0. */
3382
+ sx: number;
3383
+ /** Vertical tile scale as a fraction (`sy` / 100000). Default 1.0. */
3384
+ sy: number;
3385
+ /** Mirror mode: `'none' | 'x' | 'y' | 'xy'` (`flip`). Default `'none'`. */
3386
+ flip: string;
3387
+ /**
3388
+ * Anchor corner the tile grid registers against:
3389
+ * `tl|t|tr|l|ctr|r|bl|b|br` (`algn`). Default `'tl'`.
3390
+ */
3391
+ algn: string;
3392
+ }
3393
+
3095
3394
  declare interface ViewportRange {
3096
3395
  row: number;
3097
3396
  col: number;
@@ -3099,6 +3398,13 @@ declare interface ViewportRange {
3099
3398
  cols: number;
3100
3399
  }
3101
3400
 
3401
+ /** Serializable subset of RenderPageOptions (callbacks cannot cross the wire). */
3402
+ declare type WireRenderPageOptions = Omit<RenderPageOptions, 'onTextRun'>;
3403
+
3404
+ /** Serializable subset of RenderViewportOptions: drop the callback and the
3405
+ * image cache (the worker owns its own). */
3406
+ declare type WireRenderViewportOptions = Omit<RenderViewportOptions, 'onTextRun' | 'loadedImages'>;
3407
+
3102
3408
  declare interface Workbook {
3103
3409
  sheets: SheetMeta[];
3104
3410
  }
@@ -3139,6 +3445,17 @@ declare interface Worksheet {
3139
3445
  /** A1-style cell refs of commented cells (ECMA-376 §18.7.3). Rendered as a
3140
3446
  * small red triangle in each cell's top-right corner. */
3141
3447
  commentRefs?: string[];
3448
+ /** Full-fidelity comment bodies (cell ref + author + plain text) for every
3449
+ * `<comment>` in `xl/commentsN.xml` (ECMA-376 §18.7). Parallel to
3450
+ * {@link commentRefs} (one entry per ref). Consume this to read the note
3451
+ * text; the renderer uses {@link commentRefs} for the red indicator and the
3452
+ * viewer surfaces these bodies in an Excel-style hover popup. */
3453
+ comments?: XlsxComment[];
3454
+ /** Data-validation rules on this sheet (ECMA-376 §18.3.1.32–33). Exposed for
3455
+ * tooling. The viewer draws a list-dropdown arrow on the active cell when the
3456
+ * selection intersects a `list`-type rule's `sqref` (display only — opening
3457
+ * the list / picking a value is out of scope for a viewer). */
3458
+ dataValidations?: DataValidation[];
3142
3459
  /** Defined names in scope for this sheet (ECMA-376 §18.2.5). Used by
3143
3460
  * conditional-formatting `expression` rules that call named ranges
3144
3461
  * (e.g. `task_start`, `today`). */
@@ -3168,7 +3485,9 @@ export declare namespace xlsx {
3168
3485
  export {
3169
3486
  XlsxWorkbook,
3170
3487
  LoadOptions_3 as LoadOptions,
3488
+ WireRenderViewportOptions,
3171
3489
  XlsxViewer,
3490
+ ResolvedList,
3172
3491
  XlsxViewerOptions,
3173
3492
  CellAddress,
3174
3493
  CellRange_2 as CellRange,
@@ -3205,6 +3524,8 @@ export declare namespace xlsx {
3205
3524
  CfIcon,
3206
3525
  DefinedName,
3207
3526
  Hyperlink,
3527
+ XlsxComment,
3528
+ DataValidation,
3208
3529
  TableInfo,
3209
3530
  TableColumnInfo,
3210
3531
  SlicerAnchor,
@@ -3279,6 +3600,24 @@ declare interface XlsxChartSeries {
3279
3600
  errBars?: ErrBars[];
3280
3601
  }
3281
3602
 
3603
+ /** One cell comment. Sourced from the classic notes file `xl/commentsN.xml`
3604
+ * (ECMA-376 §18.7) when present, otherwise from the Office-365 threaded
3605
+ * comments part `xl/threadedComments/` (MS-XLSX schema
3606
+ * `…/spreadsheetml/2018/threadedcomments`, `personId` resolved via
3607
+ * `xl/persons/`). `text` is the joined plain text — every `<r><t>` run for
3608
+ * classic notes, every reply in the thread (newline-joined) for threaded
3609
+ * comments; rich-text formatting is dropped. 1:1 with the Rust `XlsxComment`
3610
+ * (serde camelCase). */
3611
+ declare interface XlsxComment {
3612
+ /** A1-style cell reference (`@ref` on the comment element). */
3613
+ cellRef: string;
3614
+ /** Resolved author name — the `<authors>` entry (classic) or the `<person>`
3615
+ * `displayName` (threaded). Absent when unresolved. */
3616
+ author?: string;
3617
+ /** Concatenated plain text of every run / threaded reply. */
3618
+ text: string;
3619
+ }
3620
+
3282
3621
  /** Emitted once per cell that has text, with the cell's canvas-pixel bounds. */
3283
3622
  declare interface XlsxTextRunInfo {
3284
3623
  text: string;
@@ -3313,6 +3652,12 @@ declare class XlsxViewer {
3313
3652
  private currentSheet;
3314
3653
  private currentWorksheet;
3315
3654
  private opts;
3655
+ /** 'main' renders on this thread; 'worker' paints worker-produced bitmaps. */
3656
+ private readonly _mode;
3657
+ /** The canvas's bitmaprenderer context, used only in worker mode. A canvas
3658
+ * holds one context type for its lifetime, so this is obtained once and the
3659
+ * main-mode 2d render path is never used on the same canvas. */
3660
+ private _bitmapCtx;
3316
3661
  private resizeObserver;
3317
3662
  /**
3318
3663
  * Start-anchored horizontal scroll position (the {@link effectiveScrollLeft}
@@ -3332,6 +3677,32 @@ declare class XlsxViewer {
3332
3677
  private selectionOverlay;
3333
3678
  private keydownHandler;
3334
3679
  private pendingTap;
3680
+ /** DOM overlay element that shows the hovered cell's comment. Lives in
3681
+ * canvasArea above the scrollHost; `pointer-events:none` so it never blocks
3682
+ * cell interaction. */
3683
+ private commentPopup;
3684
+ /** `"row:col"` → comment for the current sheet, rebuilt on every showSheet. */
3685
+ private commentMap;
3686
+ /** `"row:col"` of the cell whose popup is currently shown (or pending), so a
3687
+ * pointermove within the same cell doesn't restart the show timer. */
3688
+ private commentPopupKey;
3689
+ /** Pending show timer (see {@link COMMENT_POPUP_DELAY_MS}). */
3690
+ private commentPopupTimer;
3691
+ /** DOM overlay listing a list-validated cell's allowed values. Lives in
3692
+ * canvasArea above the scrollHost; unlike the comment popup this is a click
3693
+ * target (`pointer-events:auto`). Read-only: hovering an item highlights it
3694
+ * but selecting does NOT change the cell. */
3695
+ private validationPanel;
3696
+ /** `"row:col"` of the cell whose panel is currently open, or null. Lets a
3697
+ * re-click on the same arrow toggle the panel closed. */
3698
+ private validationPanelKey;
3699
+ /** Screen rect (canvasArea CSS px) of the dropdown arrow button last drawn by
3700
+ * {@link maybeDrawValidationDropdown}, so pointerdown can hit-test it. Null
3701
+ * when no arrow is currently visible. */
3702
+ private validationArrowRect;
3703
+ /** Document-level pointerdown listener that closes the panel on an outside
3704
+ * click; installed only while the panel is open. */
3705
+ private validationOutsideHandler;
3335
3706
  constructor(container: HTMLElement, opts?: XlsxViewerOptions);
3336
3707
  /**
3337
3708
  * Load an XLSX from URL or ArrayBuffer and render the first sheet.
@@ -3406,6 +3777,14 @@ declare class XlsxViewer {
3406
3777
  private getCellRect;
3407
3778
  /** Returns the current selection, including mode. */
3408
3779
  get selection(): CellRange_2 | null;
3780
+ /**
3781
+ * Programmatically select a single cell by A1 reference (e.g. `"B2"`), as if
3782
+ * the user had clicked it: updates the active/anchor cell, redraws the
3783
+ * selection overlay (including any list-validation dropdown arrow), and fires
3784
+ * `onSelectionChange`. A no-op for malformed refs. Closes any open validation
3785
+ * panel, matching the click path.
3786
+ */
3787
+ select(ref: string): void;
3409
3788
  /**
3410
3789
  * Returns what the header area contains at the given client coordinates.
3411
3790
  * Returns null when the point is in the cell grid (not a header).
@@ -3414,6 +3793,49 @@ declare class XlsxViewer {
3414
3793
  /** Copy the selected cell range as tab-separated text to the clipboard. */
3415
3794
  private copySelection;
3416
3795
  private updateSelectionOverlay;
3796
+ /** Draw the Excel list-validation dropdown button just outside the
3797
+ * bottom-right corner of the *active* cell when that cell is covered by a
3798
+ * `list` data-validation rule. Anchored to the single active cell (not the
3799
+ * whole range) to mirror Excel, which attaches the button to the active
3800
+ * cell of the selection. */
3801
+ private maybeDrawValidationDropdown;
3802
+ /** Toggle the dropdown panel for the active cell's list validation. Called
3803
+ * from pointerdown when the arrow rect is hit. Re-clicking the same arrow
3804
+ * closes it. */
3805
+ private toggleValidationPanel;
3806
+ /** Resolve the allowed values for `formula1` (relative to the current sheet)
3807
+ * and render them in the panel anchored below the active cell. Async because
3808
+ * cross-sheet range references may need a lazily-parsed worksheet. */
3809
+ private openValidationPanel;
3810
+ /** Build the panel's children. Uses textContent throughout (no HTML injection
3811
+ * from cell values). Items highlight on hover but are NOT selectable —
3812
+ * this is a read-only viewer, so clicking a value must not change the cell. */
3813
+ private renderValidationPanel;
3814
+ /** Position the (already-populated, visible-or-becoming-visible) panel below
3815
+ * the dropdown arrow / active cell using the pure geometry calculator. */
3816
+ private positionValidationPanel;
3817
+ /** Install a document-level pointerdown listener that closes the panel on a
3818
+ * click outside it (and outside the arrow, which toggles via its own path).
3819
+ * Removed by {@link hideValidationPanel}. */
3820
+ private installValidationOutsideHandler;
3821
+ /** Hide the panel and detach its outside-click listener. Called on re-click,
3822
+ * outside click, Esc, scroll, selection change, sheet switch and destroy. */
3823
+ private hideValidationPanel;
3824
+ /** Build the `"row:col"` → comment index for the given sheet. Parses each
3825
+ * `XlsxComment.cellRef` with the shared {@link parseA1}; later refs win on a
3826
+ * collision (Excel allows at most one note per cell, so this is moot in
3827
+ * practice). */
3828
+ private buildCommentMap;
3829
+ /** Show the popup for the comment on `cell` after the hover dwell, anchored to
3830
+ * the cell's current on-screen rect. No-op when the cell carries no comment.
3831
+ * Re-hovering the same cell does not restart the timer. */
3832
+ private scheduleCommentPopup;
3833
+ /** Immediately render the popup for `comment` anchored to `cell` (used by the
3834
+ * hover-dwell timer and by touch selection, which has no hover). */
3835
+ private renderCommentPopup;
3836
+ /** Hide the popup and cancel any pending show. Called on cell-out, scroll,
3837
+ * sheet switch and destroy. */
3838
+ private hideCommentPopup;
3417
3839
  private applyPointerSelection;
3418
3840
  private setupSelectionEvents;
3419
3841
  private buildTabs;
@@ -3490,6 +3912,15 @@ declare interface XlsxViewerOptions {
3490
3912
  * dependency-injection contract as the docx/pptx viewers.
3491
3913
  */
3492
3914
  math?: MathRenderer;
3915
+ /**
3916
+ * `'main'` (default): parse in a worker, render on the main thread. `'worker'`:
3917
+ * parse AND render entirely inside the worker and paint the returned
3918
+ * ImageBitmap onto the viewer's canvas, so document rendering never blocks the
3919
+ * UI thread. All interaction (scroll, sheet tabs, frozen panes, zoom, cell
3920
+ * selection) is unchanged. Requires `Worker` + `OffscreenCanvas`. Equations
3921
+ * require `'main'` (the math engine cannot cross the worker boundary).
3922
+ */
3923
+ mode?: 'main' | 'worker';
3493
3924
  }
3494
3925
 
3495
3926
  declare class XlsxWorkbook {
@@ -3497,7 +3928,7 @@ declare class XlsxWorkbook {
3497
3928
  private bridge;
3498
3929
  private parsedWorkbook;
3499
3930
  private sheetCache;
3500
- /** Cache of loaded images keyed by their data URL. Shared across sheets. */
3931
+ /** Cache of decoded image bitmaps keyed by their data URL. Shared across sheets. */
3501
3932
  private imageCache;
3502
3933
  private rawData;
3503
3934
  private maxZipEntryBytes;
@@ -3505,6 +3936,7 @@ declare class XlsxWorkbook {
3505
3936
  * `renderViewport` call reuses it — equations in shapes render when present,
3506
3937
  * and are skipped (engine tree-shaken) when omitted. */
3507
3938
  private math;
3939
+ private _mode;
3508
3940
  private constructor();
3509
3941
  /** Parse an XLSX from a URL or ArrayBuffer. */
3510
3942
  static load(source: string | ArrayBuffer, opts?: LoadOptions_3): Promise<XlsxWorkbook>;
@@ -3515,7 +3947,38 @@ declare class XlsxWorkbook {
3515
3947
  * `null` for sheets that declare no tab color. */
3516
3948
  get tabColors(): (string | null)[];
3517
3949
  getWorksheet(sheetIndex: number): Promise<Worksheet>;
3950
+ /**
3951
+ * Resolve a `list`-type data-validation `formula1` (ECMA-376 §18.3.1.32) into
3952
+ * the set of allowed values to display, evaluated relative to `sheetIndex`
3953
+ * (the sheet that owns the validation, used to resolve unqualified ranges):
3954
+ *
3955
+ * - Inline quoted list `"A,B,C"` → the literal values.
3956
+ * - Range ref `$B$2:$B$5` → each non-empty cell's *display
3957
+ * string* (the same formatted text the grid shows, via {@link formatCellValue}),
3958
+ * walked row-major. `Sheet2!$A$1:$A$9` resolves against the named sheet
3959
+ * (lazily parsed via {@link getWorksheet}, hence async).
3960
+ * - Named range / complex formula → `{ kind: 'formula' }` carrying the
3961
+ * raw text so the caller can disclose it rather than blanking it.
3962
+ *
3963
+ * Read-only: this only reads cell values for display; it never writes.
3964
+ */
3965
+ resolveValidationList(sheetIndex: number, formula1: string | undefined): Promise<ResolvedList>;
3518
3966
  renderViewport(target: HTMLCanvasElement | OffscreenCanvas, sheetIndex: number, viewport: ViewportRange, opts?: RenderViewportOptions): Promise<void>;
3967
+ /**
3968
+ * Render a sheet viewport and return it as an ImageBitmap (both modes; in
3969
+ * worker mode the render runs entirely off the main thread). `opts.width` /
3970
+ * `opts.height` are required: there is no DOM element to measure in a worker
3971
+ * or on an OffscreenCanvas. Paint with
3972
+ * `canvas.getContext('bitmaprenderer').transferFromImageBitmap(bitmap)`.
3973
+ *
3974
+ * The returned ImageBitmap is owned by the caller: pass it to
3975
+ * `transferFromImageBitmap` (which consumes it) or call `bitmap.close()`
3976
+ * when done, or its backing memory is held until GC.
3977
+ */
3978
+ renderViewportToBitmap(sheetIndex: number, viewport: ViewportRange, opts: WireRenderViewportOptions & {
3979
+ width: number;
3980
+ height: number;
3981
+ }): Promise<ImageBitmap>;
3519
3982
  destroy(): void;
3520
3983
  }
3521
3984