@silurus/ooxml 0.64.3 → 0.66.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.
@@ -45,6 +45,29 @@ declare interface Bevel3d {
45
45
  prst: string;
46
46
  }
47
47
 
48
+ /**
49
+ * Picture bullet — ECMA-376 §21.1.2.4.2 `<a:buBlip><a:blip r:embed>`. The
50
+ * embed is resolved to the blip's embedded zip path + mime at parse time
51
+ * (mirrors {@link ImageFill}); the renderer fetches the bytes lazily by path
52
+ * via the same `getCachedBitmap(imagePath, mimeType, fetchImage)` path used for
53
+ * `pic`/blipFill. PPTX-only: the shared core `Bullet` union (used by docx/xlsx,
54
+ * which have no picture bullets) does not carry this variant, so it lives on
55
+ * the PPTX side, exactly like {@link Paragraph} extends the core paragraph.
56
+ */
57
+ declare interface BlipBullet {
58
+ type: 'blip';
59
+ /** Embedded zip path of the bullet image (e.g. "ppt/media/image1.png"). */
60
+ imagePath: string;
61
+ /** MIME type of the blip at {@link BlipBullet.imagePath} (e.g. `image/png`). */
62
+ mimeType: string;
63
+ /**
64
+ * `<a:buSzPct val>` (ECMA-376 §21.1.2.4.3) as a percentage of the text size
65
+ * (100 = same size). `null` when no explicit `<a:buSzPct>` is present, in
66
+ * which case the renderer uses the spec default of 100%.
67
+ */
68
+ sizePct: number | null;
69
+ }
70
+
48
71
  declare type BodyElement = {
49
72
  type: 'paragraph';
50
73
  } & DocParagraph | {
@@ -52,6 +75,27 @@ declare type BodyElement = {
52
75
  } & DocTable | {
53
76
  type: 'pageBreak';
54
77
  parity?: 'odd' | 'even';
78
+ }
79
+ /** ECMA-376 §17.3.1.20 `<w:br w:type="column"/>` — force the following content
80
+ * into the next newspaper column (or the next page's first column when
81
+ * already in the last column). Hoisted to the body level by the parser. */
82
+ | {
83
+ type: 'columnBreak';
84
+ }
85
+ /** ECMA-376 §17.6.x — a section boundary in the body. A `<w:sectPr>` carried in
86
+ * a paragraph's `pPr` (or a loose mid-body one) defines the section that ENDS
87
+ * here; the FINAL section's settings live on {@link DocxDocumentModel.section}.
88
+ * `columns` is the ENDING section's `<w:cols>` (§17.6.4; absent ⇒ single
89
+ * full-width column — the spec default for `@w:num` 1). `kind` is the
90
+ * ST_SectionMark (§17.18.79) controlling how the NEXT section starts:
91
+ * "continuous" (same page), "nextPage" (default; page break), "oddPage" /
92
+ * "evenPage" (page break + parity padding). The paginator switches its active
93
+ * newspaper-column geometry per section at each marker — fixing the regression
94
+ * where every section inherited the body-level section's columns. */
95
+ | {
96
+ type: 'sectionBreak';
97
+ kind: 'continuous' | 'nextPage' | 'oddPage' | 'evenPage' | string;
98
+ columns?: ColumnsSpec | null;
55
99
  };
56
100
 
57
101
  declare interface Border {
@@ -96,6 +140,14 @@ declare type Bullet = {
96
140
  startAt: number | null;
97
141
  };
98
142
 
143
+ /**
144
+ * PPTX bullet marker. The shared core {@link CoreBullet} union
145
+ * (none/inherit/char/autoNum) plus the PPTX-only picture bullet
146
+ * ({@link BlipBullet}, §21.1.2.4.2). The parser emits the `blip` variant with
147
+ * `type: "blip"`, so this is a discriminated union just like the core one.
148
+ */
149
+ declare type Bullet_2 = Bullet | BlipBullet;
150
+
99
151
  /**
100
152
  * `<a:camera>` — ECMA-376 §20.1.5.5 (`CT_Camera`). `prst` selects one of the
101
153
  * 62 preset cameras (§20.1.10.47); `fov`/`zoom`/`rot` optionally override it.
@@ -134,6 +186,14 @@ declare interface CellBorders {
134
186
  bottom: BorderSpec | null;
135
187
  left: BorderSpec | null;
136
188
  right: BorderSpec | null;
189
+ /** ECMA-376 §17.4.34 (tcBorders w:insideH/w:insideV): the interior
190
+ * horizontal/vertical border this cell contributes. Folded from the cell's
191
+ * inline tcBorders OVER the resolved conditional table-style borders (§17.7.6)
192
+ * at parse time. `null` = unset (the renderer falls back to the table-level
193
+ * insideH/insideV); a spec with style "nil"/"none" = an explicit "no interior
194
+ * border" (e.g. banded data rows in Medium List 2 / Medium Shading 2). */
195
+ insideH: BorderSpec | null;
196
+ insideV: BorderSpec | null;
137
197
  }
138
198
 
139
199
  /** ECMA-376 §17.4.7: a table cell may contain paragraphs AND nested tables. */
@@ -561,6 +621,9 @@ declare interface ChartElement {
561
621
  /** `<c:chartSpace><c:spPr><a:ln@w>` border width in EMU. null = 1px hairline
562
622
  * when a color is present. */
563
623
  chartBorderWidthEmu?: number | null;
624
+ /** Secondary value axis for combo charts (bar + line with a right-hand
625
+ * axis). null/absent for the common single value-axis case. */
626
+ secondaryValAxis?: SecondaryValueAxis | null;
564
627
  }
565
628
 
566
629
  declare interface ChartErrBars {
@@ -775,6 +838,13 @@ declare interface ChartModel {
775
838
  * ("standard" — line, no fill). Only consulted for `chartType === "radar"`.
776
839
  */
777
840
  radarStyle?: string | null;
841
+ /**
842
+ * Secondary value axis for combo charts (bar + line). When present, series
843
+ * with `useSecondaryAxis` are plotted against this axis's independent scale
844
+ * and the axis is drawn on the right edge of the plot. null/absent = single
845
+ * value axis (the common case). See {@link SecondaryValueAxis}.
846
+ */
847
+ secondaryValAxis?: SecondaryValueAxis | null;
778
848
  }
779
849
 
780
850
  declare interface ChartSeries {
@@ -804,10 +874,19 @@ declare interface ChartSeries {
804
874
  */
805
875
  labelColor?: string | null;
806
876
  /**
807
- * Mixed chart: per-series chart type override. Currently only "line" (XLSX)
808
- * is honoured; other values are treated as the chart's primary type.
877
+ * Mixed chart: per-series chart type override. Currently only "line" (XLSX
878
+ * and PPTX combo charts) is honoured; other values are treated as the
879
+ * chart's primary type.
809
880
  */
810
881
  seriesType?: string | null;
882
+ /**
883
+ * Combo chart: this series is plotted against the SECONDARY value axis
884
+ * (`ChartModel.secondaryValAxis`) — the `<c:valAx>` with `axPos="r"` /
885
+ * `<c:crosses val="max">`. When false/absent the series uses the primary
886
+ * (left) value-axis scale. PowerPoint's "Revenue vs. gross margin" combo
887
+ * (sample-14 slide-8) puts the margin line on a 0–100% secondary axis.
888
+ */
889
+ useSecondaryAxis?: boolean | null;
811
890
  /**
812
891
  * Scatter-only X values (as strings). When null the series uses
813
892
  * `ChartModel.categories` as X.
@@ -898,6 +977,29 @@ declare interface ChartSeriesDataLabels {
898
977
  */
899
978
  declare type ChartType = 'line' | 'stackedLine' | 'stackedLinePct' | 'clusteredBar' | 'clusteredBarH' | 'stackedBar' | 'stackedBarH' | 'stackedBarPct' | 'stackedBarHPct' | 'area' | 'stackedArea' | 'stackedAreaPct' | 'pie' | 'doughnut' | 'scatter' | 'bubble' | 'radar' | 'waterfall' | string;
900
979
 
980
+ /** ECMA-376 §17.6.3 `<w:col>` — one column's width and trailing space (pt). */
981
+ declare interface ColSpec {
982
+ widthPt: number;
983
+ spacePt: number;
984
+ }
985
+
986
+ /** ECMA-376 §17.6.4 `<w:cols>` — the section's multi-column configuration. */
987
+ declare interface ColumnsSpec {
988
+ /** `@w:num` — number of columns (>= 2 when emitted). */
989
+ count: number;
990
+ /** `@w:space` in pt — inter-column gap for equal-width columns (default 36pt
991
+ * = 720 twips per the spec). */
992
+ spacePt: number;
993
+ /** `@w:equalWidth` (default true) — all columns share one width + `spacePt`.
994
+ * When false, `cols` carries explicit per-column geometry. */
995
+ equalWidth: boolean;
996
+ /** `@w:sep` — draw vertical separator rules between columns. */
997
+ sep: boolean;
998
+ /** Per-column `<w:col>` entries (width + trailing space, pt). Empty when
999
+ * `equalWidth` is true. */
1000
+ cols: ColSpec[];
1001
+ }
1002
+
901
1003
  declare interface ConditionalFormat {
902
1004
  sqref: CellRange[];
903
1005
  rules: CfRule[];
@@ -1021,6 +1123,13 @@ declare interface DocParagraph {
1021
1123
  * Text" style, so footnote bodies use compact natural line height.
1022
1124
  */
1023
1125
  snapToGrid?: boolean;
1126
+ /**
1127
+ * ECMA-376 §17.3.1.11 `<w:framePr>` — text-frame / drop-cap properties.
1128
+ * Present ⇒ this paragraph is part of a text frame; the renderer positions it
1129
+ * as a frame (drop cap or generic frame) and registers a wrap exclusion so
1130
+ * following body text flows around it. Absent ⇒ ordinary in-flow paragraph.
1131
+ */
1132
+ framePr?: FramePr;
1024
1133
  }
1025
1134
 
1026
1135
  declare interface DocRevision {
@@ -1079,9 +1188,12 @@ declare interface DocTable {
1079
1188
  /** table horizontal alignment on the page: 'left' | 'center' | 'right'. */
1080
1189
  jc: string;
1081
1190
  /** ECMA-376 §17.4.52 `<w:tblLayout w:type>` — 'fixed' | 'autofit'. Absent
1082
- * (undefined) ⇒ spec default 'autofit': columns are sized by the per-column
1083
- * max preferred width (cell `widthPt`), tblGrid only as fallback. 'fixed'
1084
- * uses tblGrid widths verbatim (scaled to fit). */
1191
+ * (undefined) ⇒ spec default 'autofit'. Both paths size columns from the
1192
+ * tblGrid (§17.4.48) scaled to fit: 'fixed' uses the grid verbatim; 'autofit'
1193
+ * additionally lets content min-width grow a column. Per-cell `widthPt`/
1194
+ * `widthPct` (`<w:tcW>`) is NOT re-applied — Word bakes the resolved widths
1195
+ * into the saved grid (see resolveColumnWidths). Only a degenerate all-zero
1196
+ * grid falls back to tcW-preference sizing. */
1085
1197
  layout?: string;
1086
1198
  /** ECMA-376 §17.4.63 `<w:tblW>` preferred table width (type="dxa"), pt. */
1087
1199
  widthPt?: number;
@@ -1094,6 +1206,13 @@ declare interface DocTable {
1094
1206
  * is placed rightmost, and flips per-cell left/right borders accordingly.
1095
1207
  */
1096
1208
  bidiVisual?: boolean;
1209
+ /** ECMA-376 §17.4.57 `<w:tblpPr>` — when present the table is FLOATING
1210
+ * (absolutely positioned, out of the main text flow). Absent ⇒ block table. */
1211
+ tblpPr?: TblpPr;
1212
+ /** ECMA-376 §17.4.56 `<w:tblOverlap w:val>` — 'never' | 'overlap'. 'never' ⇒
1213
+ * the floating table must be repositioned to avoid overlapping other floats.
1214
+ * Default 'overlap' (omitted ⇒ overlap allowed). Ignored when not floating. */
1215
+ overlap?: string;
1097
1216
  }
1098
1217
 
1099
1218
  declare interface DocTableCell {
@@ -1103,12 +1222,15 @@ declare interface DocTableCell {
1103
1222
  borders: CellBorders;
1104
1223
  background: string | null;
1105
1224
  vAlign: 'top' | 'center' | 'bottom';
1106
- /** ECMA-376 §17.4.71 `<w:tcW>` preferred cell width (type="dxa"), pt. Drives
1107
- * autofit column sizing: each grid column's width is the max `widthPt` over
1108
- * the cells anchored in it. */
1225
+ /** ECMA-376 §17.4.71 `<w:tcW>` preferred cell width (type="dxa"), pt. A
1226
+ * PREFERRED width only: autofit column sizing is driven by the tblGrid
1227
+ * (§17.4.48), not by re-applying this (Word bakes the resolved widths into
1228
+ * the saved grid — see resolveColumnWidths). Consulted only for the
1229
+ * degenerate all-zero-grid fallback. */
1109
1230
  widthPt: number | null;
1110
1231
  /** `<w:tcW>` type="pct": 50ths of a percent of available content width.
1111
- * Resolved against the available width at render time. */
1232
+ * Resolved against the available width at render time. Preferred width only
1233
+ * (see `widthPt`). */
1112
1234
  widthPct?: number;
1113
1235
  /** Per-cell margins (pt) from `<w:tcPr><w:tcMar>` (ECMA-376 §17.4.42). Each
1114
1236
  * edge overrides the table-level `cellMargin*` default when set; null/absent
@@ -1141,6 +1263,8 @@ export declare namespace docx {
1141
1263
  DocxDocumentModel,
1142
1264
  DocSettings,
1143
1265
  SectionProps,
1266
+ ColumnsSpec,
1267
+ ColSpec,
1144
1268
  HeadersFooters,
1145
1269
  HeaderFooter,
1146
1270
  NumberingInfo,
@@ -1152,6 +1276,7 @@ export declare namespace docx {
1152
1276
  ImageRun,
1153
1277
  ShapeRun,
1154
1278
  ShapeText_2 as ShapeText,
1279
+ ShapeTextRun_2 as ShapeTextRun,
1155
1280
  RubyAnnotation,
1156
1281
  RenderPageOptions,
1157
1282
  RunRevision,
@@ -1160,10 +1285,13 @@ export declare namespace docx {
1160
1285
  DocNote,
1161
1286
  NoteRef,
1162
1287
  LineSpacing,
1288
+ FramePr,
1163
1289
  TabStop_2 as TabStop,
1164
1290
  ParagraphBorders,
1165
1291
  ParaBorderEdge,
1292
+ DocxRunBorder,
1166
1293
  DocTable,
1294
+ TblpPr,
1167
1295
  DocTableRow,
1168
1296
  DocTableCell,
1169
1297
  CellElement,
@@ -1285,6 +1413,19 @@ declare interface DocxDocumentModel {
1285
1413
  settings?: DocSettings;
1286
1414
  }
1287
1415
 
1416
+ /** ECMA-376 §17.3.2.4 `<w:bdr>` — a run-level border drawn as a box around the
1417
+ * run's text. Parallel to {@link ParaBorderEdge} but applies per run. */
1418
+ declare interface DocxRunBorder {
1419
+ /** "single" | "double" | "dashed" | ... (w:bdr/@w:val) */
1420
+ style: string;
1421
+ /** hex 6-char, or null for automatic (renderer falls back to text color) */
1422
+ color?: string | null;
1423
+ /** pt (sz / 8) */
1424
+ width: number;
1425
+ /** pt spacing between the border and the run text (w:space) */
1426
+ space: number;
1427
+ }
1428
+
1288
1429
  declare interface DocxTextRun {
1289
1430
  text: string;
1290
1431
  bold: boolean;
@@ -1294,8 +1435,26 @@ declare interface DocxTextRun {
1294
1435
  fontSize: number;
1295
1436
  color: string | null;
1296
1437
  fontFamily: string | null;
1438
+ /** ECMA-376 §17.3.2.26 eastAsia axis (`<w:rFonts w:eastAsia>`), resolved
1439
+ * through the style chain + docDefaults. CJK code points in this run render
1440
+ * with this family; {@link DocxTextRun.fontFamily} keeps the conflated single-
1441
+ * font fallback (ascii → eastAsia) for paths that do not split per character.
1442
+ * The renderer routes consecutive CJK code points to this axis (the same per-
1443
+ * script rule {@link ShapeTextRun.fontFamilyEastAsia} uses), so a Gothic
1444
+ * eastAsia title sits beside a serif ascii number with no name heuristics.
1445
+ * Absent ⇒ the renderer falls back to {@link DocxTextRun.fontFamily}. */
1446
+ fontFamilyEastAsia?: string | null;
1297
1447
  isLink: boolean;
1298
1448
  background: string | null;
1449
+ /** ECMA-376 §17.3.2.6 — `<w:color w:val="auto"/>` was set on this run. When
1450
+ * true and {@link DocxTextRun.color} is absent, the renderer resolves the
1451
+ * glyph color from the effective background (an implementation-defined
1452
+ * black/white contrast pick; ECMA-376 gives no normative algorithm) instead
1453
+ * of the default text color. */
1454
+ colorAuto?: boolean | null;
1455
+ /** ECMA-376 §17.3.2.4 `<w:bdr>` — a run-level border (box) drawn around the
1456
+ * run text. Absent when the run has no border. */
1457
+ border?: DocxRunBorder | null;
1299
1458
  vertAlign: 'super' | 'sub' | null;
1300
1459
  /** Target URL for hyperlinks (resolved from relationships.xml) */
1301
1460
  hyperlink: string | null;
@@ -1484,6 +1643,45 @@ declare interface FillRect {
1484
1643
  b?: number;
1485
1644
  }
1486
1645
 
1646
+ /**
1647
+ * ECMA-376 §17.3.1.11 `<w:framePr>` — text-frame / drop-cap properties.
1648
+ *
1649
+ * Lengths are pt (parser converts from twips). Per the spec, `x`/`y` are
1650
+ * ignored when `xAlign`/`yAlign` are set, and for a drop cap `y`/`yAlign` are
1651
+ * ignored entirely while `lines` drives the height. `w`/`h`/`x`/`y` are
1652
+ * `undefined` when the attribute was absent (distinct from an explicit 0).
1653
+ */
1654
+ declare interface FramePr {
1655
+ /** ST_DropCap (§17.18.20): 'none' | 'drop' | 'margin'. Default 'none'. */
1656
+ dropCap: 'none' | 'drop' | 'margin' | string;
1657
+ /** §17.3.1.11 `lines` — drop-cap vertical height in anchor lines. Default 1. */
1658
+ lines: number;
1659
+ /** ST_Wrap (§17.18.104): 'around'|'auto'|'none'|'notBeside'|'through'|'tight'. Default 'around'. */
1660
+ wrap: 'around' | 'auto' | 'none' | 'notBeside' | 'through' | 'tight' | string;
1661
+ /** ST_HAnchor (§17.18.35): 'text'(=column) | 'margin' | 'page'. Default 'page'. */
1662
+ hAnchor: 'text' | 'margin' | 'page' | string;
1663
+ /** ST_VAnchor (§17.18.100): 'text' | 'margin' | 'page'. Default 'page'. */
1664
+ vAnchor: 'text' | 'margin' | 'page' | string;
1665
+ /** ST_HeightRule (§17.18.37): 'auto' | 'atLeast' | 'exact'. Default 'auto'. */
1666
+ hRule: 'auto' | 'atLeast' | 'exact' | string;
1667
+ /** hSpace — min wrap padding L/R when wrap='around' (pt). Default 0. */
1668
+ hSpace: number;
1669
+ /** vSpace — min wrap padding top/bottom (pt). Default 0. */
1670
+ vSpace: number;
1671
+ /** w — exact frame width (pt). Absent ⇒ auto (max content line width). */
1672
+ w?: number;
1673
+ /** h — frame height (pt). Meaning gated by hRule. Absent ⇒ auto. */
1674
+ h?: number;
1675
+ /** x — absolute horizontal offset from hAnchor (pt). Ignored when xAlign set. */
1676
+ x?: number;
1677
+ /** y — absolute vertical offset from vAnchor (pt). Ignored when yAlign set / drop cap. */
1678
+ y?: number;
1679
+ /** ST_XAlign (§22.9.2.18): 'left'|'center'|'right'|'inside'|'outside'. Supersedes x. */
1680
+ xAlign?: 'left' | 'center' | 'right' | 'inside' | 'outside' | string;
1681
+ /** ST_YAlign (§22.9.2.20): 'inline'|'top'|'center'|'bottom'|'inside'|'outside'. Supersedes y. */
1682
+ yAlign?: 'inline' | 'top' | 'center' | 'bottom' | 'inside' | 'outside' | string;
1683
+ }
1684
+
1487
1685
  /** ECMA-376 §20.1.8.17 (CT_GlowEffect) — coloured halo with blur radius. */
1488
1686
  declare interface Glow {
1489
1687
  color: string;
@@ -1632,6 +1830,22 @@ declare interface ImageRun {
1632
1830
  * image. Its MIME is always `image/svg+xml` and is owned by the SVG decoder.
1633
1831
  */
1634
1832
  svgImagePath?: string;
1833
+ /**
1834
+ * ECMA-376 §20.1.8.55 `<a:srcRect>` — the source-rectangle crop applied to
1835
+ * the decoded bitmap before it is drawn into the display box. The four values
1836
+ * are inset FRACTIONS 0..1 of the source bitmap measured inward from each
1837
+ * edge (`l`/`t` from left/top, `r`/`b` from right/bottom); the visible source
1838
+ * region is `[l, t, 1−r, 1−b]`. The parser converts the raw ST_Percentage
1839
+ * (1000ths of a percent) to fractions, so the renderer crops in bitmap pixels
1840
+ * (`sx = l*w`, `sy = t*h`, `sw = (1−l−r)*w`, `sh = (1−t−b)*h`) without unit
1841
+ * knowledge. Absent / null when there is no crop (the full bitmap is drawn).
1842
+ */
1843
+ srcRect?: {
1844
+ l: number;
1845
+ t: number;
1846
+ r: number;
1847
+ b: number;
1848
+ } | null;
1635
1849
  widthPt: number;
1636
1850
  heightPt: number;
1637
1851
  /** true = wp:anchor (absolute positioned), false/undefined = wp:inline (flows with text) */
@@ -1679,6 +1893,29 @@ declare interface ImageRun {
1679
1893
  * reposition the object to prevent any overlap.
1680
1894
  */
1681
1895
  allowOverlap?: boolean;
1896
+ /** ECMA-376 §20.4.3.1 wp:align horizontal: "left" | "center" | "right" |
1897
+ * "inside" | "outside". When set the renderer aligns the image inside the
1898
+ * container indicated by `anchorXFromMargin` and ignores `anchorXPt`.
1899
+ * Mirrors {@link ShapeRun.anchorXAlign}. Absent for inline images and
1900
+ * offset-based anchors. */
1901
+ anchorXAlign?: string | null;
1902
+ /** Vertical equivalent of anchorXAlign: "top" | "center" | "bottom". */
1903
+ anchorYAlign?: string | null;
1904
+ /**
1905
+ * ECMA-376 §20.4.3.2 `<wp:positionH/@relativeFrom>` / §20.4.3.5
1906
+ * `<wp:positionV/@relativeFrom>` — names the container the offset / align /
1907
+ * pctPos is measured against. Raw spec string: `"page"`, `"margin"`,
1908
+ * `"paragraph"`, `"line"`, `"leftMargin"`, `"rightMargin"`, `"topMargin"`,
1909
+ * `"bottomMargin"`, `"insideMargin"`, `"outsideMargin"`, `"column"`,
1910
+ * `"character"`. Mirrors {@link ShapeRun.anchorXRelativeFrom} /
1911
+ * {@link ShapeRun.anchorYRelativeFrom}. When present, supersedes the legacy
1912
+ * coarse boolean hints (`anchorXFromMargin` / `anchorYFromPara`) for the
1913
+ * align and pctPos paths so e.g. `relativeFrom="margin"` + `align="top"`
1914
+ * pins the image to the top content margin rather than the page top. Absent
1915
+ * for inline images and for anchors that omitted `<wp:positionH/V>`.
1916
+ */
1917
+ anchorXRelativeFrom?: string | null;
1918
+ anchorYRelativeFrom?: string | null;
1682
1919
  }
1683
1920
 
1684
1921
  declare interface LegendManualLayout {
@@ -2021,6 +2258,33 @@ declare interface NumberingInfo {
2021
2258
  /** ECMA-376 §17.9.28 `<w:suff>` — "tab" (default) | "space" | "nothing".
2022
2259
  * Where body text starts after the marker on the first line. */
2023
2260
  suff: string;
2261
+ /** ECMA-376 §17.9.8 `<w:lvlJc>` — marker justification: "left" (default) |
2262
+ * "right" (period-aligned numerals: marker RIGHT edge at the hanging-indent
2263
+ * position) | "center". The renderer offsets the marker draw accordingly.
2264
+ * Always emitted by the parser; optional here so hand-built fixtures may omit
2265
+ * it (the renderer treats absent as "left"). */
2266
+ jc?: string;
2267
+ /** ECMA-376 §17.3.2.26 ascii axis for the marker glyph, resolved through the
2268
+ * level's `rPr` (§17.9.6) merged over the paragraph's run formatting. The
2269
+ * renderer draws Latin marker chars (e.g. a decimal "1") with this family, so
2270
+ * a heading whose ascii=Times renders its auto-number in Times (serif) even
2271
+ * when eastAsia=Gothic. Absent ⇒ the renderer falls back to its default. */
2272
+ fontFamily?: string | null;
2273
+ /** ECMA-376 §17.3.2.26 eastAsia axis for the marker glyph (same resolution as
2274
+ * {@link NumberingInfo.fontFamily}). The renderer draws CJK marker chars with
2275
+ * this family. Absent ⇒ the renderer falls back to
2276
+ * {@link NumberingInfo.fontFamily}. */
2277
+ fontFamilyEastAsia?: string | null;
2278
+ /** ECMA-376 §17.9.9/§17.9.20 — when the level uses a `<w:lvlPicBulletId>`,
2279
+ * the marker is this image (zip path, e.g. `word/media/image1.gif`), drawn in
2280
+ * place of {@link NumberingInfo.text}. Absent ⇒ ordinary text/glyph marker. */
2281
+ picBulletImagePath?: string;
2282
+ /** MIME type of {@link NumberingInfo.picBulletImagePath} (e.g. `image/gif`). */
2283
+ picBulletMimeType?: string;
2284
+ /** Picture-bullet marker width in pt (from the `<v:shape style="width">`). */
2285
+ picBulletWidthPt?: number;
2286
+ /** Picture-bullet marker height in pt (from the `<v:shape style="height">`). */
2287
+ picBulletHeightPt?: number;
2024
2288
  }
2025
2289
 
2026
2290
  declare interface NumFmt {
@@ -2073,6 +2337,13 @@ declare interface Paragraph {
2073
2337
  * `eaLnBrk` flag that the pptx parser emits but the shared core model does not
2074
2338
  * carry (docx/xlsx paragraphs don't surface it). Mirrors the Rust
2075
2339
  * `Paragraph` struct's `ea_ln_brk` field 1:1.
2340
+ *
2341
+ * Note on `bullet`: the parser also emits the picture-bullet variant
2342
+ * ({@link BlipBullet}, `type: "blip"`) at runtime, but `bullet` keeps the
2343
+ * narrower core type here because a TS interface can only *narrow* an inherited
2344
+ * property, not widen its union (the core `Paragraph.bullet` is used by
2345
+ * docx/xlsx, which have no picture bullets). Consumers that need the picture
2346
+ * variant narrow `bullet` with {@link asBullet} / a `type === 'blip'` check.
2076
2347
  */
2077
2348
  declare interface Paragraph_2 extends Paragraph {
2078
2349
  /**
@@ -2357,7 +2628,8 @@ export declare namespace pptx {
2357
2628
  SoftEdge,
2358
2629
  Reflection,
2359
2630
  PathCmd,
2360
- Bullet,
2631
+ Bullet_2 as Bullet,
2632
+ BlipBullet,
2361
2633
  SpaceLine,
2362
2634
  TabStop,
2363
2635
  TextBody,
@@ -2735,7 +3007,7 @@ declare interface RenderViewportOptions {
2735
3007
  cellScale?: number;
2736
3008
  /** Pre-decoded image sources keyed by their zip `imagePath` (for ImageAnchor
2737
3009
  * and group-leaf image rendering). */
2738
- loadedImages?: Map<string, CanvasImageSource>;
3010
+ loadedImages?: Map<string, CanvasImageSource | null>;
2739
3011
  /** Fetch an embedded image's bytes by zip path, wrapped in a Blob of the given
2740
3012
  * MIME (twin of pptx/docx `fetchImage`). The orchestrator decodes these into
2741
3013
  * {@link loadedImages} before the synchronous draw. Supplied by
@@ -2845,6 +3117,43 @@ declare interface Scene3d {
2845
3117
  lightRig?: LightRig;
2846
3118
  }
2847
3119
 
3120
+ /**
3121
+ * A secondary value axis (combo charts). Mirrors the primary value-axis
3122
+ * properties but lives in its own object so the flat primary-axis fields stay
3123
+ * untouched. Parsed from the right-hand `<c:valAx>` (`axPos="r"`,
3124
+ * `<c:crosses val="max">`).
3125
+ */
3126
+ declare interface SecondaryValueAxis {
3127
+ /** `<c:scaling><c:min val>`. null = derive from the series data. */
3128
+ min: number | null;
3129
+ /** `<c:scaling><c:max val>`. null = derive from the series data. */
3130
+ max: number | null;
3131
+ /** `<c:title>` plain text. null = no title. */
3132
+ title: string | null;
3133
+ /** `<c:delete val="1"/>` — hide labels/ticks entirely. */
3134
+ hidden: boolean;
3135
+ /** `<c:numFmt formatCode>` for tick labels. */
3136
+ formatCode?: string | null;
3137
+ /** `<c:txPr>…<a:solidFill>` tick-label color (hex without '#'). */
3138
+ fontColor?: string | null;
3139
+ /** `<c:txPr>` tick-label font size (hpt). */
3140
+ fontSizeHpt?: number | null;
3141
+ /** `<c:spPr><a:ln><a:solidFill>` axis-line color (hex without '#'). */
3142
+ lineColor?: string | null;
3143
+ /** `<c:spPr><a:ln w>` axis-line width in EMU. */
3144
+ lineWidthEmu?: number | null;
3145
+ /** `<c:spPr><a:ln><a:noFill>` — hide just the axis rule. */
3146
+ lineHidden: boolean;
3147
+ /** `<c:majorTickMark>` — "cross" (default) | "out" | "in" | "none". */
3148
+ majorTickMark: string;
3149
+ /** `<c:title>` run-prop font size (hpt). */
3150
+ titleFontSizeHpt?: number | null;
3151
+ /** `<c:title>` run-prop bold flag. */
3152
+ titleFontBold?: boolean | null;
3153
+ /** `<c:title>` run-prop color (hex without '#'). */
3154
+ titleFontColor?: string | null;
3155
+ }
3156
+
2848
3157
  declare interface SectionProps {
2849
3158
  pageWidth: number;
2850
3159
  pageHeight: number;
@@ -2856,12 +3165,31 @@ declare interface SectionProps {
2856
3165
  footerDistance: number;
2857
3166
  titlePage: boolean;
2858
3167
  evenAndOddHeaders: boolean;
3168
+ /** ECMA-376 §17.6.22 ST_SectionMark — the body (final) section's `<w:type>`
3169
+ * start type ("continuous" | "nextPage" | "oddPage" | "evenPage"). Governs
3170
+ * how the last section begins relative to the previous one; consumed by the
3171
+ * paginator at the boundary INTO the final section. Absent ⇒ "nextPage" (the
3172
+ * spec default). Non-final sections carry their start type on their own
3173
+ * SectionBreak marker. */
3174
+ sectionStart?: string | null;
2859
3175
  /** ECMA-376 §17.6.5 w:docGrid/@w:type — "default" | "lines" | "linesAndChars" | "snapToChars". */
2860
3176
  docGridType?: string | null;
2861
3177
  /** ECMA-376 §17.6.5 w:docGrid/@w:linePitch in pt. When docGridType is "lines" or
2862
3178
  * "linesAndChars", auto line spacing multiplies against this pitch instead of
2863
3179
  * the font's natural line height. */
2864
3180
  docGridLinePitch?: number | null;
3181
+ /** ECMA-376 §17.6.5 w:docGrid/@w:charSpace (ST_DecimalNumber, signed). The
3182
+ * raw character-grid spacing in 1/4096ths of an em (NOT twips). When
3183
+ * docGridType is "linesAndChars" or "snapToChars", every full-width East-
3184
+ * Asian glyph occupies a fixed cell of width `fontSizePt + charSpace/4096` pt
3185
+ * (negative = tighter). Absent ⇒ East-Asian glyphs keep their natural em
3186
+ * advance. */
3187
+ docGridCharSpace?: number | null;
3188
+ /** ECMA-376 §17.6.4 `<w:cols>` — newspaper-style multi-column layout. `null`
3189
+ * (or absent) ⇒ single full-width column (unchanged behavior). When present,
3190
+ * body text flows top-to-bottom through `count` columns (newspaper fill);
3191
+ * see {@link computeColumns}. */
3192
+ columns?: ColumnsSpec | null;
2865
3193
  }
2866
3194
 
2867
3195
  declare type SelectionMode_2 = 'cells' | 'rows' | 'cols' | 'all';
@@ -3100,6 +3428,17 @@ declare interface ShapeRun {
3100
3428
  /** `<a:xfrm flipV>` (§20.1.7.6) — mirror about the horizontal centre line. */
3101
3429
  flipV?: boolean;
3102
3430
  wrapMode?: string | null;
3431
+ /** Padding top (pt). Anchor-only. Mirrors {@link ImageRun.distTop}; an anchored
3432
+ * wrap-shape uses these to size its float-exclusion band (ECMA-376 §20.4.2.x). */
3433
+ distTop?: number;
3434
+ /** Padding bottom (pt). Anchor-only. */
3435
+ distBottom?: number;
3436
+ /** Padding left (pt). Anchor-only. */
3437
+ distLeft?: number;
3438
+ /** Padding right (pt). Anchor-only. */
3439
+ distRight?: number;
3440
+ /** wrapText attribute: "bothSides" | "left" | "right" | "largest". */
3441
+ wrapSide?: string | null;
3103
3442
  /** Text rendered INSIDE the shape's bounding box (`<wps:txbx><w:txbxContent>`). */
3104
3443
  textBlocks?: ShapeText_2[];
3105
3444
  /** "t" | "ctr" | "b" — vertical anchor for the shape's text body (`<wps:bodyPr @anchor>`). */
@@ -3126,7 +3465,26 @@ declare interface ShapeText_2 {
3126
3465
  fontFamily?: string | null;
3127
3466
  bold?: boolean;
3128
3467
  italic?: boolean;
3468
+ /** Per-run formatting for this paragraph (one entry per `<w:r>` with text).
3469
+ * When non-empty the renderer draws the block as rich text (each run's
3470
+ * font); otherwise it uses the single block-level format fields above
3471
+ * (image blocks / legacy single-format paragraphs). Absent for image-only
3472
+ * paragraphs. */
3473
+ runs?: ShapeTextRun_2[];
3129
3474
  alignment: string;
3475
+ /** Zip path of an inline image inside this text-box paragraph
3476
+ * (`<w:drawing><wp:inline><a:blip r:embed>`), e.g. `word/media/image1.emf`.
3477
+ * Absent for a text-only paragraph. */
3478
+ imagePath?: string;
3479
+ /** MIME type of the blip at {@link ShapeText.imagePath}. */
3480
+ mimeType?: string;
3481
+ /** Zip path of the vector original (`asvg:svgBlip` extension), preferred over
3482
+ * `imagePath` when present. */
3483
+ svgImagePath?: string;
3484
+ /** Inline image natural width in pt (from `<wp:extent cx>`). */
3485
+ imageWidthPt?: number;
3486
+ /** Inline image natural height in pt (from `<wp:extent cy>`). */
3487
+ imageHeightPt?: number;
3130
3488
  }
3131
3489
 
3132
3490
  /** A run within a shape paragraph — tagged union mirroring the Rust enum
@@ -3156,6 +3514,25 @@ declare type ShapeTextRun = {
3156
3514
  color?: string;
3157
3515
  };
3158
3516
 
3517
+ /** One formatting run (`<w:r>`) inside a shape-text paragraph. Mirrors the
3518
+ * character-formatting fields of {@link ShapeText}; the renderer lays a
3519
+ * paragraph's {@link ShapeText.runs} out as rich text so mixed bold/non-bold
3520
+ * runs each keep their own font. */
3521
+ declare interface ShapeTextRun_2 {
3522
+ text: string;
3523
+ fontSizePt: number;
3524
+ color?: string | null;
3525
+ /** ECMA-376 §17.3.2.26 ascii axis (`<w:rFonts w:ascii>`), resolved through
3526
+ * docDefaults. Latin letters/digits in this run render with this family. */
3527
+ fontFamily?: string | null;
3528
+ /** ECMA-376 §17.3.2.26 eastAsia axis (`<w:rFonts w:eastAsia>`), resolved
3529
+ * through docDefaults. CJK characters in this run render with this family;
3530
+ * the renderer falls back to {@link ShapeTextRun.fontFamily} when absent. */
3531
+ fontFamilyEastAsia?: string | null;
3532
+ bold?: boolean;
3533
+ italic?: boolean;
3534
+ }
3535
+
3159
3536
  declare interface SharedString {
3160
3537
  text: string;
3161
3538
  runs?: Run[];
@@ -3454,6 +3831,39 @@ declare interface TabStop_2 {
3454
3831
  leader: 'none' | 'dot' | 'hyphen' | 'underscore' | 'heavy' | 'middleDot';
3455
3832
  }
3456
3833
 
3834
+ /**
3835
+ * ECMA-376 §17.4.57 `<w:tblpPr>` — floating-table positioning. Present in
3836
+ * `<w:tblPr>` ⇒ the table FLOATS (out of the main text flow, absolutely
3837
+ * positioned by its top-left corner). All fields are optional in the source.
3838
+ */
3839
+ declare interface TblpPr {
3840
+ /** §17.4.57 minimum distance to wrapping text (dist padding), pt. Default 0. */
3841
+ leftFromText: number;
3842
+ rightFromText: number;
3843
+ topFromText: number;
3844
+ bottomFromText: number;
3845
+ /** §17.4.57 ST_HAnchor {text,margin,page}. Default 'page'. */
3846
+ horzAnchor: 'text' | 'margin' | 'page' | string;
3847
+ /** True iff the source `<w:tblpPr>` carried ANY horizontal positioning hint
3848
+ * (horzAnchor, tblpX, or tblpXSpec). When false, no horizontal position was
3849
+ * given: ECMA-376's literal default is the page edge, but Word places such a
3850
+ * table at the anchor paragraph's text/column left. computeFloatTableBox uses
3851
+ * this flag to apply that Word-runtime placement. */
3852
+ horzSpecified: boolean;
3853
+ /** §17.4.57 ST_VAnchor {text,margin,page}. Default 'page'. */
3854
+ vertAnchor: 'text' | 'margin' | 'page' | string;
3855
+ /** §17.4.57 absolute signed offset from the horz/vert anchor edge, pt.
3856
+ * Default 0. Ignored when the matching `*Spec` is present. */
3857
+ tblpX: number;
3858
+ tblpY: number;
3859
+ /** §17.4.57 ST_XAlign {left,center,right,inside,outside}. Supersedes tblpX. */
3860
+ tblpXSpec?: 'left' | 'center' | 'right' | 'inside' | 'outside' | string;
3861
+ /** §17.4.57 ST_YAlign {inline,top,center,bottom,inside,outside}. Supersedes
3862
+ * tblpY, UNLESS vertAnchor='text' (relative vertical positioning is not
3863
+ * allowed there ⇒ tblpYSpec is ignored, fall back to tblpY). */
3864
+ tblpYSpec?: 'inline' | 'top' | 'center' | 'bottom' | 'inside' | 'outside' | string;
3865
+ }
3866
+
3457
3867
  /**
3458
3868
  * PPTX text body. Extends the shared core `TextBody` with PPTX-only bodyPr
3459
3869
  * fields that the pptx parser surfaces but the shared core model does not yet