superdoc 2.4.0-next.41 → 2.4.0-next.43

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.
@@ -19,7 +19,7 @@ var COLLABORATION_UPGRADE_ENGINE_MINIMUM_NODE_MAJOR = 20;
19
19
  var PRIVATE_ENGINE_INFO = (0, _superdoc_docx_engine_collaboration_upgrade_engine.getCollaborationUpgradeEngineInfo)();
20
20
  var ENGINE_INFO = Object.freeze({
21
21
  ...PRIVATE_ENGINE_INFO,
22
- superdocVersion: "2.4.0-next.41",
22
+ superdocVersion: "2.4.0-next.43",
23
23
  roomSchemaVersion: Object.freeze({ ...PRIVATE_ENGINE_INFO.roomSchemaVersion }),
24
24
  supportedBundleVersions: SUPPORTED_COLLABORATION_UPGRADE_BUNDLE_VERSIONS,
25
25
  supportedV1ReaderContractVersions: SUPPORTED_V1_READER_CONTRACT_VERSIONS
@@ -18,7 +18,7 @@ var COLLABORATION_UPGRADE_ENGINE_MINIMUM_NODE_MAJOR = 20;
18
18
  var PRIVATE_ENGINE_INFO = getCollaborationUpgradeEngineInfo$1();
19
19
  var ENGINE_INFO = Object.freeze({
20
20
  ...PRIVATE_ENGINE_INFO,
21
- superdocVersion: "2.4.0-next.41",
21
+ superdocVersion: "2.4.0-next.43",
22
22
  roomSchemaVersion: Object.freeze({ ...PRIVATE_ENGINE_INFO.roomSchemaVersion }),
23
23
  supportedBundleVersions: SUPPORTED_COLLABORATION_UPGRADE_BUNDLE_VERSIONS,
24
24
  supportedV1ReaderContractVersions: SUPPORTED_V1_READER_CONTRACT_VERSIONS
@@ -742,6 +742,16 @@ export type CellBorders = {
742
742
  bottom?: BorderSpec;
743
743
  left?: BorderSpec;
744
744
  };
745
+ /** True when a normalized border contributes a visible edge. */
746
+ export declare const isPresentBorder: (border?: BorderSpec) => border is BorderSpec;
747
+ /** True when the source explicitly suppresses an edge rather than omitting it. */
748
+ export declare const isExplicitNoneBorder: (border?: unknown) => boolean;
749
+ /**
750
+ * Resolve the single visible edge shared by two cells according to
751
+ * ECMA-376 Part 1 §17.4.66. Kept in the editor-neutral contract package so
752
+ * import and DOM paint use one conflict algorithm.
753
+ */
754
+ export declare const resolveBorderConflict: (first?: BorderSpec, second?: BorderSpec) => BorderSpec | undefined;
745
755
  export type TableCellAttrs = {
746
756
  borders?: CellBorders;
747
757
  padding?: BoxSpacing;
@@ -974,6 +984,13 @@ export type TextFormatting = {
974
984
  export type TextPart = {
975
985
  text: string;
976
986
  formatting?: TextFormatting;
987
+ /**
988
+ * Paragraph properties carried by the first visible part of a shape-text
989
+ * paragraph. Shape text is intentionally flattened into `parts`, so this
990
+ * marker preserves the authored block geometry without introducing a second
991
+ * competing text model.
992
+ */
993
+ paragraphProperties?: ShapeTextParagraphProperties;
977
994
  /** Optional field token (e.g., PAGE/NUMPAGES/SECTIONPAGES) resolved at render time. */
978
995
  fieldType?: 'PAGE' | 'NUMPAGES' | 'SECTIONPAGES';
979
996
  /** PAGE/SECTIONPAGES field-local value formatting override. */
@@ -999,6 +1016,17 @@ export type TextPart = {
999
1016
  height?: number;
1000
1017
  alt?: string;
1001
1018
  };
1019
+ /** Paragraph geometry used by flattened DrawingML/VML shape text. */
1020
+ export type ShapeTextParagraphProperties = {
1021
+ horizontalAlign?: 'left' | 'center' | 'right' | 'justify';
1022
+ spacingBefore?: number;
1023
+ spacingAfter?: number;
1024
+ line?: number;
1025
+ lineUnit?: 'px' | 'multiplier';
1026
+ leftIndent?: number;
1027
+ rightIndent?: number;
1028
+ firstLineIndent?: number;
1029
+ };
1002
1030
  /** Text content configuration for shapes. */
1003
1031
  export type ShapeTextContent = {
1004
1032
  /** Array of text parts with individual formatting. */
@@ -1025,6 +1053,8 @@ export type VectorShapeStyle = {
1025
1053
  fillColor?: FillColor;
1026
1054
  strokeColor?: StrokeColor;
1027
1055
  strokeWidth?: number;
1056
+ /** Optional per-edge frame used by render-only table cells inside legacy shape groups. */
1057
+ borders?: CellBorders;
1028
1058
  lineEnds?: LineEnds;
1029
1059
  textContent?: ShapeTextContent;
1030
1060
  textAlign?: string;
@@ -1124,6 +1154,8 @@ export type VectorShapeDrawing = DrawingBlockBase & {
1124
1154
  export type TextboxDrawing = DrawingBlockBase & {
1125
1155
  drawingKind: 'textboxShape';
1126
1156
  geometry: DrawingGeometry;
1157
+ /** `a:spAutoFit`: resize the shape height to its measured text content. */
1158
+ autoFit?: boolean;
1127
1159
  shapeKind?: string;
1128
1160
  customGeometry?: CustomGeometryData;
1129
1161
  fillColor?: FillColor;
@@ -1312,6 +1344,8 @@ export type ColumnBreakBlock = {
1312
1344
  /** Positioning for anchored images (offsets in CSS px). */
1313
1345
  export type ImageAnchor = {
1314
1346
  isAnchored?: boolean;
1347
+ /** Keep the anchored object inside its table cell and resize the cell as needed. */
1348
+ layoutInCell?: boolean;
1315
1349
  hRelativeFrom?: 'column' | 'page' | 'margin';
1316
1350
  vRelativeFrom?: 'paragraph' | 'page' | 'margin';
1317
1351
  alignH?: 'left' | 'center' | 'right';
@@ -1418,7 +1452,7 @@ export type ExclusionZone = {
1418
1452
  left: number;
1419
1453
  right: number;
1420
1454
  };
1421
- wrapMode: 'left' | 'right' | 'both' | 'none' | 'largest';
1455
+ wrapMode: 'left' | 'right' | 'both' | 'none' | 'largest' | 'topBottom';
1422
1456
  polygon?: number[][];
1423
1457
  };
1424
1458
  export type ParagraphSpacing = {
@@ -1930,6 +1964,18 @@ export type Line = {
1930
1964
  */
1931
1965
  tabWidths?: Record<number, number>;
1932
1966
  };
1967
+ /**
1968
+ * One contiguous horizontal region available to a measured paragraph line.
1969
+ *
1970
+ * Coordinates are relative to the paragraph fragment's content origin. A line
1971
+ * can expose multiple regions when text wraps on both sides of a floating
1972
+ * object. Measuring owns the line breaks inside these regions; layout owns
1973
+ * deriving the regions from page/column float geometry.
1974
+ */
1975
+ export type ParagraphLineRegion = {
1976
+ offsetX: number;
1977
+ width: number;
1978
+ };
1933
1979
  export type LineSegment = {
1934
1980
  runIndex: number;
1935
1981
  fromChar: number;
@@ -1,4 +1,4 @@
1
- import { FlowBlock, HeaderFooterLayout, Measure, PageNumberChapterSeparator, PageNumberFormat, ParagraphBlock, ParagraphMeasure } from '../../contracts/src/index.js';
1
+ import { FlowBlock, HeaderFooterLayout, Measure, PageNumberChapterSeparator, PageNumberFormat, ParagraphBlock, ParagraphLineRegion, ParagraphMeasure } from '../../contracts/src/index.js';
2
2
  import { HeaderFooterConstraints, LayoutExecutionCheckpoint, LayoutExecutionControl } from '../../layout-engine/src/index.js';
3
3
  import { MeasureCache } from './cache.js';
4
4
  import { ResolveHeaderFooterTokensOptions } from './resolveHeaderFooterTokens.js';
@@ -127,4 +127,4 @@ export declare function invalidateHeaderFooterMeasureCache(blockIds: string[]):
127
127
  * @param pageResolver - Callback to resolve display page info for a physical page number
128
128
  * @returns Batch result with layouts, blocks, and measures for each variant
129
129
  */
130
- export declare function layoutHeaderFooterWithCache(sections: HeaderFooterBatch, constraints: HeaderFooterConstraints, measureBlock: MeasureResolver, cache?: HeaderFooterLayoutCache, totalPages?: number, pageResolver?: PageResolver, kind?: 'header' | 'footer', fontSignature?: string, remeasureParagraph?: (block: ParagraphBlock, maxWidth: number, firstLineIndent?: number) => ParagraphMeasure, options?: ResolveHeaderFooterTokensOptions, execution?: HeaderFooterLayoutExecution): Promise<HeaderFooterBatchResult>;
130
+ export declare function layoutHeaderFooterWithCache(sections: HeaderFooterBatch, constraints: HeaderFooterConstraints, measureBlock: MeasureResolver, cache?: HeaderFooterLayoutCache, totalPages?: number, pageResolver?: PageResolver, kind?: 'header' | 'footer', fontSignature?: string, remeasureParagraph?: (block: ParagraphBlock, maxWidth: number, firstLineIndent?: number, lineRegions?: readonly (readonly ParagraphLineRegion[])[]) => ParagraphMeasure, options?: ResolveHeaderFooterTokensOptions, execution?: HeaderFooterLayoutExecution): Promise<HeaderFooterBatchResult>;
@@ -1,4 +1,4 @@
1
- import { ParagraphBlock, ParagraphMeasure } from '../../contracts/src/index.js';
1
+ import { ParagraphBlock, ParagraphMeasure, ParagraphLineRegion } from '../../contracts/src/index.js';
2
2
  /** Drop cached text widths and the canvas context. Call when registered font faces may have changed. */
3
3
  export declare function clearRemeasureTextCaches(): void;
4
4
  /**
@@ -72,4 +72,4 @@ export declare function clearRemeasureTextCaches(): void;
72
72
  * // First line has only 170px available (200 - 30), subsequent lines have full 200px
73
73
  * ```
74
74
  */
75
- export declare function remeasureParagraph(block: ParagraphBlock, maxWidth: number, firstLineIndent?: number): ParagraphMeasure;
75
+ export declare function remeasureParagraph(block: ParagraphBlock, maxWidth: number, firstLineIndent?: number, lineRegions?: readonly (readonly ParagraphLineRegion[])[]): ParagraphMeasure;
@@ -31,6 +31,19 @@ export type FloatingObjectManager = {
31
31
  width: number;
32
32
  offsetX: number;
33
33
  };
34
+ /**
35
+ * Compute every contiguous horizontal region available to a line.
36
+ * Unlike computeAvailableWidth, this preserves both sides of a centered
37
+ * `wrapText="bothSides"` object instead of collapsing them to one side.
38
+ */
39
+ computeAvailableRegions(lineY: number, lineHeight: number, baseWidth: number, columnIndex: number, pageNumber: number): Array<{
40
+ offsetX: number;
41
+ width: number;
42
+ }>;
43
+ /**
44
+ * Return the first Y coordinate below every overlapping TopAndBottom float.
45
+ */
46
+ computeVerticalClearance(lineY: number, lineHeight: number, columnIndex: number, pageNumber: number): number | null;
34
47
  /**
35
48
  * Get all floating images for a page (for debugging/painting).
36
49
  */
@@ -1,4 +1,4 @@
1
- import { ColumnLayout, FlowBlock, HeaderFooterLayout, Layout, Measure, Page, ParagraphBlock, ParagraphMeasure, SectionMetadata, FlowMode, DocumentBackground } from '../../contracts/src/index.js';
1
+ import { ColumnLayout, FlowBlock, HeaderFooterLayout, Layout, Measure, Page, ParagraphBlock, ParagraphMeasure, SectionMetadata, FlowMode, DocumentBackground, ParagraphLineRegion } from '../../contracts/src/index.js';
2
2
  import { PageState, ConstraintBoundary } from './paginator.js';
3
3
  import { LayoutExecutionControl } from './execution.js';
4
4
  type PageSize = {
@@ -31,7 +31,7 @@ export type LayoutOptions = {
31
31
  marginTop?: number;
32
32
  marginBottom?: number;
33
33
  };
34
- remeasureParagraph?: (block: ParagraphBlock, maxWidth: number, firstLineIndent?: number) => ParagraphMeasure;
34
+ remeasureParagraph?: (block: ParagraphBlock, maxWidth: number, firstLineIndent?: number, lineRegions?: readonly (readonly ParagraphLineRegion[])[]) => ParagraphMeasure;
35
35
  /** @internal Positioned paragraph frames that render without advancing the story cursor. */
36
36
  nonFlowPositionedParagraphFrameIds?: ReadonlySet<string>;
37
37
  sectionMetadata?: SectionMetadata[];
@@ -337,8 +337,8 @@ export declare function layoutDocumentRange(input: LayoutRangeInput): LayoutRang
337
337
  * Returns separate measurement bounds (for pagination) and render bounds
338
338
  * (for overlay shift). See the Coordinate Contract in the fix plan for details.
339
339
  */
340
- export declare function layoutHeaderFooter(blocks: FlowBlock[], measures: Measure[], constraints: HeaderFooterConstraints, kind?: 'header' | 'footer', remeasureParagraph?: (block: ParagraphBlock, maxWidth: number, firstLineIndent?: number) => ParagraphMeasure): HeaderFooterLayout;
341
- export declare function layoutHeaderFooterCooperatively(blocks: FlowBlock[], measures: Measure[], constraints: HeaderFooterConstraints, kind?: 'header' | 'footer', remeasureParagraph?: (block: ParagraphBlock, maxWidth: number, firstLineIndent?: number) => ParagraphMeasure, execution?: LayoutExecutionControl): Promise<HeaderFooterLayout>;
340
+ export declare function layoutHeaderFooter(blocks: FlowBlock[], measures: Measure[], constraints: HeaderFooterConstraints, kind?: 'header' | 'footer', remeasureParagraph?: LayoutOptions['remeasureParagraph']): HeaderFooterLayout;
341
+ export declare function layoutHeaderFooterCooperatively(blocks: FlowBlock[], measures: Measure[], constraints: HeaderFooterConstraints, kind?: 'header' | 'footer', remeasureParagraph?: LayoutOptions['remeasureParagraph'], execution?: LayoutExecutionControl): Promise<HeaderFooterLayout>;
342
342
  export { buildAnchorMap, resolvePageRefTokens, getTocBlocksForRemeasurement } from './resolvePageRefs.js';
343
343
  export { buildChapterContextByPage, buildChapterContextByPageCooperatively, computeDisplayPageNumber, computeDisplayPageNumberCooperatively, formatPageNumber, formatPageNumberFieldValue, formatSectionPageNumberText, normalizeChapterMarkerText, } from './pageNumbering.js';
344
344
  export type { ChapterPageInfo, DisplayPageInfo, PageNumberFormat } from './pageNumbering.js';
@@ -1,6 +1,6 @@
1
1
  import { FloatingObjectManager } from './floating-objects.js';
2
2
  import { PageState } from './paginator.js';
3
- import { PageMargins, ParagraphBlock, ParagraphMeasure, ImageBlock, ImageMeasure, DrawingBlock, DrawingMeasure } from '../../contracts/src/index.js';
3
+ import { PageMargins, ParagraphBlock, ParagraphMeasure, ImageBlock, ImageMeasure, DrawingBlock, DrawingMeasure, ParagraphLineRegion } from '../../contracts/src/index.js';
4
4
  import { AnchoredTable } from './anchors.js';
5
5
  /**
6
6
  * SD-2656: ordered footnote anchor entry. The body slicer reads the candidate
@@ -21,7 +21,7 @@ export type ParagraphLayoutContext = {
21
21
  advanceColumn: (state: PageState) => PageState;
22
22
  columnX: (state: PageState, columnIndex?: number) => number;
23
23
  floatManager: FloatingObjectManager;
24
- remeasureParagraph?: (block: ParagraphBlock, maxWidth: number, firstLineIndent?: number) => ParagraphMeasure;
24
+ remeasureParagraph?: (block: ParagraphBlock, maxWidth: number, firstLineIndent?: number, lineRegions?: readonly (readonly ParagraphLineRegion[])[]) => ParagraphMeasure;
25
25
  /**
26
26
  * Override the paragraph's spacing-after value. Used when contextual spacing
27
27
  * should suppress spacing between this paragraph and the next (same-style) paragraph.
@@ -79,32 +79,9 @@ export declare const borderValueToSpec: (value?: TableBorderValue | null) => Bor
79
79
  * ```
80
80
  */
81
81
  export declare const resolveTableBorderValue: (explicit: TableBorderValue | undefined | null, fallback?: TableBorderValue | undefined | null) => BorderSpec | undefined;
82
- export declare const isPresentBorder: (b?: BorderSpec) => b is BorderSpec;
83
- /**
84
- * True when a border is EXPLICITLY set to none/nil (`w:val="nil"`/`"none"`), as opposed to
85
- * simply unset/absent. The distinction matters for shared interior edges (§17.4.66): an
86
- * explicit none on BOTH adjacent cells suppresses the divider, while an unset side inherits
87
- * the table's insideH/insideV. Accepts either a CellBorders BorderSpec (`{style:'none'}`) or
88
- * a TableBorderValue (`{none:true}`).
89
- */
90
- export declare const isExplicitNoneBorder: (b?: unknown) => boolean;
91
- /**
92
- * OOXML cell-border conflict resolution (ECMA-376 §17.4.66).
93
- *
94
- * With zero cell spacing, two cells sharing an edge each specify a border; the spec
95
- * collapses them to a SINGLE displayed border:
96
- * 1. If either side is nil/none/absent, the opposing (present) border is displayed.
97
- * 2. Otherwise the border with greater weight wins, where
98
- * weight = (#lines in the style) × (style number).
99
- * 3. Equal weight → the style higher on the precedence list (single first) wins.
100
- * 4. Identical style → the color with the smaller brightness (R+B+2G, then B+2G, then
101
- * G) wins; finally the first border (reading order) wins.
102
- *
103
- * @param a - One side's border (the owning cell's, e.g. the lower/right cell)
104
- * @param b - The opposing side's border (e.g. the upper/left neighbor)
105
- * @returns The single BorderSpec to display, or undefined if neither is present.
106
- */
107
- export declare const resolveBorderConflict: (a?: BorderSpec, b?: BorderSpec) => BorderSpec | undefined;
82
+ export declare const isPresentBorder: (border?: BorderSpec) => border is BorderSpec;
83
+ export declare const isExplicitNoneBorder: (border?: unknown) => boolean;
84
+ export declare const resolveBorderConflict: (first?: BorderSpec, second?: BorderSpec) => BorderSpec | undefined;
108
85
  /**
109
86
  * Creates a border overlay element for a table fragment.
110
87
  *
package/dist/superdoc.cjs CHANGED
@@ -43260,7 +43260,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
43260
43260
  this.config.colors = shuffleArray(this.config.colors);
43261
43261
  this.userColorMap = /* @__PURE__ */ new Map();
43262
43262
  this.colorIndex = 0;
43263
- this.version = "2.4.0-next.41";
43263
+ this.version = "2.4.0-next.43";
43264
43264
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
43265
43265
  this.superdocId = config.superdocId || require_uuid.v4();
43266
43266
  this.colors = this.config.colors ?? [];
@@ -43193,7 +43193,7 @@ var SuperDoc = class extends import_eventemitter3.default {
43193
43193
  this.config.colors = shuffleArray(this.config.colors);
43194
43194
  this.userColorMap = /* @__PURE__ */ new Map();
43195
43195
  this.colorIndex = 0;
43196
- this.version = "2.4.0-next.41";
43196
+ this.version = "2.4.0-next.43";
43197
43197
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
43198
43198
  this.superdocId = config.superdocId || v4();
43199
43199
  this.colors = this.config.colors ?? [];