@silurus/ooxml 0.2.0 → 0.4.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.
@@ -7,6 +7,31 @@ declare interface ArrowEnd {
7
7
  len: string;
8
8
  }
9
9
 
10
+ /**
11
+ * Observe an element's size and invoke a render callback, coalescing bursts to
12
+ * one call per animation frame and serializing overlapping async renders.
13
+ *
14
+ * Framework-agnostic: call from any mount/setup hook and invoke the returned
15
+ * disposer in the corresponding teardown hook.
16
+ *
17
+ * @example
18
+ * const detach = autoResize(
19
+ * (width) => pres.renderSlide(canvas, 0, { width }),
20
+ * canvas,
21
+ * );
22
+ * // later
23
+ * detach();
24
+ */
25
+ declare function autoResize(render: (width: number, height: number) => void | Promise<void>, element: Element, opts?: AutoResizeOptions): () => void;
26
+
27
+ declare interface AutoResizeOptions {
28
+ /**
29
+ * Skip rendering while `document.hidden` is true and fire once with the latest
30
+ * observed size when the tab becomes visible again. Default: true.
31
+ */
32
+ pauseWhenHidden?: boolean;
33
+ }
34
+
10
35
  declare type BodyElement = {
11
36
  type: 'paragraph';
12
37
  } & DocParagraph | {
@@ -218,6 +243,24 @@ declare interface ChartElement {
218
243
  catAxisHidden: boolean;
219
244
  valAxisHidden: boolean;
220
245
  plotAreaBg: string | null;
246
+ /** Outer chartSpace background (hex without '#'). null when noFill/absent. */
247
+ chartBg: string | null;
248
+ /** True when <c:legend> is declared; false suppresses the legend entirely. */
249
+ showLegend: boolean;
250
+ /** catAx crossBetween: "between" (default, 0.5-step padding) or "midCat". */
251
+ catAxisCrossBetween: 'between' | 'midCat' | string;
252
+ /** `<c:valAx><c:majorTickMark>`. "cross" (default) | "out" | "in" | "none". */
253
+ valAxisMajorTickMark: 'cross' | 'out' | 'in' | 'none' | string;
254
+ /** `<c:catAx><c:majorTickMark>`. */
255
+ catAxisMajorTickMark: 'cross' | 'out' | 'in' | 'none' | string;
256
+ /** Title font size in OOXML hundredths of a point (1600 = 16pt). null = default. */
257
+ titleFontSizeHpt: number | null;
258
+ /** `<c:catAx><c:txPr>` font size (hpt). null = proportional default. */
259
+ catAxisFontSizeHpt: number | null;
260
+ /** `<c:valAx><c:txPr>` font size (hpt). null = proportional default. */
261
+ valAxisFontSizeHpt: number | null;
262
+ /** `<c:dLbls><c:txPr>` font size (hpt) for data-point value labels. */
263
+ dataLabelFontSizeHpt: number | null;
221
264
  }
222
265
 
223
266
  declare interface ChartSeries {
@@ -249,7 +292,12 @@ declare interface ConditionalFormat {
249
292
  }
250
293
 
251
294
  declare interface DocParagraph {
252
- alignment: 'left' | 'center' | 'right' | 'justify';
295
+ /**
296
+ * ECMA-376 §17.18.44 ST_Jc. Renderer honors left, start, center, right, end,
297
+ * both, distribute. Other values (kashida variants, numTab, thaiDistribute)
298
+ * are treated as start-aligned.
299
+ */
300
+ alignment: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | 'both' | 'distribute' | string;
253
301
  indentLeft: number;
254
302
  indentRight: number;
255
303
  indentFirst: number;
@@ -265,6 +313,12 @@ declare interface DocParagraph {
265
313
  pageBreakBefore?: boolean;
266
314
  /** Suppress spacing between adjacent same-style paragraphs (w:contextualSpacing) */
267
315
  contextualSpacing?: boolean;
316
+ /** Keep paragraph on same page as the next paragraph (w:keepNext) */
317
+ keepNext?: boolean;
318
+ /** Keep all lines of this paragraph on the same page (w:keepLines) */
319
+ keepLines?: boolean;
320
+ /** Widow/orphan control (w:widowControl). ECMA-376 default is true. */
321
+ widowControl?: boolean;
268
322
  /** Paragraph borders (w:pBdr) */
269
323
  borders?: ParagraphBorders | null;
270
324
  /** Style ID of the applied paragraph style */
@@ -282,7 +336,9 @@ declare type DocRun = {
282
336
  breakType: 'line' | 'page' | 'column';
283
337
  } | {
284
338
  type: 'field';
285
- } & FieldRun;
339
+ } & FieldRun | {
340
+ type: 'shape';
341
+ } & ShapeRun;
286
342
 
287
343
  declare interface DocTable {
288
344
  colWidths: number[];
@@ -321,6 +377,8 @@ export declare namespace docx {
321
377
  export {
322
378
  DocxDocument,
323
379
  DocxViewer,
380
+ autoResize,
381
+ AutoResizeOptions,
324
382
  Document_2 as Document,
325
383
  SectionProps,
326
384
  DocParagraph,
@@ -422,6 +480,13 @@ declare interface GradientStop {
422
480
  color: string;
423
481
  }
424
482
 
483
+ declare interface GradientStop_2 {
484
+ /** 0.0–1.0 */
485
+ position: number;
486
+ /** hex 6-char */
487
+ color: string;
488
+ }
489
+
425
490
  declare interface HeaderFooter {
426
491
  body: BodyElement[];
427
492
  }
@@ -522,6 +587,24 @@ declare interface LoadOptions {
522
587
  useGoogleFonts?: boolean;
523
588
  }
524
589
 
590
+ declare interface MediaElement {
591
+ type: 'media';
592
+ x: number;
593
+ y: number;
594
+ width: number;
595
+ height: number;
596
+ /** "audio" or "video" */
597
+ mediaKind: 'audio' | 'video';
598
+ /** Poster image zip path (e.g. "ppt/media/image2.png"). Empty when no poster. */
599
+ posterPath: string;
600
+ /** Poster image MIME type (empty when no poster). */
601
+ posterMimeType: string;
602
+ /** Path inside the pptx zip (e.g. "ppt/media/media2.mp4"). Used by getMedia. */
603
+ mediaPath: string;
604
+ /** MIME type of the underlying media (e.g. "audio/mpeg", "video/mp4"). */
605
+ mimeType: string;
606
+ }
607
+
525
608
  declare interface MergeCell {
526
609
  top: number;
527
610
  left: number;
@@ -621,6 +704,32 @@ declare type PathCmd = {
621
704
  cmd: 'close';
622
705
  };
623
706
 
707
+ declare type PathCmd_2 = {
708
+ cmd: 'moveTo';
709
+ x: number;
710
+ y: number;
711
+ } | {
712
+ cmd: 'lineTo';
713
+ x: number;
714
+ y: number;
715
+ } | {
716
+ cmd: 'cubicBezTo';
717
+ x1: number;
718
+ y1: number;
719
+ x2: number;
720
+ y2: number;
721
+ x: number;
722
+ y: number;
723
+ } | {
724
+ cmd: 'arcTo';
725
+ wr: number;
726
+ hr: number;
727
+ stAng: number;
728
+ swAng: number;
729
+ } | {
730
+ cmd: 'close';
731
+ };
732
+
624
733
  declare interface PictureElement {
625
734
  type: 'picture';
626
735
  x: number;
@@ -644,6 +753,8 @@ declare interface PictureElement {
644
753
  r?: number;
645
754
  b?: number;
646
755
  };
756
+ /** a:blip > a:alphaModFix@amt as 0..1. Undefined = fully opaque. */
757
+ alpha?: number;
647
758
  }
648
759
 
649
760
  export declare namespace pptx {
@@ -655,6 +766,8 @@ export declare namespace pptx {
655
766
  RenderSlideOptions,
656
767
  renderSlide,
657
768
  RenderOptions,
769
+ autoResize,
770
+ AutoResizeOptions,
658
771
  Presentation,
659
772
  Slide,
660
773
  SlideElement,
@@ -691,6 +804,8 @@ declare class PptxPresentation {
691
804
  private readonly _worker;
692
805
  private _presentation;
693
806
  private _pendingParseCallbacks;
807
+ private _pendingMediaCallbacks;
808
+ private _mediaCache;
694
809
  private _nextId;
695
810
  private _workerReady;
696
811
  private _workerReadyCallbacks;
@@ -707,6 +822,19 @@ declare class PptxPresentation {
707
822
  get slideHeight(): number;
708
823
  /** Render a slide onto the given canvas. */
709
824
  renderSlide(canvas: HTMLCanvasElement, slideIndex: number, opts?: RenderSlideOptions): Promise<void>;
825
+ /**
826
+ * Extract raw media bytes for a zip path referenced by {@link MediaElement}.
827
+ * Results are cached by path for the lifetime of this instance.
828
+ */
829
+ getMedia(mediaPath: string): Promise<Blob>;
830
+ private _findMimeTypeForPath;
831
+ /**
832
+ * Render a slide and attach canvas-native playback controls for any
833
+ * embedded audio/video. Returns a disposable handle that owns the RAF loop,
834
+ * media elements, and object URLs. Unlike {@link renderSlide}, this method
835
+ * is stateful — always call `handle.dispose()` when leaving the slide.
836
+ */
837
+ presentSlide(canvas: HTMLCanvasElement, slideIndex: number, opts?: RenderSlideOptions): Promise<PresentationHandle>;
710
838
  /** Terminate the worker and release all resources. */
711
839
  destroy(): void;
712
840
  }
@@ -764,12 +892,31 @@ declare interface Presentation {
764
892
  minorFont: string | null;
765
893
  }
766
894
 
895
+ declare interface PresentationHandle {
896
+ play(mediaPath?: string): void;
897
+ pause(mediaPath?: string): void;
898
+ dispose(): void;
899
+ }
900
+
767
901
  declare interface RenderOptions {
768
902
  width?: number;
769
903
  defaultTextColor?: string | null;
770
904
  dpr?: number;
771
905
  majorFont?: string | null;
772
906
  minorFont?: string | null;
907
+ /**
908
+ * Lazily resolve an archive-internal asset (by zip path) to a Blob. The
909
+ * renderer uses this to fetch posters and other large embedded assets on
910
+ * demand, keeping the parse output free of inlined base64.
911
+ */
912
+ fetchMedia?: (path: string) => Promise<Blob>;
913
+ /**
914
+ * When true, renderMedia draws only the poster frame — play/pause badges
915
+ * and progress bars are left to the caller. Set by the pptx presentSlide
916
+ * API so its interactive handle can own all control chrome without
917
+ * the static renderer drawing a duplicate play badge.
918
+ */
919
+ skipMediaControls?: boolean;
773
920
  }
774
921
 
775
922
  declare interface RenderPageOptions {
@@ -791,6 +938,12 @@ declare interface RenderSlideOptions {
791
938
  width?: number;
792
939
  /** Device pixel ratio. Defaults to window.devicePixelRatio or 1. */
793
940
  dpr?: number;
941
+ /**
942
+ * Skip drawing the play badge overlay on media elements. Used internally by
943
+ * {@link PptxPresentation.presentSlide} so its interactive handle can draw
944
+ * its own play/pause chrome without duplication.
945
+ */
946
+ skipMediaControls?: boolean;
794
947
  }
795
948
 
796
949
  declare interface RenderViewportOptions {
@@ -886,6 +1039,38 @@ declare interface ShapeElement {
886
1039
  shadow: Shadow | null;
887
1040
  }
888
1041
 
1042
+ declare type ShapeFill = {
1043
+ fillType: 'solid';
1044
+ color: string;
1045
+ } | {
1046
+ fillType: 'gradient';
1047
+ stops: GradientStop_2[];
1048
+ angle: number;
1049
+ gradType: string;
1050
+ };
1051
+
1052
+ declare interface ShapeRun {
1053
+ widthPt: number;
1054
+ heightPt: number;
1055
+ /** X offset in pt */
1056
+ anchorXPt: number;
1057
+ /** Y offset in pt */
1058
+ anchorYPt: number;
1059
+ anchorXFromMargin: boolean;
1060
+ anchorYFromPara: boolean;
1061
+ /** Draw behind text when true (wp:anchor behindDoc="1"). */
1062
+ behindDoc?: boolean;
1063
+ /** Document-order index within a group; lower values render first. */
1064
+ zOrder: number;
1065
+ /** Normalized [0,1] custom-geometry sub-paths */
1066
+ subpaths: PathCmd_2[][];
1067
+ fill: ShapeFill | null;
1068
+ stroke: string | null;
1069
+ strokeWidth?: number;
1070
+ rotation?: number;
1071
+ wrapMode?: string | null;
1072
+ }
1073
+
889
1074
  declare interface SharedString {
890
1075
  text: string;
891
1076
  runs?: Run[];
@@ -905,7 +1090,7 @@ declare interface Slide {
905
1090
  elements: SlideElement[];
906
1091
  }
907
1092
 
908
- declare type SlideElement = ShapeElement | PictureElement | TableElement | ChartElement;
1093
+ declare type SlideElement = ShapeElement | PictureElement | TableElement | ChartElement | MediaElement;
909
1094
 
910
1095
  declare interface SolidFill {
911
1096
  fillType: 'solid';
@@ -1106,6 +1291,8 @@ export declare namespace xlsx {
1106
1291
  XlsxWorkbook,
1107
1292
  XlsxViewer,
1108
1293
  XlsxViewerOptions,
1294
+ autoResize,
1295
+ AutoResizeOptions,
1109
1296
  Workbook,
1110
1297
  SheetMeta,
1111
1298
  Worksheet,
@@ -7,6 +7,31 @@ declare interface ArrowEnd {
7
7
  len: string;
8
8
  }
9
9
 
10
+ /**
11
+ * Observe an element's size and invoke a render callback, coalescing bursts to
12
+ * one call per animation frame and serializing overlapping async renders.
13
+ *
14
+ * Framework-agnostic: call from any mount/setup hook and invoke the returned
15
+ * disposer in the corresponding teardown hook.
16
+ *
17
+ * @example
18
+ * const detach = autoResize(
19
+ * (width) => pres.renderSlide(canvas, 0, { width }),
20
+ * canvas,
21
+ * );
22
+ * // later
23
+ * detach();
24
+ */
25
+ export declare function autoResize(render: (width: number, height: number) => void | Promise<void>, element: Element, opts?: AutoResizeOptions): () => void;
26
+
27
+ export declare interface AutoResizeOptions {
28
+ /**
29
+ * Skip rendering while `document.hidden` is true and fire once with the latest
30
+ * observed size when the tab becomes visible again. Default: true.
31
+ */
32
+ pauseWhenHidden?: boolean;
33
+ }
34
+
10
35
  declare type Bullet = {
11
36
  type: 'none';
12
37
  } | {
@@ -45,6 +70,24 @@ declare interface ChartElement {
45
70
  catAxisHidden: boolean;
46
71
  valAxisHidden: boolean;
47
72
  plotAreaBg: string | null;
73
+ /** Outer chartSpace background (hex without '#'). null when noFill/absent. */
74
+ chartBg: string | null;
75
+ /** True when <c:legend> is declared; false suppresses the legend entirely. */
76
+ showLegend: boolean;
77
+ /** catAx crossBetween: "between" (default, 0.5-step padding) or "midCat". */
78
+ catAxisCrossBetween: 'between' | 'midCat' | string;
79
+ /** `<c:valAx><c:majorTickMark>`. "cross" (default) | "out" | "in" | "none". */
80
+ valAxisMajorTickMark: 'cross' | 'out' | 'in' | 'none' | string;
81
+ /** `<c:catAx><c:majorTickMark>`. */
82
+ catAxisMajorTickMark: 'cross' | 'out' | 'in' | 'none' | string;
83
+ /** Title font size in OOXML hundredths of a point (1600 = 16pt). null = default. */
84
+ titleFontSizeHpt: number | null;
85
+ /** `<c:catAx><c:txPr>` font size (hpt). null = proportional default. */
86
+ catAxisFontSizeHpt: number | null;
87
+ /** `<c:valAx><c:txPr>` font size (hpt). null = proportional default. */
88
+ valAxisFontSizeHpt: number | null;
89
+ /** `<c:dLbls><c:txPr>` font size (hpt) for data-point value labels. */
90
+ dataLabelFontSizeHpt: number | null;
48
91
  }
49
92
 
50
93
  declare interface ChartSeries {
@@ -104,6 +147,24 @@ export declare interface LoadOptions {
104
147
  useGoogleFonts?: boolean;
105
148
  }
106
149
 
150
+ declare interface MediaElement {
151
+ type: 'media';
152
+ x: number;
153
+ y: number;
154
+ width: number;
155
+ height: number;
156
+ /** "audio" or "video" */
157
+ mediaKind: 'audio' | 'video';
158
+ /** Poster image zip path (e.g. "ppt/media/image2.png"). Empty when no poster. */
159
+ posterPath: string;
160
+ /** Poster image MIME type (empty when no poster). */
161
+ posterMimeType: string;
162
+ /** Path inside the pptx zip (e.g. "ppt/media/media2.mp4"). Used by getMedia. */
163
+ mediaPath: string;
164
+ /** MIME type of the underlying media (e.g. "audio/mpeg", "video/mp4"). */
165
+ mimeType: string;
166
+ }
167
+
107
168
  export declare interface NoFill {
108
169
  fillType: 'none';
109
170
  }
@@ -182,6 +243,8 @@ export declare interface PictureElement {
182
243
  r?: number;
183
244
  b?: number;
184
245
  };
246
+ /** a:blip > a:alphaModFix@amt as 0..1. Undefined = fully opaque. */
247
+ alpha?: number;
185
248
  }
186
249
 
187
250
  /**
@@ -203,6 +266,8 @@ export declare class PptxPresentation {
203
266
  private readonly _worker;
204
267
  private _presentation;
205
268
  private _pendingParseCallbacks;
269
+ private _pendingMediaCallbacks;
270
+ private _mediaCache;
206
271
  private _nextId;
207
272
  private _workerReady;
208
273
  private _workerReadyCallbacks;
@@ -219,6 +284,19 @@ export declare class PptxPresentation {
219
284
  get slideHeight(): number;
220
285
  /** Render a slide onto the given canvas. */
221
286
  renderSlide(canvas: HTMLCanvasElement, slideIndex: number, opts?: RenderSlideOptions): Promise<void>;
287
+ /**
288
+ * Extract raw media bytes for a zip path referenced by {@link MediaElement}.
289
+ * Results are cached by path for the lifetime of this instance.
290
+ */
291
+ getMedia(mediaPath: string): Promise<Blob>;
292
+ private _findMimeTypeForPath;
293
+ /**
294
+ * Render a slide and attach canvas-native playback controls for any
295
+ * embedded audio/video. Returns a disposable handle that owns the RAF loop,
296
+ * media elements, and object URLs. Unlike {@link renderSlide}, this method
297
+ * is stateful — always call `handle.dispose()` when leaving the slide.
298
+ */
299
+ presentSlide(canvas: HTMLCanvasElement, slideIndex: number, opts?: RenderSlideOptions): Promise<PresentationHandle>;
222
300
  /** Terminate the worker and release all resources. */
223
301
  destroy(): void;
224
302
  }
@@ -276,12 +354,31 @@ export declare interface Presentation {
276
354
  minorFont: string | null;
277
355
  }
278
356
 
357
+ declare interface PresentationHandle {
358
+ play(mediaPath?: string): void;
359
+ pause(mediaPath?: string): void;
360
+ dispose(): void;
361
+ }
362
+
279
363
  export declare interface RenderOptions {
280
364
  width?: number;
281
365
  defaultTextColor?: string | null;
282
366
  dpr?: number;
283
367
  majorFont?: string | null;
284
368
  minorFont?: string | null;
369
+ /**
370
+ * Lazily resolve an archive-internal asset (by zip path) to a Blob. The
371
+ * renderer uses this to fetch posters and other large embedded assets on
372
+ * demand, keeping the parse output free of inlined base64.
373
+ */
374
+ fetchMedia?: (path: string) => Promise<Blob>;
375
+ /**
376
+ * When true, renderMedia draws only the poster frame — play/pause badges
377
+ * and progress bars are left to the caller. Set by the pptx presentSlide
378
+ * API so its interactive handle can own all control chrome without
379
+ * the static renderer drawing a duplicate play badge.
380
+ */
381
+ skipMediaControls?: boolean;
285
382
  }
286
383
 
287
384
  /**
@@ -296,6 +393,12 @@ export declare interface RenderSlideOptions {
296
393
  width?: number;
297
394
  /** Device pixel ratio. Defaults to window.devicePixelRatio or 1. */
298
395
  dpr?: number;
396
+ /**
397
+ * Skip drawing the play badge overlay on media elements. Used internally by
398
+ * {@link PptxPresentation.presentSlide} so its interactive handle can draw
399
+ * its own play/pause chrome without duplication.
400
+ */
401
+ skipMediaControls?: boolean;
299
402
  }
300
403
 
301
404
  declare interface Shadow {
@@ -349,7 +452,7 @@ export declare interface Slide {
349
452
  elements: SlideElement[];
350
453
  }
351
454
 
352
- export declare type SlideElement = ShapeElement | PictureElement | TableElement | ChartElement;
455
+ export declare type SlideElement = ShapeElement | PictureElement | TableElement | ChartElement | MediaElement;
353
456
 
354
457
  export declare interface SolidFill {
355
458
  fillType: 'solid';
@@ -1,3 +1,28 @@
1
+ /**
2
+ * Observe an element's size and invoke a render callback, coalescing bursts to
3
+ * one call per animation frame and serializing overlapping async renders.
4
+ *
5
+ * Framework-agnostic: call from any mount/setup hook and invoke the returned
6
+ * disposer in the corresponding teardown hook.
7
+ *
8
+ * @example
9
+ * const detach = autoResize(
10
+ * (width) => pres.renderSlide(canvas, 0, { width }),
11
+ * canvas,
12
+ * );
13
+ * // later
14
+ * detach();
15
+ */
16
+ export declare function autoResize(render: (width: number, height: number) => void | Promise<void>, element: Element, opts?: AutoResizeOptions): () => void;
17
+
18
+ export declare interface AutoResizeOptions {
19
+ /**
20
+ * Skip rendering while `document.hidden` is true and fire once with the latest
21
+ * observed size when the tab becomes visible again. Default: true.
22
+ */
23
+ pauseWhenHidden?: boolean;
24
+ }
25
+
1
26
  export declare interface Border {
2
27
  left: BorderEdge | null;
3
28
  right: BorderEdge | null;