superdoc 2.4.0 → 2.5.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.
Files changed (63) hide show
  1. package/README.md +12 -90
  2. package/dist/chunks/{create-super-doc-ui-CqGmoMMA.cjs → create-super-doc-ui-Bom7oDPv.cjs} +194 -29
  3. package/dist/chunks/{create-super-doc-ui-CmOSA_lN.es.js → create-super-doc-ui-DbzVC0rr.es.js} +194 -29
  4. package/dist/chunks/{eventemitter3-DEIiXiH2.es.js → eventemitter3-CMOjDs74.es.js} +1 -1
  5. package/dist/chunks/{eventemitter3-C_TAnXOl.cjs → eventemitter3-D38u8ta_.cjs} +1 -1
  6. package/dist/chunks/{jszip-D8mAFF-r.cjs → jszip-RC64TPzL.cjs} +1 -1
  7. package/dist/chunks/{jszip-BzJ3CyxR.es.js → jszip-VxCFV9YS.es.js} +1 -1
  8. package/dist/chunks/{rolldown-runtime-0pSA04fp.es.js → rolldown-runtime-B5TtN50X.es.js} +1 -1
  9. package/dist/chunks/{rolldown-runtime-74VwNCz7.cjs → rolldown-runtime-DtsSbkrh.cjs} +1 -1
  10. package/dist/collaboration-upgrade-engine.cjs +1 -1
  11. package/dist/collaboration-upgrade-engine.es.js +1 -1
  12. package/dist/document-api/src/types/track-changes.types.d.ts +17 -0
  13. package/dist/layout-engine/contracts/src/graphic-placement.d.ts +35 -6
  14. package/dist/layout-engine/contracts/src/index.d.ts +296 -13
  15. package/dist/layout-engine/contracts/src/resolved-layout.d.ts +5 -0
  16. package/dist/layout-engine/dom-contract/src/class-names.d.ts +2 -0
  17. package/dist/layout-engine/layout-bridge/src/footnote-scorer.d.ts +1 -1
  18. package/dist/layout-engine/layout-bridge/src/hydrateTableTextboxMeasures.d.ts +9 -0
  19. package/dist/layout-engine/layout-bridge/src/incrementalLayout.d.ts +40 -12
  20. package/dist/layout-engine/layout-bridge/src/index.d.ts +3 -2
  21. package/dist/layout-engine/layout-bridge/src/layoutHeaderFooter.d.ts +10 -7
  22. package/dist/layout-engine/layout-bridge/src/remeasure.d.ts +2 -2
  23. package/dist/layout-engine/layout-engine/src/anchors.d.ts +4 -0
  24. package/dist/layout-engine/layout-engine/src/execution.d.ts +21 -0
  25. package/dist/layout-engine/layout-engine/src/floating-objects.d.ts +15 -2
  26. package/dist/layout-engine/layout-engine/src/floating-table-anchor.d.ts +2 -0
  27. package/dist/layout-engine/layout-engine/src/footnote-anchor-index.d.ts +17 -0
  28. package/dist/layout-engine/layout-engine/src/index.d.ts +13 -10
  29. package/dist/layout-engine/layout-engine/src/inline-drawing-alignment.d.ts +9 -0
  30. package/dist/layout-engine/layout-engine/src/layout-drawing.d.ts +3 -3
  31. package/dist/layout-engine/layout-engine/src/layout-paragraph.d.ts +2 -2
  32. package/dist/layout-engine/layout-engine/src/layout-textbox.d.ts +3 -3
  33. package/dist/layout-engine/layout-engine/src/pageNumbering.d.ts +3 -41
  34. package/dist/layout-engine/layout-engine/src/paginator.d.ts +7 -2
  35. package/dist/layout-engine/layout-engine/src/resolvePageTokens.d.ts +2 -0
  36. package/dist/layout-engine/layout-engine/src/section-breaks.d.ts +1 -0
  37. package/dist/layout-engine/layout-engine/src/section-props.d.ts +5 -0
  38. package/dist/layout-engine/painters/dom/src/chart-renderer.d.ts +3 -3
  39. package/dist/layout-engine/painters/dom/src/images/image-outline.d.ts +7 -0
  40. package/dist/layout-engine/painters/dom/src/images/render-placeholder.d.ts +12 -0
  41. package/dist/layout-engine/painters/dom/src/renderer.d.ts +54 -0
  42. package/dist/layout-engine/painters/dom/src/runs/text-effects.d.ts +30 -0
  43. package/dist/layout-engine/painters/dom/src/runs/text-run.d.ts +6 -4
  44. package/dist/layout-engine/painters/dom/src/shapes/preset-text-warp-data.d.ts +32 -0
  45. package/dist/layout-engine/painters/dom/src/shapes/wordart-warp.d.ts +39 -0
  46. package/dist/layout-engine/painters/dom/src/table/border-utils.d.ts +20 -27
  47. package/dist/layout-engine/painters/dom/src/table/renderTableFragment.d.ts +1 -1
  48. package/dist/layout-engine/style-engine/src/ooxml/word-style-model/parse-theme.d.ts +7 -0
  49. package/dist/public/ui-react.cjs +1 -1
  50. package/dist/public/ui-react.es.js +1 -1
  51. package/dist/public/ui.cjs +1 -1
  52. package/dist/public/ui.es.js +1 -1
  53. package/dist/style.css +87 -87
  54. package/dist/style.layered.css +87 -87
  55. package/dist/superdoc/src/core/config/normalize-ui-config.d.ts +5 -0
  56. package/dist/superdoc/src/core/types/index.d.ts +24 -0
  57. package/dist/superdoc.cjs +88 -79
  58. package/dist/superdoc.es.js +88 -79
  59. package/dist-cdn/style.layered.css +1 -1
  60. package/dist-cdn/superdoc.min.css +1 -1
  61. package/dist-cdn/superdoc.min.js +37 -37
  62. package/package.json +2 -6
  63. package/AGENTS.md +0 -337
@@ -1,6 +1,7 @@
1
1
  import { TabStop } from './engines/tabs.js';
2
2
  import { PageNumberChapterSeparator, PageNumberFieldFormat, PageNumberFormat } from './page-number-formatting.js';
3
3
  import { TrackedChangeSemanticColorKey } from './semantic-colors.js';
4
+ import { AnchorAlignH, AnchorAlignV, AnchorHRelative, AnchorVRelative } from './graphic-placement.js';
4
5
  import { ParagraphDirectionContext, RunBidiContext, RunScriptContext, TableDirectionContext } from './direction-context.js';
5
6
  import { LayoutSourceIdentity } from './layout-identity.js';
6
7
  export { computeTabStops, layoutWithTabs, calculateTabWidth } from './engines/tabs.js';
@@ -17,7 +18,7 @@ export { shouldApplyJustify, calculateJustifySpacing, getFirstLineIndentOffset,
17
18
  export { parseInsetClipPathForScale, formatInsetClipPathTransform, type InsetClipPathScale, } from './clip-path-inset.js';
18
19
  export { SUBSCRIPT_SUPERSCRIPT_SCALE, normalizeBaselineShift, hasExplicitBaselineShift, isSuperscriptOrSubscript, usesDefaultScriptLayout, scaleFontSizeForVerticalText, resolveBaseFontSizeForVerticalText, type VerticalTextAlign, } from './vertical-text.js';
19
20
  export { computeFragmentPmRange, computeLinePmRange, type LinePmRange } from './pm-range.js';
20
- export { resolveAnchoredGraphicY, resolveAnchoredGraphicX, resolveFooterPageFrameOriginY, isPositionedParagraphFrame, isPagePositionedParagraphFrame, type ColumnLayoutForAnchor, type ResolveAnchoredGraphicYInput, } from './graphic-placement.js';
21
+ export { resolveAnchoredGraphicY, resolveAnchoredGraphicX, resolveFooterPageFrameOriginY, isPositionedParagraphFrame, isPagePositionedParagraphFrame, isAnchorHRelative, isAnchorVRelative, isAnchorAlignH, isAnchorAlignV, ANCHOR_H_RELATIVE_VALUES, ANCHOR_V_RELATIVE_VALUES, ANCHOR_H_ALIGN_VALUES, ANCHOR_V_ALIGN_VALUES, type ColumnLayoutForAnchor, type ResolveAnchoredGraphicYInput, type ResolveAnchoredGraphicXContext, type AnchorHRelative, type AnchorVRelative, type AnchorAlignH, type AnchorAlignV, } from './graphic-placement.js';
21
22
  export { LAYOUT_BOUNDARY_SCHEMA, bodyStoryLocator, namedStoryLocator, computeLayoutFragmentId, buildLayoutSourceIdentity, buildLayoutSourceIdentityForFragment, } from './layout-identity.js';
22
23
  export type { LayoutBlockRef, LayoutFragmentId, LayoutPartialRowIdentity, LayoutSourceIdentity, LayoutStoryKind, LayoutStoryLocator, } from './layout-identity.js';
23
24
  export { LAYOUT_SEGMENT_GEOMETRY_SCHEMA } from './segment-geometry.js';
@@ -317,6 +318,8 @@ export type RunMarks = {
317
318
  * Rendering normalizes a shift of zero to "no explicit shift".
318
319
  */
319
320
  baselineShift?: number;
321
+ /** Paint-only Word 2010+ text effects (`w14:textFill`, outline, shadow, reflection). */
322
+ textEffects?: TextEffects;
320
323
  };
321
324
  export type PageReferenceRelativePositionText = 'above' | 'below';
322
325
  export type FieldResultFormat = 'charformat' | 'mergeformat';
@@ -472,6 +475,31 @@ export type ImageHyperlink = {
472
475
  * baseline next to the surrounding text instead of floating above it.
473
476
  */
474
477
  export type ImageRunVerticalAlign = 'top' | 'bottom' | 'baseline';
478
+ /**
479
+ * Paint-only frame authored on a DrawingML picture (`pic:spPr/a:ln`).
480
+ *
481
+ * The frame is intentionally separate from the image dimensions: DrawingML
482
+ * strokes are centered on the picture geometry and must not enlarge the
483
+ * layout box. Keeping this as a shared contract lets inline and anchored
484
+ * pictures use the same extraction and paint path.
485
+ */
486
+ export type ImageOutline = {
487
+ color: string;
488
+ /** Physical CSS-pixel width resolved from `a:ln/@w`. */
489
+ width: number;
490
+ };
491
+ /**
492
+ * Explicit fail-closed rendering metadata for content that keeps its authored
493
+ * layout box but cannot be painted faithfully.
494
+ *
495
+ * The producer owns the diagnostic identity; painters only expose it on the
496
+ * visible, accessible placeholder. This keeps support decisions out of the DOM
497
+ * layer and makes degraded output observable in browser regression proofs.
498
+ */
499
+ export type RenderPlaceholder = {
500
+ diagnosticIds: string[];
501
+ accessibleName: string;
502
+ };
475
503
  /**
476
504
  * Inline image run for images that flow with text on the same line.
477
505
  * Unlike ImageBlock (anchored/floating images), ImageRun is part of the paragraph's run array
@@ -498,14 +526,22 @@ export type ImageRun = {
498
526
  width: number;
499
527
  /** Image height in pixels. */
500
528
  height: number;
529
+ /** Font family of the owning OOXML run, used to compose an image-only line box. */
530
+ fontFamily?: string;
531
+ /** Font size of the owning OOXML run, used to compose an image-only line box. */
532
+ fontSize?: number;
501
533
  /** Alternative text for accessibility. */
502
534
  alt?: string;
503
535
  /** Image title (tooltip). */
504
536
  title?: string;
537
+ /** Visible fail-closed replacement when the image source cannot be painted. */
538
+ placeholder?: RenderPlaceholder;
505
539
  /** DrawingML docPr/@id of the picture (used to target the Document API for interactive resize). */
506
540
  imageId?: string;
507
541
  /** Clip-path value for cropped images. */
508
542
  clipPath?: string;
543
+ /** DrawingML picture frame; paint-only and excluded from layout sizing. */
544
+ outline?: ImageOutline;
509
545
  /**
510
546
  * Spacing around the image (from DOCX distT/distB/distL/distR attributes).
511
547
  * Applied as CSS margins in the DOM painter.
@@ -717,6 +753,12 @@ export type BorderSpec = {
717
753
  color?: string;
718
754
  space?: number;
719
755
  };
756
+ /**
757
+ * Returns the complete painted width of an OOXML table border in CSS pixels.
758
+ * `w:sz` is the width of the complete border, including compound styles such
759
+ * as double. `thick` retains the existing table-painter minimum used in V2.
760
+ */
761
+ export declare const getRenderedTableBorderWidthPx: (border: Pick<BorderSpec, "style" | "width"> | undefined, defaultWidth?: number) => number;
720
762
  /**
721
763
  * Three-state border value for table borders.
722
764
  * - `null`: inherit from table style
@@ -742,6 +784,16 @@ export type CellBorders = {
742
784
  bottom?: BorderSpec;
743
785
  left?: BorderSpec;
744
786
  };
787
+ /** True when a normalized border contributes a visible edge. */
788
+ export declare const isPresentBorder: (border?: BorderSpec) => border is BorderSpec;
789
+ /** True when the source explicitly suppresses an edge rather than omitting it. */
790
+ export declare const isExplicitNoneBorder: (border?: unknown) => boolean;
791
+ /**
792
+ * Resolve the single visible edge shared by two cells according to
793
+ * ECMA-376 Part 1 §17.4.66. Kept in the editor-neutral contract package so
794
+ * import and DOM paint use one conflict algorithm.
795
+ */
796
+ export declare const resolveBorderConflict: (first?: BorderSpec, second?: BorderSpec) => BorderSpec | undefined;
745
797
  export type TableCellAttrs = {
746
798
  borders?: CellBorders;
747
799
  padding?: BoxSpacing;
@@ -874,6 +926,10 @@ export type ImageBlock = {
874
926
  height?: number;
875
927
  alt?: string;
876
928
  title?: string;
929
+ /** DrawingML picture frame; paint-only and excluded from layout sizing. */
930
+ outline?: ImageOutline;
931
+ /** Visible fail-closed replacement when the image source cannot be painted. */
932
+ placeholder?: RenderPlaceholder;
877
933
  /** DrawingML docPr/@id of the picture (used to target the Document API for interactive resize). */
878
934
  imageId?: string;
879
935
  objectFit?: 'contain' | 'cover' | 'fill' | 'scale-down';
@@ -969,11 +1025,73 @@ export type TextFormatting = {
969
1025
  fontSize?: number;
970
1026
  fontFamily?: string;
971
1027
  letterSpacing?: number;
1028
+ /** Paint-only Word 2010+ text effects shared with ordinary text runs. */
1029
+ textEffects?: TextEffects;
1030
+ };
1031
+ /** Solid color used by a text effect, with optional opacity. */
1032
+ export type TextEffectColor = {
1033
+ color: string;
1034
+ alpha?: number;
1035
+ };
1036
+ /** Word 2010+ text outline (`w14:textOutline`). */
1037
+ export type TextOutlineEffect = {
1038
+ /** Outline width converted from EMU to CSS pixels. */
1039
+ width: number;
1040
+ fill: FillColor;
1041
+ };
1042
+ /** Word 2010+ text glow (`w14:glow`). */
1043
+ export type TextGlowEffect = {
1044
+ color: TextEffectColor;
1045
+ /** Glow radius converted from EMU to CSS pixels. */
1046
+ radius: number;
1047
+ };
1048
+ /** Word 2010+ outer text shadow (`w14:shadow`). */
1049
+ export type TextShadowEffect = {
1050
+ color: TextEffectColor;
1051
+ /** Blur radius converted from EMU to CSS pixels. */
1052
+ blurRadius: number;
1053
+ /** Shadow distance converted from EMU to CSS pixels. */
1054
+ distance: number;
1055
+ /** Direction in DrawingML degrees (`0` points right, `90` points down). */
1056
+ direction: number;
1057
+ };
1058
+ /** Word 2010+ reflected-text mask (`w14:reflection`). */
1059
+ export type TextReflectionEffect = {
1060
+ blurRadius: number;
1061
+ distance: number;
1062
+ direction: number;
1063
+ /** Direction of the reflection opacity gradient; defaults to `direction`. */
1064
+ fadeDirection?: number;
1065
+ startAlpha: number;
1066
+ startPosition: number;
1067
+ endAlpha: number;
1068
+ endPosition: number;
1069
+ scaleX: number;
1070
+ scaleY: number;
1071
+ };
1072
+ /**
1073
+ * Paint-only text effects shared by paragraph runs and flattened shape text.
1074
+ * These effects do not change glyph advances, so layout measurement continues
1075
+ * to use the run's ordinary typography contract.
1076
+ */
1077
+ export type TextEffects = {
1078
+ fill?: FillColor;
1079
+ outline?: TextOutlineEffect;
1080
+ glow?: TextGlowEffect;
1081
+ shadow?: TextShadowEffect;
1082
+ reflection?: TextReflectionEffect;
972
1083
  };
973
1084
  /** A single text part with optional formatting. */
974
1085
  export type TextPart = {
975
1086
  text: string;
976
1087
  formatting?: TextFormatting;
1088
+ /**
1089
+ * Paragraph properties carried by the first visible part of a shape-text
1090
+ * paragraph. Shape text is intentionally flattened into `parts`, so this
1091
+ * marker preserves the authored block geometry without introducing a second
1092
+ * competing text model.
1093
+ */
1094
+ paragraphProperties?: ShapeTextParagraphProperties;
977
1095
  /** Optional field token (e.g., PAGE/NUMPAGES/SECTIONPAGES) resolved at render time. */
978
1096
  fieldType?: 'PAGE' | 'NUMPAGES' | 'SECTIONPAGES';
979
1097
  /** PAGE/SECTIONPAGES field-local value formatting override. */
@@ -999,6 +1117,17 @@ export type TextPart = {
999
1117
  height?: number;
1000
1118
  alt?: string;
1001
1119
  };
1120
+ /** Paragraph geometry used by flattened DrawingML/VML shape text. */
1121
+ export type ShapeTextParagraphProperties = {
1122
+ horizontalAlign?: 'left' | 'center' | 'right' | 'justify';
1123
+ spacingBefore?: number;
1124
+ spacingAfter?: number;
1125
+ line?: number;
1126
+ lineUnit?: 'px' | 'multiplier';
1127
+ leftIndent?: number;
1128
+ rightIndent?: number;
1129
+ firstLineIndent?: number;
1130
+ };
1002
1131
  /** Text content configuration for shapes. */
1003
1132
  export type ShapeTextContent = {
1004
1133
  /** Array of text parts with individual formatting. */
@@ -1006,6 +1135,34 @@ export type ShapeTextContent = {
1006
1135
  /** Horizontal text alignment within the shape. */
1007
1136
  horizontalAlign?: 'left' | 'center' | 'right';
1008
1137
  };
1138
+ /** DrawingML textbox flow/overflow semantics from `a:bodyPr`. */
1139
+ export type ShapeTextLayout = {
1140
+ /** `a:bodyPr/@wrap`; `none` keeps authored paragraphs on explicit lines only. */
1141
+ wrap?: 'square' | 'none';
1142
+ /** `a:bodyPr/@horzOverflow`. */
1143
+ horizontalOverflow?: 'overflow' | 'clip';
1144
+ /** `a:bodyPr/@vertOverflow`. */
1145
+ verticalOverflow?: 'overflow' | 'clip' | 'ellipsis';
1146
+ };
1147
+ /** ECMA-376 Part 1 `ST_TextShapeType` preset text-warp vocabulary. */
1148
+ export declare const SHAPE_TEXT_WARP_PRESETS: readonly ["textNoShape", "textPlain", "textStop", "textTriangle", "textTriangleInverted", "textChevron", "textChevronInverted", "textRingInside", "textRingOutside", "textArchUp", "textArchDown", "textCircle", "textButton", "textArchUpPour", "textArchDownPour", "textCirclePour", "textButtonPour", "textCurveUp", "textCurveDown", "textCanUp", "textCanDown", "textWave1", "textWave2", "textDoubleWave1", "textWave4", "textInflate", "textDeflate", "textInflateBottom", "textDeflateBottom", "textInflateTop", "textDeflateTop", "textDeflateInflate", "textDeflateInflateDeflate", "textFadeRight", "textFadeLeft", "textFadeUp", "textFadeDown", "textSlantUp", "textSlantDown", "textCascadeUp", "textCascadeDown"];
1149
+ export type ShapeTextWarpPreset = (typeof SHAPE_TEXT_WARP_PRESETS)[number];
1150
+ export declare function isShapeTextBaselineWarp(warp: ShapeTextWarp | undefined): boolean;
1151
+ export declare function isShapeTextSingleBandEnvelopeWarp(warp: ShapeTextWarp | undefined): boolean;
1152
+ /** Preserved `a:prstTxWarp` geometry and guide formulas from `a:bodyPr`. */
1153
+ export type ShapeTextWarp = {
1154
+ preset: ShapeTextWarpPreset;
1155
+ adjustments?: Array<{
1156
+ name: string;
1157
+ /** Raw DrawingML guide formula, for example `val 25000`. */
1158
+ formula: string;
1159
+ }>;
1160
+ };
1161
+ /** Resolve the line-breaking width for DrawingML textbox content. */
1162
+ export declare function resolveShapeTextContentMeasureWidth(shapeWidth: number, insets: {
1163
+ left: number;
1164
+ right: number;
1165
+ }, layout: ShapeTextLayout | undefined, autoFitBoundaryWidth?: number): number;
1009
1166
  export type LineEnd = {
1010
1167
  type?: string;
1011
1168
  width?: string;
@@ -1021,14 +1178,53 @@ export type EffectExtent = {
1021
1178
  right: number;
1022
1179
  bottom: number;
1023
1180
  };
1181
+ /**
1182
+ * DrawingML relative rectangle in the source 1000ths-of-a-percent units.
1183
+ * Values may be negative: ECMA-376 allows an outset as well as an inset.
1184
+ */
1185
+ export type ShapeImageFillRect = {
1186
+ left: number;
1187
+ top: number;
1188
+ right: number;
1189
+ bottom: number;
1190
+ };
1191
+ /** DrawingML `a:tile` parameters, preserved without painter-specific conversion. */
1192
+ export type ShapeImageFillTile = {
1193
+ offsetX?: number;
1194
+ offsetY?: number;
1195
+ scaleX?: number;
1196
+ scaleY?: number;
1197
+ flip?: string;
1198
+ alignment?: string;
1199
+ };
1200
+ /** Resolved bitmap used as the fill paint for vector geometry. */
1201
+ export type ShapeImageFill = {
1202
+ src: string;
1203
+ mode: 'stretch' | 'tile';
1204
+ sourceRect?: ShapeImageFillRect;
1205
+ fillRect?: ShapeImageFillRect;
1206
+ tile?: ShapeImageFillTile;
1207
+ dpi?: number;
1208
+ rotateWithShape?: boolean;
1209
+ };
1024
1210
  export type VectorShapeStyle = {
1025
1211
  fillColor?: FillColor;
1212
+ imageFill?: ShapeImageFill;
1026
1213
  strokeColor?: StrokeColor;
1027
1214
  strokeWidth?: number;
1215
+ /** Physical CSS-pixel dash/gap lengths resolved from the source stroke. */
1216
+ strokeDashArray?: number[];
1217
+ strokeLineJoin?: 'round' | 'bevel' | 'miter';
1218
+ strokeLineCap?: 'round' | 'square' | 'butt';
1219
+ /** Optional per-edge frame used by render-only table cells inside legacy shape groups. */
1220
+ borders?: CellBorders;
1028
1221
  lineEnds?: LineEnds;
1029
1222
  textContent?: ShapeTextContent;
1223
+ textLayout?: ShapeTextLayout;
1030
1224
  textAlign?: string;
1031
1225
  textVerticalAlign?: 'top' | 'center' | 'bottom';
1226
+ /** Legacy VML textbox text-flow semantics. */
1227
+ textFlow?: 'horizontal' | 'vertical' | 'vertical-ideographic' | 'horizontal-ideographic' | 'bottom-to-top';
1032
1228
  textInsets?: {
1033
1229
  top: number;
1034
1230
  right: number;
@@ -1086,6 +1282,8 @@ export type DrawingBlockBase = {
1086
1282
  drawingContent?: DrawingContentSnapshot;
1087
1283
  attrs?: Record<string, unknown>;
1088
1284
  sourceAnchor?: SourceAnchor;
1285
+ /** Visible fail-closed replacement metadata owned by the projection layer. */
1286
+ placeholder?: RenderPlaceholder;
1089
1287
  };
1090
1288
  /**
1091
1289
  * Custom geometry path data extracted from a:custGeom/a:pathLst.
@@ -1107,13 +1305,20 @@ export type VectorShapeDrawing = DrawingBlockBase & {
1107
1305
  shapeKind?: string;
1108
1306
  customGeometry?: CustomGeometryData;
1109
1307
  fillColor?: FillColor;
1308
+ imageFill?: ShapeImageFill;
1110
1309
  strokeColor?: StrokeColor;
1111
1310
  strokeWidth?: number;
1311
+ strokeDashArray?: number[];
1312
+ strokeLineJoin?: 'round' | 'bevel' | 'miter';
1313
+ strokeLineCap?: 'round' | 'square' | 'butt';
1112
1314
  lineEnds?: LineEnds;
1113
1315
  effectExtent?: EffectExtent;
1114
1316
  textContent?: ShapeTextContent;
1317
+ textLayout?: ShapeTextLayout;
1318
+ textWarp?: ShapeTextWarp;
1115
1319
  textAlign?: string;
1116
1320
  textVerticalAlign?: 'top' | 'center' | 'bottom';
1321
+ textFlow?: 'horizontal' | 'vertical' | 'vertical-ideographic' | 'horizontal-ideographic' | 'bottom-to-top';
1117
1322
  textInsets?: {
1118
1323
  top: number;
1119
1324
  right: number;
@@ -1124,26 +1329,45 @@ export type VectorShapeDrawing = DrawingBlockBase & {
1124
1329
  export type TextboxDrawing = DrawingBlockBase & {
1125
1330
  drawingKind: 'textboxShape';
1126
1331
  geometry: DrawingGeometry;
1332
+ /** `a:spAutoFit`: resize the shape height to its measured text content. */
1333
+ autoFit?: boolean;
1127
1334
  shapeKind?: string;
1128
1335
  customGeometry?: CustomGeometryData;
1129
1336
  fillColor?: FillColor;
1337
+ imageFill?: ShapeImageFill;
1130
1338
  strokeColor?: StrokeColor;
1131
1339
  strokeWidth?: number;
1340
+ strokeDashArray?: number[];
1341
+ strokeLineJoin?: 'round' | 'bevel' | 'miter';
1342
+ strokeLineCap?: 'round' | 'square' | 'butt';
1132
1343
  lineEnds?: LineEnds;
1133
1344
  effectExtent?: EffectExtent;
1134
1345
  textContent?: ShapeTextContent;
1346
+ textLayout?: ShapeTextLayout;
1347
+ textWarp?: ShapeTextWarp;
1135
1348
  textAlign?: string;
1136
1349
  textVerticalAlign?: 'top' | 'center' | 'bottom';
1350
+ textFlow?: 'horizontal' | 'vertical' | 'vertical-ideographic' | 'horizontal-ideographic' | 'bottom-to-top';
1137
1351
  textInsets?: {
1138
1352
  top: number;
1139
1353
  right: number;
1140
1354
  bottom: number;
1141
1355
  left: number;
1142
1356
  };
1143
- contentBlocks: ParagraphBlock[];
1144
- /** Paragraph layout results for table-cell textboxes; populated by the layout bridge, read by the painter. */
1145
- contentMeasures?: ParagraphMeasure[];
1357
+ /**
1358
+ * Canonical block content owned by the textbox story.
1359
+ *
1360
+ * ECMA-376 permits general block-level WordprocessingML in `w:txbxContent`.
1361
+ * V2 currently supports paragraphs and tables explicitly; keeping this as a
1362
+ * named subset makes later block-family additions additive instead of
1363
+ * flattening rich content into drawing primitives.
1364
+ */
1365
+ contentBlocks: TextboxContentBlock[];
1366
+ /** Canonical layout results for textbox content; populated by measurement or the layout bridge. */
1367
+ contentMeasures?: TextboxContentMeasure[];
1146
1368
  };
1369
+ export type TextboxContentBlock = ParagraphBlock | TableBlock;
1370
+ export type TextboxContentMeasure = ParagraphMeasure | TableMeasure;
1147
1371
  export type ShapeGroupDrawing = DrawingBlockBase & {
1148
1372
  drawingKind: 'shapeGroup';
1149
1373
  geometry: DrawingGeometry;
@@ -1214,7 +1438,14 @@ export type SectionVerticalAlign = 'top' | 'center' | 'bottom' | 'both';
1214
1438
  export type SectionBreakBlock = {
1215
1439
  kind: 'sectionBreak';
1216
1440
  id: BlockId;
1217
- type?: 'continuous' | 'nextPage' | 'evenPage' | 'oddPage';
1441
+ type?: 'continuous' | 'nextColumn' | 'nextPage' | 'evenPage' | 'oddPage';
1442
+ /**
1443
+ * Physical page parity required for a `nextPage` break. Word derives this
1444
+ * when distinct odd/even headers are enabled and the new section explicitly
1445
+ * restarts page numbering; authored `evenPage`/`oddPage` breaks express the
1446
+ * same constraint through `type` instead.
1447
+ */
1448
+ requiredPageParity?: 'even' | 'odd';
1218
1449
  pageSize?: {
1219
1450
  w: number;
1220
1451
  h: number;
@@ -1312,10 +1543,21 @@ export type ColumnBreakBlock = {
1312
1543
  /** Positioning for anchored images (offsets in CSS px). */
1313
1544
  export type ImageAnchor = {
1314
1545
  isAnchored?: boolean;
1315
- hRelativeFrom?: 'column' | 'page' | 'margin';
1316
- vRelativeFrom?: 'paragraph' | 'page' | 'margin';
1317
- alignH?: 'left' | 'center' | 'right';
1318
- alignV?: 'top' | 'center' | 'bottom';
1546
+ /**
1547
+ * Page-space coordinates from `wp:simplePos` in CSS px.
1548
+ * ECMA-376 Part 1 §20.4.2.13: when present because `wp:anchor/@simplePos`
1549
+ * is true, these coordinates override positionH/positionV.
1550
+ */
1551
+ simplePos?: {
1552
+ x: number;
1553
+ y: number;
1554
+ };
1555
+ /** Keep the anchored object inside its table cell and resize the cell as needed. */
1556
+ layoutInCell?: boolean;
1557
+ hRelativeFrom?: AnchorHRelative;
1558
+ vRelativeFrom?: AnchorVRelative;
1559
+ alignH?: AnchorAlignH;
1560
+ alignV?: AnchorAlignV;
1319
1561
  offsetH?: number;
1320
1562
  offsetV?: number;
1321
1563
  behindDoc?: boolean;
@@ -1331,6 +1573,7 @@ export type ImageAnchor = {
1331
1573
  */
1332
1574
  export declare function isPageRelativeAnchor(input: {
1333
1575
  anchor?: {
1576
+ simplePos?: unknown;
1334
1577
  vRelativeFrom?: unknown;
1335
1578
  } | null;
1336
1579
  } | null | undefined): boolean;
@@ -1418,7 +1661,7 @@ export type ExclusionZone = {
1418
1661
  left: number;
1419
1662
  right: number;
1420
1663
  };
1421
- wrapMode: 'left' | 'right' | 'both' | 'none' | 'largest';
1664
+ wrapMode: 'left' | 'right' | 'both' | 'none' | 'largest' | 'topBottom';
1422
1665
  polygon?: number[][];
1423
1666
  };
1424
1667
  export type ParagraphSpacing = {
@@ -1691,6 +1934,8 @@ export type ParagraphAttrs = {
1691
1934
  tabIntervalTwips?: number;
1692
1935
  keepNext?: boolean;
1693
1936
  keepLines?: boolean;
1937
+ /** Prevent a single first or last paragraph line from appearing alone on a page. Defaults to true. */
1938
+ widowControl?: boolean;
1694
1939
  pageBreakBefore?: boolean;
1695
1940
  trackedChangesMode?: TrackedChangesMode;
1696
1941
  trackedChangesEnabled?: boolean;
@@ -1807,6 +2052,13 @@ export declare const isForcedSectPrSectionBreak: (block: FlowBlock | undefined)
1807
2052
  * accepted only when their source/anchor proves they belong to the same filler
1808
2053
  * run.
1809
2054
  */
2055
+ export type SectionBoundaryFillerScanCheckpoint = {
2056
+ index: number;
2057
+ total: number;
2058
+ };
2059
+ export declare function collectSectionBoundaryFillerBlockIdsSteps(blocks: readonly FlowBlock[], options?: {
2060
+ isTinyInlineBoundaryDrawing?: (block: DrawingBlock, index: number) => boolean;
2061
+ }, checkpointEveryBlocks?: number | null): Generator<SectionBoundaryFillerScanCheckpoint, ReadonlySet<string>, void>;
1810
2062
  export declare const collectSectionBoundaryFillerBlockIds: (blocks: readonly FlowBlock[], options?: {
1811
2063
  isTinyInlineBoundaryDrawing?: (block: DrawingBlock, index: number) => boolean;
1812
2064
  }) => ReadonlySet<string>;
@@ -1921,6 +2173,18 @@ export type Line = {
1921
2173
  */
1922
2174
  tabWidths?: Record<number, number>;
1923
2175
  };
2176
+ /**
2177
+ * One contiguous horizontal region available to a measured paragraph line.
2178
+ *
2179
+ * Coordinates are relative to the paragraph fragment's content origin. A line
2180
+ * can expose multiple regions when text wraps on both sides of a floating
2181
+ * object. Measuring owns the line breaks inside these regions; layout owns
2182
+ * deriving the regions from page/column float geometry.
2183
+ */
2184
+ export type ParagraphLineRegion = {
2185
+ offsetX: number;
2186
+ width: number;
2187
+ };
1924
2188
  export type LineSegment = {
1925
2189
  runIndex: number;
1926
2190
  fromChar: number;
@@ -2021,8 +2285,8 @@ export type DrawingMeasure = {
2021
2285
  naturalHeight: number;
2022
2286
  geometry: DrawingGeometry;
2023
2287
  groupTransform?: ShapeGroupTransform;
2024
- /** Canonical paragraph measurements for textbox content, when the drawing owns text. */
2025
- contentMeasures?: ParagraphMeasure[];
2288
+ /** Canonical block measurements for textbox content, when the drawing owns a textbox story. */
2289
+ contentMeasures?: TextboxContentMeasure[];
2026
2290
  };
2027
2291
  export type TableCellMeasure = {
2028
2292
  /** Multi-block cell measurements (new feature) */
@@ -2151,6 +2415,13 @@ export type FootnotePageLedger = {
2151
2415
  export type Page = {
2152
2416
  number: number;
2153
2417
  fragments: Fragment[];
2418
+ /**
2419
+ * Suppress header/footer stories on a physically inserted parity page.
2420
+ * Word emits these pages to satisfy odd/even section starts, but leaves the
2421
+ * page itself completely blank and does not treat it as page one of the new
2422
+ * section.
2423
+ */
2424
+ suppressHeaderFooter?: boolean;
2154
2425
  margins?: PageMargins;
2155
2426
  /**
2156
2427
  * Extra bottom space reserved on this page for footnotes (in px).
@@ -2384,7 +2655,7 @@ export type DrawingFragment = {
2384
2655
  drawingContentId?: string;
2385
2656
  /** V2 textbox story id for DrawingML textbox content painted inside this drawing. */
2386
2657
  textboxId?: string;
2387
- contentMeasures?: ParagraphMeasure[];
2658
+ contentMeasures?: TextboxContentMeasure[];
2388
2659
  pmStart?: number;
2389
2660
  pmEnd?: number;
2390
2661
  sourceAnchor?: SourceAnchor;
@@ -2415,6 +2686,18 @@ export type HeaderFooterType = 'default' | 'first' | 'even' | 'odd';
2415
2686
  export type HeaderFooterPage = {
2416
2687
  number: number;
2417
2688
  fragments: Fragment[];
2689
+ /**
2690
+ * Measurement height for this page's resolved story content. PAGE/NUMPAGES
2691
+ * fields can wrap differently across physical pages, so paint alignment must
2692
+ * not substitute the layout-wide maximum for this value.
2693
+ */
2694
+ measurementHeight?: number;
2695
+ /** Per-page minimum rendered y, including out-of-band decorations. */
2696
+ minY?: number;
2697
+ /** Per-page maximum rendered y + fragment height. */
2698
+ maxY?: number;
2699
+ /** Per-page visual extent (`maxY - minY`). */
2700
+ renderHeight?: number;
2418
2701
  numberText?: string;
2419
2702
  /** Section-aware numeric page value before formatting. */
2420
2703
  displayNumber?: number;
@@ -476,6 +476,11 @@ export declare function isResolvedDrawingItem(item: ResolvedPaintItem): item is
476
476
  /** A resolved header/footer page — mirrors HeaderFooterPage but with resolved items. */
477
477
  export type ResolvedHeaderFooterPage = {
478
478
  number: number;
479
+ /** Page-local measurement height; see `HeaderFooterPage.measurementHeight`. */
480
+ measurementHeight?: number;
481
+ minY?: number;
482
+ maxY?: number;
483
+ renderHeight?: number;
479
484
  numberText?: string;
480
485
  /** Section-aware numeric page value before formatting. */
481
486
  displayNumber?: number;
@@ -12,6 +12,8 @@ export declare const DOM_CLASS_NAMES: {
12
12
  readonly PAGE: "superdoc-page";
13
13
  /** Fragment container (paragraph, table, image block, etc.). */
14
14
  readonly FRAGMENT: "superdoc-fragment";
15
+ /** Non-flowing fragment whose visual position must not define body flow geometry. */
16
+ readonly FLOATING_FRAGMENT: "superdoc-floating-fragment";
15
17
  /** Line container within a fragment. */
16
18
  readonly LINE: "superdoc-line";
17
19
  /**
@@ -42,7 +42,7 @@ export type FootnoteWindowScoreResult = {
42
42
  };
43
43
  export declare const isMandatoryOnlyFootnotePage: (ledger: FootnotePageLedger, preferredDeltaThresholdPx?: number, mandatoryOnlyTolerancePx?: number) => boolean;
44
44
  /**
45
- * SD-2656 (post-Vivienne-feedback): a page whose LAST anchor partially rendered
45
+ * SD-2656: a page whose LAST anchor partially rendered
46
46
  * but spilled to a later page. The user-visible bug is a footnote split across
47
47
  * pages even when the preferred reserve would fit the whole anchor on the
48
48
  * anchor page (Word does keep it together).
@@ -0,0 +1,9 @@
1
+ import { FlowBlock, ParagraphBlock, ParagraphMeasure } from '../../contracts/src/index.js';
2
+ type TextboxRemeasure = (block: ParagraphBlock, maxWidth: number) => ParagraphMeasure;
3
+ /**
4
+ * Derives table-cell textbox measurements without mutating the projection
5
+ * plane supplied by the caller. Only the textbox and its table ancestry are
6
+ * copied; documents without table textboxes retain their original identities.
7
+ */
8
+ export declare function hydrateTableTextboxMeasures(blocks: FlowBlock[], remeasure: TextboxRemeasure): FlowBlock[];
9
+ export {};