@stll/folio-core 0.30.0 → 0.31.1

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.
@@ -16,18 +16,28 @@ type BilingualRow = ({
16
16
  rowId: string;
17
17
  } & BilingualParagraphRef) | {
18
18
  kind: "table";
19
+ layout: "inline";
19
20
  rowId: string;
20
21
  /**
21
22
  * Every paragraph inside the table, in document order. The table is not
22
23
  * copied, so these are the paragraphs to translate in place.
23
24
  */
24
25
  paragraphs: BilingualTableParagraphRef[];
26
+ } | {
27
+ kind: "table";
28
+ layout: "stacked";
29
+ /** Equals the first target paragraph id. */
30
+ rowId: string;
31
+ /** Source/target paragraph pairs in table document order. */
32
+ paragraphs: BilingualParagraphRef[];
25
33
  };
26
34
  type BilingualTableParagraphRef = {
27
35
  paraId: string | undefined;
28
36
  sourceText: string;
29
37
  };
30
38
  type BilingualBorders = "none" | "grid";
39
+ declare const BILINGUAL_TABLE_LAYOUTS: readonly ["inline", "stacked"];
40
+ type BilingualTableLayout = (typeof BILINGUAL_TABLE_LAYOUTS)[number];
31
41
  type CreateBilingualDocumentOptions = {
32
42
  /**
33
43
  * Suffix for cloned style ids and names (for example `"en"` turns
@@ -37,6 +47,13 @@ type CreateBilingualDocumentOptions = {
37
47
  targetStyleSuffix: string;
38
48
  /** Table borders; legal practice is usually `"none"`. Default `"none"`. */
39
49
  borders?: BilingualBorders;
50
+ /**
51
+ * Layout for source tables. `"inline"` keeps one full-width table whose
52
+ * paragraphs are translated in place. `"stacked"` keeps the source table
53
+ * and adds an independently addressable target copy below it. Default
54
+ * `"inline"`.
55
+ */
56
+ tableLayout?: BilingualTableLayout;
40
57
  /**
41
58
  * Paragraph handles exposed by Folio's canonical AI-edit snapshot for the
42
59
  * source DOCX. Only these paragraphs may become translation rows.
@@ -52,7 +69,7 @@ type CreateBilingualDocumentResult = {
52
69
  declare const InvalidBilingualDocumentOptionsError_base: import("better-result").TaggedErrorClass<"InvalidBilingualDocumentOptionsError">;
53
70
  declare class InvalidBilingualDocumentOptionsError extends InvalidBilingualDocumentOptionsError_base<{
54
71
  message: string;
55
- option: "targetStyleSuffix";
72
+ option: "tableLayout" | "targetStyleSuffix";
56
73
  }> {}
57
74
  declare function createBilingualDocument(source: document_d_exports.Document, options: CreateBilingualDocumentOptions): CreateBilingualDocumentResult;
58
75
  /**
@@ -60,8 +77,8 @@ declare function createBilingualDocument(source: document_d_exports.Document, op
60
77
  * {@link createBilingualDocument}. A dedicated table-style discriminator keeps
61
78
  * ordinary two-column source tables from being mistaken for bilingual output;
62
79
  * the expected row structure is validated as a second check. Rows are returned
63
- * in document order; the right paragraph's `paraId` is the row handle.
80
+ * in document order.
64
81
  */
65
82
  declare function readBilingualDocument(document: document_d_exports.Document, editableParagraphIds: ReadonlySet<string>): BilingualRow[];
66
83
  //#endregion
67
- export { BilingualBorders, BilingualParagraphRef, BilingualRow, BilingualRowKind, BilingualTableParagraphRef, CreateBilingualDocumentOptions, CreateBilingualDocumentResult, InvalidBilingualDocumentOptionsError, createBilingualDocument, readBilingualDocument };
84
+ export { BILINGUAL_TABLE_LAYOUTS, BilingualBorders, BilingualParagraphRef, BilingualRow, BilingualRowKind, BilingualTableLayout, BilingualTableParagraphRef, CreateBilingualDocumentOptions, CreateBilingualDocumentResult, InvalidBilingualDocumentOptionsError, createBilingualDocument, readBilingualDocument };
@@ -17,13 +17,15 @@ import { TaggedError } from "better-result";
17
17
  *
18
18
  * Section breaks cannot live inside a table cell, so the body is split at
19
19
  * paragraphs carrying `sectionProperties`: each section becomes its own table
20
- * and the break paragraph stays between the tables. A source table (parties,
21
- * signature block) is kept once, in a row spanning both columns: it is signed
22
- * and read once, and its labels are translated inline rather than duplicated.
20
+ * and the break paragraph stays between the tables. Source tables (parties,
21
+ * signature blocks) can either span both columns for inline translation or be
22
+ * followed by a full-width target copy, depending on `tableLayout`.
23
23
  * Structural-only paragraphs are also kept once between tables; they have no
24
24
  * independently editable text for a translation row to address.
25
25
  */
26
+ const BILINGUAL_TABLE_LAYOUTS = ["inline", "stacked"];
26
27
  const STYLE_SUFFIX_PATTERN = /^[A-Za-z0-9-]+$/u;
28
+ const DEFAULT_TABLE_LAYOUT = BILINGUAL_TABLE_LAYOUTS[0];
27
29
  var InvalidBilingualDocumentOptionsError = class extends TaggedError("InvalidBilingualDocumentOptionsError") {};
28
30
  var UneditableBilingualManifestError = class extends TaggedError("UneditableBilingualManifestError") {};
29
31
  const FULL_WIDTH_PCT = 5e3;
@@ -56,12 +58,18 @@ const TABLE_BORDERS = {
56
58
  insideV: GRID_BORDER
57
59
  }
58
60
  };
61
+ const isBilingualTableLayout = (value) => typeof value === "string" && BILINGUAL_TABLE_LAYOUTS.some((layout) => layout === value);
59
62
  function createBilingualDocument(source, options) {
60
63
  if (!STYLE_SUFFIX_PATTERN.test(options.targetStyleSuffix)) throw new InvalidBilingualDocumentOptionsError({
61
64
  message: `targetStyleSuffix must match ${STYLE_SUFFIX_PATTERN}; received ${JSON.stringify(options.targetStyleSuffix)}`,
62
65
  option: "targetStyleSuffix"
63
66
  });
67
+ if (options.tableLayout !== void 0 && !isBilingualTableLayout(options.tableLayout)) throw new InvalidBilingualDocumentOptionsError({
68
+ message: `tableLayout must be one of ${BILINGUAL_TABLE_LAYOUTS.join(", ")}; received ${JSON.stringify(options.tableLayout)}`,
69
+ option: "tableLayout"
70
+ });
64
71
  const borders = options.borders ?? "none";
72
+ const tableLayout = options.tableLayout ?? DEFAULT_TABLE_LAYOUT;
65
73
  const warnings = [];
66
74
  const styles = source.package.styles;
67
75
  const numbering = source.package.numbering;
@@ -128,12 +136,36 @@ function createBilingualDocument(source, options) {
128
136
  content.push(block);
129
137
  continue;
130
138
  }
131
- rows.push({
132
- kind: "table",
133
- rowId: paragraphs.at(0)?.paraId ?? tableRowHandle(rows.length),
134
- paragraphs
135
- });
136
- sectionRows.push(buildSpanningRow(block));
139
+ if (tableLayout === "inline") {
140
+ rows.push({
141
+ kind: "table",
142
+ layout: "inline",
143
+ rowId: paragraphs.at(0)?.paraId ?? tableRowHandle(rows.length),
144
+ paragraphs
145
+ });
146
+ sectionRows.push(buildInlineTableRow(block));
147
+ continue;
148
+ }
149
+ if (tableLayout === "stacked") {
150
+ const target = cloneTableForTarget({
151
+ table: block,
152
+ editableParagraphIds: options.editableParagraphIds,
153
+ paraIds,
154
+ styleCloner,
155
+ cloner
156
+ });
157
+ rows.push({
158
+ kind: "table",
159
+ layout: "stacked",
160
+ rowId: target.paragraphs.at(0)?.targetParaId ?? tableRowHandle(rows.length),
161
+ paragraphs: target.paragraphs
162
+ });
163
+ sectionRows.push(buildStackedTableRow({
164
+ source: block,
165
+ target: target.table
166
+ }));
167
+ continue;
168
+ }
137
169
  }
138
170
  flushSection();
139
171
  return {
@@ -367,6 +399,33 @@ const collectTableParagraphs = (table) => {
367
399
  else out.push(...collectTableParagraphs(item));
368
400
  return out;
369
401
  };
402
+ const cloneTableForTarget = ({ table, editableParagraphIds, paraIds, styleCloner, cloner }) => {
403
+ const paragraphs = [];
404
+ const cloneTable = (source) => ({
405
+ ...structuredClone(source),
406
+ rows: source.rows.map((row) => ({
407
+ ...structuredClone(row),
408
+ cells: row.cells.map((cell) => ({
409
+ ...structuredClone(cell),
410
+ content: cell.content.map((item) => {
411
+ if (item.type === "table") return cloneTable(item);
412
+ const targetParaId = paraIds.mint(item.paraId);
413
+ const copy = cloneParagraphForTarget(item, targetParaId, styleCloner, cloner);
414
+ if (item.paraId !== void 0 && editableParagraphIds.has(item.paraId)) paragraphs.push({
415
+ sourceParaId: item.paraId,
416
+ targetParaId,
417
+ sourceText: getParagraphText(item)
418
+ });
419
+ return copy;
420
+ })
421
+ }))
422
+ }))
423
+ });
424
+ return {
425
+ table: cloneTable(table),
426
+ paragraphs
427
+ };
428
+ };
370
429
  const buildRow = (left, right, styleById, textWidth) => {
371
430
  const columnWidth = Math.floor(textWidth / 2);
372
431
  const geometry = resolveHorizontalParagraphGeometry(left, styleById);
@@ -411,16 +470,21 @@ const projectParagraphIntoColumn = (paragraph, geometry, sourceWidth, columnWidt
411
470
  const maxSideIndent = Math.max(0, columnWidth - MIN_COLUMN_TEXT_WIDTH_TWIPS);
412
471
  let indentLeft = projectSideIndent(geometry.indentLeft, scale, maxSideIndent);
413
472
  let indentRight = projectSideIndent(geometry.indentRight, scale, maxSideIndent);
414
- if (indentLeft + indentRight - maxSideIndent > 0) {
415
- const total = indentLeft + indentRight;
416
- indentLeft = Math.round(indentLeft / total * maxSideIndent);
473
+ const indentFirstLine = geometry.indentFirstLine === void 0 ? void 0 : Math.max(-maxSideIndent, Math.round(geometry.indentFirstLine * scale));
474
+ const minimumLeftIndent = Math.min(maxSideIndent, Math.max(0, -(indentFirstLine ?? 0)));
475
+ indentLeft = Math.max(indentLeft, minimumLeftIndent);
476
+ const flexibleLeft = indentLeft - minimumLeftIndent;
477
+ const flexibleTotal = flexibleLeft + indentRight;
478
+ const flexibleMaximum = maxSideIndent - minimumLeftIndent;
479
+ if (flexibleTotal > flexibleMaximum) {
480
+ indentLeft = minimumLeftIndent + Math.round(flexibleLeft / flexibleTotal * flexibleMaximum);
417
481
  indentRight = maxSideIndent - indentLeft;
418
482
  }
419
483
  const formatting = {
420
484
  ...paragraph.formatting,
421
- ...geometry.indentLeft !== void 0 && { indentLeft },
485
+ ...(geometry.indentLeft !== void 0 || minimumLeftIndent > 0) && { indentLeft },
422
486
  ...geometry.indentRight !== void 0 && { indentRight },
423
- ...geometry.indentFirstLine !== void 0 && { indentFirstLine: Math.round(geometry.indentFirstLine * scale) },
487
+ ...indentFirstLine !== void 0 && { indentFirstLine },
424
488
  ...geometry.hangingIndent !== void 0 && { hangingIndent: geometry.hangingIndent },
425
489
  ...geometry.tabs !== void 0 && { tabs: geometry.tabs.map((tab) => ({
426
490
  ...tab,
@@ -445,7 +509,7 @@ const buildCell = (paragraph) => ({
445
509
  content: [paragraph]
446
510
  });
447
511
  /** A source table kept once, across both columns. */
448
- const buildSpanningRow = (table) => ({
512
+ const buildInlineTableRow = (table) => ({
449
513
  type: "tableRow",
450
514
  formatting: { cantSplit: true },
451
515
  cells: [{
@@ -464,6 +528,33 @@ const buildSpanningRow = (table) => ({
464
528
  }]
465
529
  }]
466
530
  });
531
+ const buildStackedTableRow = ({ source, target }) => ({
532
+ type: "tableRow",
533
+ formatting: { cantSplit: false },
534
+ cells: [{
535
+ type: "tableCell",
536
+ formatting: {
537
+ width: {
538
+ value: FULL_WIDTH_PCT,
539
+ type: "pct"
540
+ },
541
+ gridSpan: 2,
542
+ verticalAlign: "top"
543
+ },
544
+ content: [
545
+ source,
546
+ {
547
+ type: "paragraph",
548
+ content: []
549
+ },
550
+ target,
551
+ {
552
+ type: "paragraph",
553
+ content: []
554
+ }
555
+ ]
556
+ }]
557
+ });
467
558
  const buildTable = (rows, borders, textWidth) => ({
468
559
  type: "table",
469
560
  formatting: {
@@ -537,7 +628,7 @@ const createParaIdMinter = (taken) => {
537
628
  * {@link createBilingualDocument}. A dedicated table-style discriminator keeps
538
629
  * ordinary two-column source tables from being mistaken for bilingual output;
539
630
  * the expected row structure is validated as a second check. Rows are returned
540
- * in document order; the right paragraph's `paraId` is the row handle.
631
+ * in document order.
541
632
  */
542
633
  function readBilingualDocument(document, editableParagraphIds) {
543
634
  const styleById = new Map((document.package.styles?.styles ?? []).map((style) => [style.styleId, style]));
@@ -549,12 +640,54 @@ function readBilingualDocument(document, editableParagraphIds) {
549
640
  const [left, right] = row.cells;
550
641
  if (!left) continue;
551
642
  if (!right) {
552
- const paragraphs = left.content.filter((item) => item.type === "table").flatMap(collectTableParagraphs).filter((paragraph) => paragraph.paraId !== void 0 && editableParagraphIds.has(paragraph.paraId)).map((paragraph) => ({
643
+ const nestedTables = left.content.filter((item) => item.type === "table");
644
+ const sourceTable = nestedTables.at(0);
645
+ if (!sourceTable) {
646
+ missingHandleCount += 1;
647
+ continue;
648
+ }
649
+ if (nestedTables.length === 2) {
650
+ const targetTable = nestedTables.at(1);
651
+ if (!targetTable) continue;
652
+ const sourceParagraphs = collectTableParagraphs(sourceTable);
653
+ const targetParagraphs = collectTableParagraphs(targetTable);
654
+ if (sourceParagraphs.length !== targetParagraphs.length) {
655
+ missingHandleCount += 1;
656
+ continue;
657
+ }
658
+ const paragraphs = [];
659
+ for (const [index, source] of sourceParagraphs.entries()) {
660
+ if (source.paraId === void 0 || !editableParagraphIds.has(source.paraId)) continue;
661
+ const target = targetParagraphs.at(index);
662
+ if (target?.paraId === void 0 || target.paraId === source.paraId || !editableParagraphIds.has(target.paraId)) {
663
+ missingHandleCount += 1;
664
+ continue;
665
+ }
666
+ paragraphs.push({
667
+ sourceParaId: source.paraId,
668
+ targetParaId: target.paraId,
669
+ sourceText: getParagraphText(source)
670
+ });
671
+ }
672
+ rows.push({
673
+ kind: "table",
674
+ layout: "stacked",
675
+ rowId: paragraphs.at(0)?.targetParaId ?? tableRowHandle(rows.length),
676
+ paragraphs
677
+ });
678
+ continue;
679
+ }
680
+ if (nestedTables.length !== 1) {
681
+ missingHandleCount += 1;
682
+ continue;
683
+ }
684
+ const paragraphs = collectTableParagraphs(sourceTable).filter((paragraph) => paragraph.paraId !== void 0 && editableParagraphIds.has(paragraph.paraId)).map((paragraph) => ({
553
685
  paraId: paragraph.paraId,
554
686
  sourceText: getParagraphText(paragraph)
555
687
  }));
556
688
  rows.push({
557
689
  kind: "table",
690
+ layout: "inline",
558
691
  rowId: paragraphs.at(0)?.paraId ?? tableRowHandle(rows.length),
559
692
  paragraphs
560
693
  });
@@ -582,26 +715,24 @@ function readBilingualDocument(document, editableParagraphIds) {
582
715
  }
583
716
  }
584
717
  if (missingHandleCount > 0) throw new UneditableBilingualManifestError({
585
- message: "Bilingual manifest contains handles absent from the Folio AI-edit snapshot.",
718
+ message: "Bilingual manifest structure or handles do not match the Folio AI-edit snapshot.",
586
719
  missingHandleCount
587
720
  });
588
721
  return rows;
589
722
  }
590
723
  const isBilingualTable = (table) => {
591
724
  if (table.formatting?.styleId !== BILINGUAL_TABLE_STYLE_ID) return false;
592
- let pairs = 0;
593
725
  for (const row of table.rows) {
594
726
  const cells = row.cells;
595
727
  if (cells.length === 2) {
596
728
  if (!cells.every((cell) => cell.content.length === 1 && cell.content[0]?.type === "paragraph")) return false;
597
- pairs += 1;
598
729
  continue;
599
730
  }
600
731
  if (cells.length === 1 && cells[0]?.formatting?.gridSpan === 2) continue;
601
732
  return false;
602
733
  }
603
- return pairs > 0;
734
+ return table.rows.length > 0;
604
735
  };
605
736
  const isParagraphWithId = (value) => "type" in value && value.type === "paragraph" && "paraId" in value && typeof value.paraId === "string";
606
737
  //#endregion
607
- export { InvalidBilingualDocumentOptionsError, createBilingualDocument, readBilingualDocument };
738
+ export { BILINGUAL_TABLE_LAYOUTS, InvalidBilingualDocumentOptionsError, createBilingualDocument, readBilingualDocument };
@@ -61,10 +61,11 @@ function frameWrapType(frame) {
61
61
  function toFrameTextBox(content, frame, nextBlockId) {
62
62
  const first = content.at(0);
63
63
  const last = content.at(-1);
64
+ const hasAuthoredWidth = frame.width !== void 0;
64
65
  const textBox = {
65
66
  kind: "textBox",
66
67
  id: nextBlockId(),
67
- width: frame.width ?? 200,
68
+ width: frame.width ?? 0,
68
69
  margins: {
69
70
  top: 0,
70
71
  right: 0,
@@ -82,6 +83,11 @@ function toFrameTextBox(content, frame, nextBlockId) {
82
83
  ...first?.pmStart !== void 0 ? { pmStart: first.pmStart } : {},
83
84
  ...last?.pmEnd !== void 0 ? { pmEnd: last.pmEnd } : {}
84
85
  };
86
+ if (!hasAuthoredWidth) {
87
+ textBox.widthMode = "intrinsic";
88
+ textBox.autoFit = "shape";
89
+ textBox.textWrap = "none";
90
+ }
85
91
  if (frame.height !== void 0) textBox.height = frame.height;
86
92
  const position = framePosition(frame);
87
93
  if (position !== void 0) textBox.position = position;
@@ -769,6 +769,8 @@ type TextBoxBlock = {
769
769
  id: BlockId;
770
770
  /** Width in pixels */
771
771
  width: number;
772
+ /** Whether width is authored or derived from the live rendered content. */
773
+ widthMode?: "intrinsic";
772
774
  /** Height in pixels (may be auto-calculated) */
773
775
  height?: number;
774
776
  /** Text fitting behavior */
@@ -177,6 +177,12 @@ type HeaderFooterLayoutInfo = {
177
177
  left: number;
178
178
  };
179
179
  };
180
+ type HeaderFooterHorizontalPosition = {
181
+ relativeTo?: string;
182
+ posOffset?: number;
183
+ align?: string;
184
+ alignment?: string;
185
+ };
180
186
  /**
181
187
  * Resolve the CSS `left` (px string) for an anchored object (image or text box)
182
188
  * in a header/footer, honoring `wp:positionH` (relativeTo page/margin, align
@@ -184,12 +190,11 @@ type HeaderFooterLayoutInfo = {
184
190
  * a page-centered banner in the header lands centered like Word, not pinned to
185
191
  * the left. Ported from eigenpal/docx-editor#700.
186
192
  */
187
- declare function resolveHeaderFooterFloatLeft(width: number, h: {
188
- relativeTo?: string;
189
- posOffset?: number;
190
- align?: string;
191
- alignment?: string;
192
- } | undefined, layout: HeaderFooterLayoutInfo): string;
193
+ declare function resolveHeaderFooterFloatLeft(width: number, h: HeaderFooterHorizontalPosition | undefined, layout: HeaderFooterLayoutInfo): string;
194
+ declare function resolveHeaderFooterIntrinsicFrameHorizontalPosition(h: HeaderFooterHorizontalPosition | undefined, layout: HeaderFooterLayoutInfo): {
195
+ left: string;
196
+ transform?: string;
197
+ };
193
198
  /**
194
199
  * Resolve the on-page coordinates of an anchored floating image.
195
200
  *
@@ -297,4 +302,4 @@ declare function findPageShellForPmPos(container: HTMLElement, pmPos: number): {
297
302
  isExact: boolean;
298
303
  } | null;
299
304
  //#endregion
300
- export { type AnchoredImagePosition, FootnoteRenderItem, type HeaderFooterContent, HeaderFooterLayoutInfo, PAGE_CLASS_NAMES, PAINTER_PAINTED_EVENT, PageFloatingImage, type PageGeometry, PainterPaintedDetail, type RenderContext, RenderPageOptions, applySectionHeaderFooterOptions, calculateFootnoteAreaRenderHeight, computePageFingerprint, emuToPixels, findPageShellForPmPos, floatingTableReservesBand, getDefaultPageFontFamily, isFloatingImageRun, renderAllPagesNow, renderFloatingImagesLayer, renderFootnoteArea, renderPage, renderPages, resolveAnchoredImagePosition, resolveHeaderFooterFloatLeft };
305
+ export { type AnchoredImagePosition, FootnoteRenderItem, type HeaderFooterContent, HeaderFooterLayoutInfo, PAGE_CLASS_NAMES, PAINTER_PAINTED_EVENT, PageFloatingImage, type PageGeometry, PainterPaintedDetail, type RenderContext, RenderPageOptions, applySectionHeaderFooterOptions, calculateFootnoteAreaRenderHeight, computePageFingerprint, emuToPixels, findPageShellForPmPos, floatingTableReservesBand, getDefaultPageFontFamily, isFloatingImageRun, renderAllPagesNow, renderFloatingImagesLayer, renderFootnoteArea, renderPage, renderPages, resolveAnchoredImagePosition, resolveHeaderFooterFloatLeft, resolveHeaderFooterIntrinsicFrameHorizontalPosition };
@@ -207,6 +207,37 @@ function applyContentAreaStyles(element, page) {
207
207
  function getPositionAlignment(position) {
208
208
  return position?.align ?? position?.alignment;
209
209
  }
210
+ function resolveHeaderFooterHorizontalAnchorPoint(h, layout) {
211
+ if (!h) return {
212
+ left: 0,
213
+ alignment: "left"
214
+ };
215
+ if (h.posOffset !== void 0) {
216
+ const pageOffset = h.relativeTo === "page" ? -layout.flowLeft : 0;
217
+ return {
218
+ left: emuToPixels(h.posOffset) + pageOffset,
219
+ alignment: "left"
220
+ };
221
+ }
222
+ let align = getPositionAlignment(h);
223
+ if (align === "inside") align = "left";
224
+ else if (align === "outside") align = "right";
225
+ const alignment = align === "center" || align === "right" ? align : "left";
226
+ const frameWidth = h.relativeTo === "page" ? layout.pageWidth : layout.contentWidth;
227
+ const frameLeft = h.relativeTo === "page" ? -layout.flowLeft : 0;
228
+ if (alignment === "center") return {
229
+ left: frameLeft + frameWidth / 2,
230
+ alignment
231
+ };
232
+ if (alignment === "right") return {
233
+ left: frameLeft + frameWidth,
234
+ alignment
235
+ };
236
+ return {
237
+ left: frameLeft,
238
+ alignment
239
+ };
240
+ }
210
241
  function resolveHeaderFooterFloatTop(floatImg, layout) {
211
242
  const v = floatImg.position.vertical;
212
243
  if (!v) return floatImg.paragraphY;
@@ -261,20 +292,24 @@ function resolveHeaderFooterFloatingTablePosition(floating, measure, layout, sou
261
292
  * the left. Ported from eigenpal/docx-editor#700.
262
293
  */
263
294
  function resolveHeaderFooterFloatLeft(width, h, layout) {
264
- if (!h) return "0";
265
- let align = getPositionAlignment(h);
266
- if (align === "inside") align = "left";
267
- else if (align === "outside") align = "right";
268
- if (h.relativeTo === "page") {
269
- if (h.posOffset !== void 0) return `${emuToPixels(h.posOffset) - layout.flowLeft}px`;
270
- if (align === "right") return `${layout.pageWidth - width - layout.flowLeft}px`;
271
- if (align === "center") return `${(layout.pageWidth - width) / 2 - layout.flowLeft}px`;
272
- if (align === "left") return `${-layout.flowLeft}px`;
273
- }
274
- if (h.posOffset !== void 0) return `${emuToPixels(h.posOffset)}px`;
275
- if (align === "right") return `${layout.contentWidth - width}px`;
276
- if (align === "center") return `${(layout.contentWidth - width) / 2}px`;
277
- return "0";
295
+ const anchor = resolveHeaderFooterHorizontalAnchorPoint(h, layout);
296
+ let widthFactor = 0;
297
+ if (anchor.alignment === "right") widthFactor = 1;
298
+ else if (anchor.alignment === "center") widthFactor = .5;
299
+ const left = anchor.left - width * widthFactor;
300
+ return left === 0 ? "0" : `${left}px`;
301
+ }
302
+ function resolveHeaderFooterIntrinsicFrameHorizontalPosition(h, layout) {
303
+ const anchor = resolveHeaderFooterHorizontalAnchorPoint(h, layout);
304
+ if (anchor.alignment === "center") return {
305
+ left: `${anchor.left}px`,
306
+ transform: "translateX(-50%)"
307
+ };
308
+ if (anchor.alignment === "right") return {
309
+ left: `${anchor.left}px`,
310
+ transform: "translateX(-100%)"
311
+ };
312
+ return { left: anchor.left === 0 ? "0" : `${anchor.left}px` };
278
313
  }
279
314
  function applyHeaderFooterFloatHorizontalPosition(img, floatImg, layout) {
280
315
  img.style.left = resolveHeaderFooterFloatLeft(floatImg.width, floatImg.position.horizontal, layout);
@@ -500,6 +535,12 @@ function renderHeaderFooterContent(content, context, options, layout) {
500
535
  }, layout) : cursorY;
501
536
  fragEl.style.top = `${textBoxTop}px`;
502
537
  fragEl.style.left = resolveHeaderFooterFloatLeft(measure.width, block.position?.horizontal, layout);
538
+ if (block.widthMode === "intrinsic") {
539
+ const horizontalPosition = resolveHeaderFooterIntrinsicFrameHorizontalPosition(block.position?.horizontal, layout);
540
+ fragEl.style.width = "max-content";
541
+ fragEl.style.left = horizontalPosition.left;
542
+ fragEl.style.transform = horizontalPosition.transform ?? "";
543
+ }
503
544
  if (block.wrapType === "behind") fragEl.style.zIndex = "-1";
504
545
  containerEl.append(fragEl);
505
546
  if (!isPositionedHeaderFooterTextBoxBlock(block)) cursorY += measure.height;
@@ -1823,4 +1864,4 @@ function depopulatePageShell(shell, pageDataMap) {
1823
1864
  }
1824
1865
  }
1825
1866
  //#endregion
1826
- export { PAGE_CLASS_NAMES, PAINTER_PAINTED_EVENT, applySectionHeaderFooterOptions, calculateFootnoteAreaRenderHeight, computePageFingerprint, emuToPixels, findPageShellForPmPos, floatingTableReservesBand, getDefaultPageFontFamily, isFloatingImageRun, renderAllPagesNow, renderFloatingImagesLayer, renderFootnoteArea, renderPage, renderPages, resolveAnchoredImagePosition, resolveHeaderFooterFloatLeft };
1867
+ export { PAGE_CLASS_NAMES, PAINTER_PAINTED_EVENT, applySectionHeaderFooterOptions, calculateFootnoteAreaRenderHeight, computePageFingerprint, emuToPixels, findPageShellForPmPos, floatingTableReservesBand, getDefaultPageFontFamily, isFloatingImageRun, renderAllPagesNow, renderFloatingImagesLayer, renderFootnoteArea, renderPage, renderPages, resolveAnchoredImagePosition, resolveHeaderFooterFloatLeft, resolveHeaderFooterIntrinsicFrameHorizontalPosition };
@@ -12,6 +12,7 @@ import { getAutomaticTextColorForBackground } from "./documentColors.js";
12
12
  import { applyImageVisualAttrs, hasImageCrop, hasImageVisualAttrs } from "./renderImage.js";
13
13
  import { renderParagraphFragment } from "./renderParagraph.js";
14
14
  import { renderTextBoxFragment } from "./renderTextBox.js";
15
+ import { ownedRowBottomBorderOffsets } from "./tableRowPaintGeometry.js";
15
16
  //#region src/layout-painter/renderTable.ts
16
17
  /**
17
18
  * Table Renderer
@@ -36,6 +37,7 @@ const TABLE_CLASS_NAMES = {
36
37
  tableEdgeHandleRight: "layout-table-edge-handle-right"
37
38
  };
38
39
  const CELL_DIAGONAL_BORDER_CLASS = "layout-table-cell-diagonal-border";
40
+ const CELL_BOTTOM_BORDER_CLASS = "layout-table-cell-bottom-border";
39
41
  function renderCellContent({ cell, cellMeasure, context, doc, contentWidthOverride, pageContentPosition }) {
40
42
  const contentEl = doc.createElement("div");
41
43
  contentEl.className = TABLE_CLASS_NAMES.cellContent;
@@ -355,7 +357,7 @@ function renderTableCell({ cell, cellMeasure, x, width, rowHeight, borderFlags,
355
357
  if (cell.borders) {
356
358
  if (borderFlags.drawTop) applyBorder(cellEl, "top", cell.borders.top);
357
359
  applyBorder(cellEl, "right", cell.borders.right);
358
- applyBorder(cellEl, "bottom", cell.borders.bottom);
360
+ if (borderFlags.drawBottom) applyBorder(cellEl, "bottom", cell.borders.bottom);
359
361
  if (borderFlags.drawLeft) applyBorder(cellEl, "left", cell.borders.left);
360
362
  }
361
363
  if (cell.background) {
@@ -444,7 +446,26 @@ function renderTableCell({ cell, cellMeasure, x, width, rowHeight, borderFlags,
444
446
  return cellEl;
445
447
  }
446
448
  const hasVisibleBorder = (border) => border !== void 0 && border.style !== "none" && border.style !== "nil";
447
- function renderTableRow({ row, rowMeasure, rowIndex, y, columnWidths, totalRows, context, doc, rowYPositions, isFirstRowInFragment, bidi = false, columnsPinned = false, cellGrid, cellPlacements, contentClip, pageContentPosition, inlineOffset = 0 }) {
449
+ const isMinimumHeightRow = (row) => row?.height !== void 0 && row.heightRule !== "exact";
450
+ const rowHasVerticalMerge = (row) => row?.cells.some((cell) => (cell.rowSpan ?? 1) > 1) === true;
451
+ const continuationRowBottomBorderOffsets = (fragment, block, measure, cellGrid) => {
452
+ const rowHeights = measure.rows.slice(fragment.fromRow, fragment.toRow).map(({ height }) => height);
453
+ const fragmentHasVerticalMerge = block.rows.slice(fragment.fromRow, fragment.toRow).some((row, fragmentRowIndex) => rowHasVerticalMerge(row) || (cellGrid.occupiedColumnsByRow.get(fragment.fromRow + fragmentRowIndex)?.size ?? 0) > 0);
454
+ if (fragment.continuesFromPrev !== true || fragment.headerRowCount || fragment.topClip !== void 0 || fragment.bottomClip !== void 0 || fragmentHasVerticalMerge) return rowHeights.map(() => 0);
455
+ const snapAfterRow = rowHeights.slice(0, -1).map((_, fragmentRowIndex) => {
456
+ const rowIndex = fragment.fromRow + fragmentRowIndex;
457
+ const row = block.rows[rowIndex];
458
+ const nextRow = block.rows[rowIndex + 1];
459
+ return isMinimumHeightRow(row) && isMinimumHeightRow(nextRow) && !rowHasVerticalMerge(row) && !rowHasVerticalMerge(nextRow) && row?.cells.some((cell) => hasVisibleBorder(cell.borders?.bottom)) === true;
460
+ });
461
+ if (!snapAfterRow.some(Boolean)) return rowHeights.map(() => 0);
462
+ return ownedRowBottomBorderOffsets({
463
+ origin: fragment.y,
464
+ rowHeights,
465
+ snapAfterRow
466
+ });
467
+ };
468
+ function renderTableRow({ row, rowMeasure, rowIndex, y, columnWidths, totalRows, context, doc, rowYPositions, isFirstRowInFragment, bidi = false, columnsPinned = false, cellGrid, cellPlacements, contentClip, pageContentPosition, inlineOffset = 0, bottomBorderOffset = 0 }) {
448
469
  const rowEl = doc.createElement("div");
449
470
  rowEl.className = TABLE_CLASS_NAMES.row;
450
471
  rowEl.style.position = "absolute";
@@ -477,6 +498,7 @@ function renderTableRow({ row, rowMeasure, rowIndex, y, columnWidths, totalRows,
477
498
  const leftCell = getSourceCellAt(cellGrid, rowIndex, bidi ? columnIndex + colSpan : columnIndex - 1);
478
499
  const drawTop = isFirstRow || !hasVisibleBorder(aboveCell?.borders?.bottom);
479
500
  const drawLeft = isFirstCol || !hasVisibleBorder(leftCell?.borders?.right);
501
+ const paintBottomBorderSeparately = bottomBorderOffset > 0 && hasVisibleBorder(cell.borders?.bottom);
480
502
  const cellEl = renderTableCell({
481
503
  cell,
482
504
  cellMeasure,
@@ -485,6 +507,7 @@ function renderTableRow({ row, rowMeasure, rowIndex, y, columnWidths, totalRows,
485
507
  rowHeight: cellHeight,
486
508
  borderFlags: {
487
509
  drawTop,
510
+ drawBottom: !paintBottomBorderSeparately,
488
511
  isLastRow,
489
512
  drawLeft,
490
513
  isLastCol
@@ -503,6 +526,20 @@ function renderTableRow({ row, rowMeasure, rowIndex, y, columnWidths, totalRows,
503
526
  cellEl.dataset["columnIndex"] = String(columnIndex);
504
527
  if (rowSpan > 1) cellEl.dataset["rowSpan"] = String(rowSpan);
505
528
  rowEl.append(cellEl);
529
+ if (paintBottomBorderSeparately) {
530
+ const bottomBorderEl = doc.createElement("div");
531
+ bottomBorderEl.className = CELL_BOTTOM_BORDER_CLASS;
532
+ bottomBorderEl.style.position = "absolute";
533
+ bottomBorderEl.style.left = `${cellLeft}px`;
534
+ bottomBorderEl.style.top = "0";
535
+ bottomBorderEl.style.width = `${width}px`;
536
+ bottomBorderEl.style.height = `${cellHeight + bottomBorderOffset}px`;
537
+ bottomBorderEl.style.boxSizing = "border-box";
538
+ bottomBorderEl.style.pointerEvents = "none";
539
+ bottomBorderEl.style.zIndex = "1";
540
+ applyBorder(bottomBorderEl, "bottom", cell.borders?.bottom);
541
+ rowEl.append(bottomBorderEl);
542
+ }
506
543
  }
507
544
  return rowEl;
508
545
  }
@@ -568,6 +605,7 @@ function renderTableFragment(fragment, block, measure, context, options = {}) {
568
605
  columnWidths: measure.columnWidths,
569
606
  bidi: block.bidi === true
570
607
  });
608
+ const contentRowBottomBorderOffsets = continuationRowBottomBorderOffsets(fragment, block, measure, cellGrid);
571
609
  const headerRowCount = fragment.headerRowCount ?? 0;
572
610
  let y = 0;
573
611
  if (headerRowCount > 0 && fragment.continuesFromPrev) for (let hdrIdx = 0; hdrIdx < headerRowCount; hdrIdx++) {
@@ -646,6 +684,7 @@ function renderTableFragment(fragment, block, measure, context, options = {}) {
646
684
  columnsPinned,
647
685
  cellGrid,
648
686
  cellPlacements,
687
+ bottomBorderOffset: contentRowBottomBorderOffsets[rowIndex - fragment.fromRow] ?? 0,
649
688
  ...contentClip ? { contentClip } : {},
650
689
  ...tablePageContentPosition ? { pageContentPosition: {
651
690
  ...tablePageContentPosition,
@@ -0,0 +1,15 @@
1
+ //#region src/layout-painter/tableRowPaintGeometry.d.ts
2
+ type OwnedRowBottomBorderOffsetsOptions = {
3
+ origin: number;
4
+ rowHeights: readonly number[];
5
+ /** Whether the row ending at this index owns a visible shared bottom edge. */
6
+ snapAfterRow: readonly boolean[];
7
+ };
8
+ /**
9
+ * Offset bottom-owned shared edges onto CSS pixel boundaries. Source row
10
+ * geometry remains unchanged, so content floors and the final band edge stay
11
+ * exact; only the independently painted border moves.
12
+ */
13
+ declare const ownedRowBottomBorderOffsets: ({ origin, rowHeights, snapAfterRow }: OwnedRowBottomBorderOffsetsOptions) => number[];
14
+ //#endregion
15
+ export { ownedRowBottomBorderOffsets };
@@ -0,0 +1,22 @@
1
+ //#region src/layout-painter/tableRowPaintGeometry.ts
2
+ const CSS_PIXEL_ROUNDING_EPSILON = 1e-6;
3
+ /**
4
+ * Offset bottom-owned shared edges onto CSS pixel boundaries. Source row
5
+ * geometry remains unchanged, so content floors and the final band edge stay
6
+ * exact; only the independently painted border moves.
7
+ */
8
+ const ownedRowBottomBorderOffsets = ({ origin, rowHeights, snapAfterRow }) => {
9
+ const offsets = [];
10
+ let boundary = origin;
11
+ for (let rowIndex = 0; rowIndex < rowHeights.length; rowIndex++) {
12
+ boundary += rowHeights[rowIndex] ?? 0;
13
+ if (rowIndex === rowHeights.length - 1 || snapAfterRow[rowIndex] !== true) {
14
+ offsets.push(0);
15
+ continue;
16
+ }
17
+ offsets.push(Math.ceil(boundary - CSS_PIXEL_ROUNDING_EPSILON) - boundary);
18
+ }
19
+ return offsets;
20
+ };
21
+ //#endregion
22
+ export { ownedRowBottomBorderOffsets };
package/dist/server.d.ts CHANGED
@@ -19,7 +19,7 @@ import { EvaluateDocxXmlPatchProposalArgs, FOLIO_DOCX_XML_PATCH_PROPOSAL_DEFAULT
19
19
  import { FOLIO_DOCX_CONFORMANCE_CHECKS, FOLIO_DOCX_CONFORMANCE_ISSUE_CODES, FOLIO_DOCX_CONFORMANCE_PROFILE, FOLIO_DOCX_CONFORMANCE_REPORT_VERSION, FolioDocxConformanceCheck, FolioDocxConformanceCheckId, FolioDocxConformanceCheckStatus, FolioDocxConformanceIssue, FolioDocxConformanceIssueCode, FolioDocxConformanceReport, FolioDocxConformanceStatus, ValidateDocxConformanceOptions, validateDocxConformance } from "./docx/server/validateDocxConformance.js";
20
20
  import { ApplyDocxXmlPatchProposalArgs, FOLIO_DOCX_XML_PATCH_APPLICATION_PROFILE, FOLIO_DOCX_XML_PATCH_APPLICATION_VERSION, FolioDocxXmlPatchApplication, FolioDocxXmlPatchApplicationError, FolioDocxXmlPatchApplicationReceipt, UnsupportedFolioDocxXmlPatchApplicationProfileError, applyDocxXmlPatchProposal } from "./docx/server/applyDocxXmlPatchProposal.js";
21
21
  import { HEADING_LEVELS, HeadingLevel, InvalidFolioReportBuilderOptionsError, TableCellSpec, bookmark, createTableOfContentsField, endnote, heading, hyperlink, pageBreak, paragraph, run, table } from "./docx/server/build.js";
22
- import { BilingualBorders, BilingualParagraphRef, BilingualRow, BilingualRowKind, BilingualTableParagraphRef, CreateBilingualDocumentOptions, CreateBilingualDocumentResult, InvalidBilingualDocumentOptionsError, createBilingualDocument, readBilingualDocument } from "./docx/server/createBilingualDocument.js";
22
+ import { BILINGUAL_TABLE_LAYOUTS, BilingualBorders, BilingualParagraphRef, BilingualRow, BilingualRowKind, BilingualTableLayout, BilingualTableParagraphRef, CreateBilingualDocumentOptions, CreateBilingualDocumentResult, InvalidBilingualDocumentOptionsError, createBilingualDocument, readBilingualDocument } from "./docx/server/createBilingualDocument.js";
23
23
  import { CreateBilingualDocxOptions, CreateBilingualDocxResult, createBilingualDocx, readBilingualDocx } from "./docx/server/createBilingualDocx.js";
24
24
  import { docxToMarkdown } from "./docx/server/docxToMarkdown.js";
25
25
  import { DocxParagraphSource, DocxTableRowKind, DocxTableRowPosition, ExtractedDocxParagraph, ExtractedDocxTableCell, ExtractedDocxTableCellParagraph, ExtractedDocxText, extractDocxText } from "./docx/server/extractDocxText.js";
@@ -27,4 +27,4 @@ import { FOLIO_DOCX_PACKAGE_INSPECTION_DEFAULTS, FOLIO_DOCX_PACKAGE_INSPECTION_E
27
27
  import { FOLIO_YJS_DOCX_MATERIALIZATION_ERROR_CODES, FOLIO_YJS_PROSEMIRROR_FRAGMENT_NAME, FOLIO_YJS_UPDATE_MAX_BYTES, FolioYjsDocxMaterializationError, FolioYjsDocxMaterializationErrorCode, MaterializeYjsDocxOptions, materializeYjsDocx } from "./docx/server/materializeYjsDocx.js";
28
28
  import { GenerateRedlineDocxOptions, GenerateRedlineDocxResult, GenerateRedlineUnprocessedStory, InvalidGenerateRedlineDocxOptionsError, generateRedlineDocx } from "./redline.js";
29
29
  import { FOLIO_VERSION_COMPARISON_PRIVACY_TRANSFORMS, FOLIO_VERSION_COMPARISON_SCOPES, FolioBlockDiff, FolioCompareDocxVersionsOptions, FolioDocumentMetadataValue, FolioFormatProperty, FolioMetadataDiff, FolioStoryDiff, FolioVersionBlockHandle, FolioVersionComparisonPrivacyTransform, FolioVersionComparisonScope, FolioVersionDiff, FolioVersionDiffPrivacyOptions, FolioVersionDiffPrivacyReport, FolioVersionDiffSegment, FolioVersionDiffSummaryCounts, InvalidFolioVersionComparisonOptionsError, applyFolioVersionDiffPrivacy, compareDocxVersions, isFolioVersionComparisonPrivacyTransform, isFolioVersionComparisonScope } from "./version-comparison.js";
30
- export { type ApplyDocxXmlPatchProposalArgs, type ApplyFolioAIEditsToBufferOptions, type ApplyFolioAIEditsToBufferResult, type BilingualBorders, type BilingualParagraphRef, type BilingualRow, type BilingualRowKind, type BilingualTableParagraphRef, type CreateBilingualDocumentOptions, type CreateBilingualDocumentResult, type CreateBilingualDocxOptions, type CreateBilingualDocxResult, type CreateCommentReplyInput, type CreateEmptyDocumentOptions, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, type DeriveBlockIdInput, type DocumentPreset, type DocumentStyleCatalog, type DocumentStyleCatalogEntry, type DocumentStyleSet, DocxArchiveError, type DocxArchiveOptions, type DocxParagraphSource, type DocxTableRowKind, type DocxTableRowPosition, EnsureParaIdsError, type EnsureParaIdsOptions, type EnsureParaIdsResult, type EvaluateDocxXmlPatchProposalArgs, type ExtractDocumentStyleSetOptions, type ExtractedDocxParagraph, type ExtractedDocxTableCell, type ExtractedDocxTableCellParagraph, type ExtractedDocxText, FOLIO_DOCUMENT_METADATA_PROPERTIES, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_DOCUMENT_PRIVACY_TRANSFORMS, FOLIO_DOCX_CONFORMANCE_CHECKS, FOLIO_DOCX_CONFORMANCE_ISSUE_CODES, FOLIO_DOCX_CONFORMANCE_PROFILE, FOLIO_DOCX_CONFORMANCE_REPORT_VERSION, FOLIO_DOCX_PACKAGE_INSPECTION_DEFAULTS, FOLIO_DOCX_PACKAGE_INSPECTION_ERROR_CODES, FOLIO_DOCX_PACKAGE_INSPECTION_VERSION, FOLIO_DOCX_XML_PATCH_APPLICATION_PROFILE, FOLIO_DOCX_XML_PATCH_APPLICATION_VERSION, FOLIO_DOCX_XML_PATCH_PROPOSAL_DEFAULTS, FOLIO_DOCX_XML_PATCH_PROPOSAL_ISSUE_CODES, FOLIO_DOCX_XML_PATCH_PROPOSAL_PROFILE, FOLIO_DOCX_XML_PATCH_PROPOSAL_VERSION, FOLIO_RESOLVED_REVIEWED_VIEWS, FOLIO_REVIEWED_VIEWS, FOLIO_VERSION_COMPARISON_PRIVACY_TRANSFORMS, FOLIO_VERSION_COMPARISON_SCOPES, FOLIO_YJS_DOCX_MATERIALIZATION_ERROR_CODES, FOLIO_YJS_PROSEMIRROR_FRAGMENT_NAME, FOLIO_YJS_UPDATE_MAX_BYTES, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIComment, type FolioAIEditApplyMode, type FolioAIEditApplyResult, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditSnapshot, type FolioAIInlineFormatting, type FolioAITextRangeHandle, type FolioApplyDocumentOperationsOptions, type FolioApplyDocumentOperationsToStoryOptions, type FolioApplyOperationsOptions, type FolioBlockDiff, type FolioBlockId, type FolioCompareDocxVersionsOptions, type FolioDocumentMetadataProperty, type FolioDocumentMetadataValue, type FolioDocumentNavigationTarget, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationStatus, type FolioDocumentOperationStory, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocumentOutline, type FolioDocumentOutlineEntry, FolioDocumentPrivacyArchiveError, type FolioDocumentPrivacyOptions, type FolioDocumentPrivacyReport, type FolioDocumentPrivacyTransform, type FolioDocumentSection, type FolioDocumentSectionHandle, type FolioDocumentSectionReadResult, type FolioDocumentStory, type FolioDocumentStoryHandle, FolioDocumentStoryNotFoundError, type FolioDocxConformanceCheck, type FolioDocxConformanceCheckId, type FolioDocxConformanceCheckStatus, type FolioDocxConformanceIssue, type FolioDocxConformanceIssueCode, type FolioDocxConformanceReport, type FolioDocxConformanceStatus, type FolioDocxInspectedXmlPart, type FolioDocxPackageInspection, FolioDocxPackageInspectionError, type FolioDocxPackageInspectionErrorCode, type FolioDocxPackageInspectionLimits, type FolioDocxPackagePart, type FolioDocxPackagePartKind, type FolioDocxPreparedXmlReplacement, FolioDocxReviewer, type FolioDocxReviewerOptions, type FolioDocxXmlPatchApplication, FolioDocxXmlPatchApplicationError, type FolioDocxXmlPatchApplicationReceipt, type FolioDocxXmlPatchProposal, type FolioDocxXmlPatchProposalEvaluation, type FolioDocxXmlPatchProposalIssue, type FolioDocxXmlPatchProposalIssueCode, type FolioDocxXmlPatchProposalLimits, type FolioDocxXmlReplacement, type FolioEditableDocumentStoryHandle, type FolioFormatProperty, type FolioMetadataDiff, type FolioReadReviewedStoryOptions, type FolioResolveReviewedStoryOptions, type FolioResolvedReviewedView, type FolioReviewChange, type FolioReviewChangeFilter, type FolioReviewChangeKind, type FolioReviewComment, type FolioReviewCommentFilter, type FolioReviewCommentReply, type FolioReviewReplyInput, type FolioReviewedStory, type FolioReviewedView, type FolioStoryDiff, type FolioVersionBlockHandle, type FolioVersionComparisonPrivacyTransform, type FolioVersionComparisonScope, type FolioVersionDiff, type FolioVersionDiffPrivacyOptions, type FolioVersionDiffPrivacyReport, type FolioVersionDiffSegment, type FolioVersionDiffSummaryCounts, FolioYjsDocxMaterializationError, type FolioYjsDocxMaterializationErrorCode, type GenerateRedlineDocxOptions, type GenerateRedlineDocxResult, type GenerateRedlineUnprocessedStory, HEADING_LEVELS, type HeadingLevel, type InspectDocxPackageOptions, InvalidBilingualDocumentOptionsError, InvalidFolioDocumentOperationBatchError, InvalidFolioDocumentPrivacyOptionsError, InvalidFolioDocxXmlPatchProposalError, InvalidFolioDocxXmlPatchProposalOptionsError, InvalidFolioReportBuilderOptionsError, InvalidFolioVersionComparisonOptionsError, InvalidGenerateRedlineDocxOptionsError, type MaterializeYjsDocxOptions, type ParseOptions, type RewriteDocxMetadataPrivacyResult, STELLA_STYLE_SET_NAME, type TableCellSpec, UnsupportedFolioDocumentOperationVersionError, UnsupportedFolioDocxXmlPatchApplicationProfileError, UnsupportedFolioReviewedViewError, type ValidateDocxConformanceOptions, applyDocxXmlPatchProposal, applyFolioAIEditsToBuffer, applyFolioVersionDiffPrivacy, assertSupportedFolioDocumentOperationVersion, bookmark, compareDocxVersions, createBilingualDocument, createBilingualDocx, createDocx, createEmptyDocument, createFolioAITextRangeHandle, createStellaStyleDocumentPreset, createStellaStyleSet, createTableOfContentsField, deriveBlockId, docxToMarkdown, endnote, ensureParaIds, evaluateDocxXmlPatchProposal, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractDocxText, generateRedlineDocx, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioDocumentOutline, getFolioParaIdFromBlockId, hashFolioAIBlockText, heading, hyperlink, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxPackage, isFolioBlockId, isFolioDocumentOperationModeSupported, isFolioDocumentPrivacyTransform, isFolioResolvedReviewedView, isFolioReviewedView, isFolioVersionComparisonPrivacyTransform, isFolioVersionComparisonScope, isSequentialFolioBlockId, isSupportedFolioDocumentOperationVersion, materializeYjsDocx, normalizeFolioAIBlockText, pageBreak, paragraph, parseDocx, parseFolioDocumentOperationBatch, parseFolioDocxXmlPatchProposal, readBilingualDocument, readBilingualDocx, readFolioDocumentSection, replyToComment, rewriteDocxMetadataPrivacy, run, table, validateDocxConformance };
30
+ export { type ApplyDocxXmlPatchProposalArgs, type ApplyFolioAIEditsToBufferOptions, type ApplyFolioAIEditsToBufferResult, BILINGUAL_TABLE_LAYOUTS, type BilingualBorders, type BilingualParagraphRef, type BilingualRow, type BilingualRowKind, type BilingualTableLayout, type BilingualTableParagraphRef, type CreateBilingualDocumentOptions, type CreateBilingualDocumentResult, type CreateBilingualDocxOptions, type CreateBilingualDocxResult, type CreateCommentReplyInput, type CreateEmptyDocumentOptions, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, type DeriveBlockIdInput, type DocumentPreset, type DocumentStyleCatalog, type DocumentStyleCatalogEntry, type DocumentStyleSet, DocxArchiveError, type DocxArchiveOptions, type DocxParagraphSource, type DocxTableRowKind, type DocxTableRowPosition, EnsureParaIdsError, type EnsureParaIdsOptions, type EnsureParaIdsResult, type EvaluateDocxXmlPatchProposalArgs, type ExtractDocumentStyleSetOptions, type ExtractedDocxParagraph, type ExtractedDocxTableCell, type ExtractedDocxTableCellParagraph, type ExtractedDocxText, FOLIO_DOCUMENT_METADATA_PROPERTIES, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_DOCUMENT_PRIVACY_TRANSFORMS, FOLIO_DOCX_CONFORMANCE_CHECKS, FOLIO_DOCX_CONFORMANCE_ISSUE_CODES, FOLIO_DOCX_CONFORMANCE_PROFILE, FOLIO_DOCX_CONFORMANCE_REPORT_VERSION, FOLIO_DOCX_PACKAGE_INSPECTION_DEFAULTS, FOLIO_DOCX_PACKAGE_INSPECTION_ERROR_CODES, FOLIO_DOCX_PACKAGE_INSPECTION_VERSION, FOLIO_DOCX_XML_PATCH_APPLICATION_PROFILE, FOLIO_DOCX_XML_PATCH_APPLICATION_VERSION, FOLIO_DOCX_XML_PATCH_PROPOSAL_DEFAULTS, FOLIO_DOCX_XML_PATCH_PROPOSAL_ISSUE_CODES, FOLIO_DOCX_XML_PATCH_PROPOSAL_PROFILE, FOLIO_DOCX_XML_PATCH_PROPOSAL_VERSION, FOLIO_RESOLVED_REVIEWED_VIEWS, FOLIO_REVIEWED_VIEWS, FOLIO_VERSION_COMPARISON_PRIVACY_TRANSFORMS, FOLIO_VERSION_COMPARISON_SCOPES, FOLIO_YJS_DOCX_MATERIALIZATION_ERROR_CODES, FOLIO_YJS_PROSEMIRROR_FRAGMENT_NAME, FOLIO_YJS_UPDATE_MAX_BYTES, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIComment, type FolioAIEditApplyMode, type FolioAIEditApplyResult, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditSnapshot, type FolioAIInlineFormatting, type FolioAITextRangeHandle, type FolioApplyDocumentOperationsOptions, type FolioApplyDocumentOperationsToStoryOptions, type FolioApplyOperationsOptions, type FolioBlockDiff, type FolioBlockId, type FolioCompareDocxVersionsOptions, type FolioDocumentMetadataProperty, type FolioDocumentMetadataValue, type FolioDocumentNavigationTarget, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationStatus, type FolioDocumentOperationStory, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocumentOutline, type FolioDocumentOutlineEntry, FolioDocumentPrivacyArchiveError, type FolioDocumentPrivacyOptions, type FolioDocumentPrivacyReport, type FolioDocumentPrivacyTransform, type FolioDocumentSection, type FolioDocumentSectionHandle, type FolioDocumentSectionReadResult, type FolioDocumentStory, type FolioDocumentStoryHandle, FolioDocumentStoryNotFoundError, type FolioDocxConformanceCheck, type FolioDocxConformanceCheckId, type FolioDocxConformanceCheckStatus, type FolioDocxConformanceIssue, type FolioDocxConformanceIssueCode, type FolioDocxConformanceReport, type FolioDocxConformanceStatus, type FolioDocxInspectedXmlPart, type FolioDocxPackageInspection, FolioDocxPackageInspectionError, type FolioDocxPackageInspectionErrorCode, type FolioDocxPackageInspectionLimits, type FolioDocxPackagePart, type FolioDocxPackagePartKind, type FolioDocxPreparedXmlReplacement, FolioDocxReviewer, type FolioDocxReviewerOptions, type FolioDocxXmlPatchApplication, FolioDocxXmlPatchApplicationError, type FolioDocxXmlPatchApplicationReceipt, type FolioDocxXmlPatchProposal, type FolioDocxXmlPatchProposalEvaluation, type FolioDocxXmlPatchProposalIssue, type FolioDocxXmlPatchProposalIssueCode, type FolioDocxXmlPatchProposalLimits, type FolioDocxXmlReplacement, type FolioEditableDocumentStoryHandle, type FolioFormatProperty, type FolioMetadataDiff, type FolioReadReviewedStoryOptions, type FolioResolveReviewedStoryOptions, type FolioResolvedReviewedView, type FolioReviewChange, type FolioReviewChangeFilter, type FolioReviewChangeKind, type FolioReviewComment, type FolioReviewCommentFilter, type FolioReviewCommentReply, type FolioReviewReplyInput, type FolioReviewedStory, type FolioReviewedView, type FolioStoryDiff, type FolioVersionBlockHandle, type FolioVersionComparisonPrivacyTransform, type FolioVersionComparisonScope, type FolioVersionDiff, type FolioVersionDiffPrivacyOptions, type FolioVersionDiffPrivacyReport, type FolioVersionDiffSegment, type FolioVersionDiffSummaryCounts, FolioYjsDocxMaterializationError, type FolioYjsDocxMaterializationErrorCode, type GenerateRedlineDocxOptions, type GenerateRedlineDocxResult, type GenerateRedlineUnprocessedStory, HEADING_LEVELS, type HeadingLevel, type InspectDocxPackageOptions, InvalidBilingualDocumentOptionsError, InvalidFolioDocumentOperationBatchError, InvalidFolioDocumentPrivacyOptionsError, InvalidFolioDocxXmlPatchProposalError, InvalidFolioDocxXmlPatchProposalOptionsError, InvalidFolioReportBuilderOptionsError, InvalidFolioVersionComparisonOptionsError, InvalidGenerateRedlineDocxOptionsError, type MaterializeYjsDocxOptions, type ParseOptions, type RewriteDocxMetadataPrivacyResult, STELLA_STYLE_SET_NAME, type TableCellSpec, UnsupportedFolioDocumentOperationVersionError, UnsupportedFolioDocxXmlPatchApplicationProfileError, UnsupportedFolioReviewedViewError, type ValidateDocxConformanceOptions, applyDocxXmlPatchProposal, applyFolioAIEditsToBuffer, applyFolioVersionDiffPrivacy, assertSupportedFolioDocumentOperationVersion, bookmark, compareDocxVersions, createBilingualDocument, createBilingualDocx, createDocx, createEmptyDocument, createFolioAITextRangeHandle, createStellaStyleDocumentPreset, createStellaStyleSet, createTableOfContentsField, deriveBlockId, docxToMarkdown, endnote, ensureParaIds, evaluateDocxXmlPatchProposal, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractDocxText, generateRedlineDocx, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioDocumentOutline, getFolioParaIdFromBlockId, hashFolioAIBlockText, heading, hyperlink, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxPackage, isFolioBlockId, isFolioDocumentOperationModeSupported, isFolioDocumentPrivacyTransform, isFolioResolvedReviewedView, isFolioReviewedView, isFolioVersionComparisonPrivacyTransform, isFolioVersionComparisonScope, isSequentialFolioBlockId, isSupportedFolioDocumentOperationVersion, materializeYjsDocx, normalizeFolioAIBlockText, pageBreak, paragraph, parseDocx, parseFolioDocumentOperationBatch, parseFolioDocxXmlPatchProposal, readBilingualDocument, readBilingualDocx, readFolioDocumentSection, replyToComment, rewriteDocxMetadataPrivacy, run, table, validateDocxConformance };
package/dist/server.js CHANGED
@@ -10,7 +10,7 @@ import { createDocx } from "./docx/rezip.js";
10
10
  import { FOLIO_DOCX_XML_PATCH_APPLICATION_PROFILE, FOLIO_DOCX_XML_PATCH_APPLICATION_VERSION, FolioDocxXmlPatchApplicationError, UnsupportedFolioDocxXmlPatchApplicationProfileError, applyDocxXmlPatchProposal } from "./docx/server/applyDocxXmlPatchProposal.js";
11
11
  import { DocxArchiveError } from "./docx/server/boundedArchive.js";
12
12
  import { HEADING_LEVELS, InvalidFolioReportBuilderOptionsError, bookmark, createTableOfContentsField, endnote, heading, hyperlink, pageBreak, paragraph, run, table } from "./docx/server/build.js";
13
- import { InvalidBilingualDocumentOptionsError, createBilingualDocument, readBilingualDocument } from "./docx/server/createBilingualDocument.js";
13
+ import { BILINGUAL_TABLE_LAYOUTS, InvalidBilingualDocumentOptionsError, createBilingualDocument, readBilingualDocument } from "./docx/server/createBilingualDocument.js";
14
14
  import { createBilingualDocx, readBilingualDocx } from "./docx/server/createBilingualDocx.js";
15
15
  import { docxToMarkdown } from "./docx/server/docxToMarkdown.js";
16
16
  import { FOLIO_DOCX_XML_PATCH_PROPOSAL_DEFAULTS, FOLIO_DOCX_XML_PATCH_PROPOSAL_ISSUE_CODES, FOLIO_DOCX_XML_PATCH_PROPOSAL_PROFILE, FOLIO_DOCX_XML_PATCH_PROPOSAL_VERSION, InvalidFolioDocxXmlPatchProposalError, InvalidFolioDocxXmlPatchProposalOptionsError, evaluateDocxXmlPatchProposal, parseFolioDocxXmlPatchProposal } from "./docx/server/evaluateDocxXmlPatchProposal.js";
@@ -25,4 +25,4 @@ import { DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION } from "./style-set
25
25
  import { deriveBlockId, getFolioParaIdFromBlockId, isFolioBlockId, isSequentialFolioBlockId } from "./types/block-id.js";
26
26
  import { createEmptyDocument } from "./utils/createDocument.js";
27
27
  import { FOLIO_VERSION_COMPARISON_PRIVACY_TRANSFORMS, FOLIO_VERSION_COMPARISON_SCOPES, InvalidFolioVersionComparisonOptionsError, applyFolioVersionDiffPrivacy, compareDocxVersions, isFolioVersionComparisonPrivacyTransform, isFolioVersionComparisonScope } from "./version-comparison.js";
28
- export { DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DocxArchiveError, EnsureParaIdsError, FOLIO_DOCUMENT_METADATA_PROPERTIES, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_DOCUMENT_PRIVACY_TRANSFORMS, FOLIO_DOCX_CONFORMANCE_CHECKS, FOLIO_DOCX_CONFORMANCE_ISSUE_CODES, FOLIO_DOCX_CONFORMANCE_PROFILE, FOLIO_DOCX_CONFORMANCE_REPORT_VERSION, FOLIO_DOCX_PACKAGE_INSPECTION_DEFAULTS, FOLIO_DOCX_PACKAGE_INSPECTION_ERROR_CODES, FOLIO_DOCX_PACKAGE_INSPECTION_VERSION, FOLIO_DOCX_XML_PATCH_APPLICATION_PROFILE, FOLIO_DOCX_XML_PATCH_APPLICATION_VERSION, FOLIO_DOCX_XML_PATCH_PROPOSAL_DEFAULTS, FOLIO_DOCX_XML_PATCH_PROPOSAL_ISSUE_CODES, FOLIO_DOCX_XML_PATCH_PROPOSAL_PROFILE, FOLIO_DOCX_XML_PATCH_PROPOSAL_VERSION, FOLIO_RESOLVED_REVIEWED_VIEWS, FOLIO_REVIEWED_VIEWS, FOLIO_VERSION_COMPARISON_PRIVACY_TRANSFORMS, FOLIO_VERSION_COMPARISON_SCOPES, FOLIO_YJS_DOCX_MATERIALIZATION_ERROR_CODES, FOLIO_YJS_PROSEMIRROR_FRAGMENT_NAME, FOLIO_YJS_UPDATE_MAX_BYTES, FolioDocumentPrivacyArchiveError, FolioDocumentStoryNotFoundError, FolioDocxPackageInspectionError, FolioDocxReviewer, FolioDocxXmlPatchApplicationError, FolioYjsDocxMaterializationError, HEADING_LEVELS, InvalidBilingualDocumentOptionsError, InvalidFolioDocumentOperationBatchError, InvalidFolioDocumentPrivacyOptionsError, InvalidFolioDocxXmlPatchProposalError, InvalidFolioDocxXmlPatchProposalOptionsError, InvalidFolioReportBuilderOptionsError, InvalidFolioVersionComparisonOptionsError, InvalidGenerateRedlineDocxOptionsError, STELLA_STYLE_SET_NAME, UnsupportedFolioDocumentOperationVersionError, UnsupportedFolioDocxXmlPatchApplicationProfileError, UnsupportedFolioReviewedViewError, applyDocxXmlPatchProposal, applyFolioAIEditsToBuffer, applyFolioVersionDiffPrivacy, assertSupportedFolioDocumentOperationVersion, bookmark, compareDocxVersions, createBilingualDocument, createBilingualDocx, createDocx, createEmptyDocument, createFolioAITextRangeHandle, createStellaStyleDocumentPreset, createStellaStyleSet, createTableOfContentsField, deriveBlockId, docxToMarkdown, endnote, ensureParaIds, evaluateDocxXmlPatchProposal, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractDocxText, generateRedlineDocx, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioDocumentOutline, getFolioParaIdFromBlockId, hashFolioAIBlockText, heading, hyperlink, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxPackage, isFolioBlockId, isFolioDocumentOperationModeSupported, isFolioDocumentPrivacyTransform, isFolioResolvedReviewedView, isFolioReviewedView, isFolioVersionComparisonPrivacyTransform, isFolioVersionComparisonScope, isSequentialFolioBlockId, isSupportedFolioDocumentOperationVersion, materializeYjsDocx, normalizeFolioAIBlockText, pageBreak, paragraph, parseDocx, parseFolioDocumentOperationBatch, parseFolioDocxXmlPatchProposal, readBilingualDocument, readBilingualDocx, readFolioDocumentSection, replyToComment, rewriteDocxMetadataPrivacy, run, table, validateDocxConformance };
28
+ export { BILINGUAL_TABLE_LAYOUTS, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DocxArchiveError, EnsureParaIdsError, FOLIO_DOCUMENT_METADATA_PROPERTIES, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_DOCUMENT_PRIVACY_TRANSFORMS, FOLIO_DOCX_CONFORMANCE_CHECKS, FOLIO_DOCX_CONFORMANCE_ISSUE_CODES, FOLIO_DOCX_CONFORMANCE_PROFILE, FOLIO_DOCX_CONFORMANCE_REPORT_VERSION, FOLIO_DOCX_PACKAGE_INSPECTION_DEFAULTS, FOLIO_DOCX_PACKAGE_INSPECTION_ERROR_CODES, FOLIO_DOCX_PACKAGE_INSPECTION_VERSION, FOLIO_DOCX_XML_PATCH_APPLICATION_PROFILE, FOLIO_DOCX_XML_PATCH_APPLICATION_VERSION, FOLIO_DOCX_XML_PATCH_PROPOSAL_DEFAULTS, FOLIO_DOCX_XML_PATCH_PROPOSAL_ISSUE_CODES, FOLIO_DOCX_XML_PATCH_PROPOSAL_PROFILE, FOLIO_DOCX_XML_PATCH_PROPOSAL_VERSION, FOLIO_RESOLVED_REVIEWED_VIEWS, FOLIO_REVIEWED_VIEWS, FOLIO_VERSION_COMPARISON_PRIVACY_TRANSFORMS, FOLIO_VERSION_COMPARISON_SCOPES, FOLIO_YJS_DOCX_MATERIALIZATION_ERROR_CODES, FOLIO_YJS_PROSEMIRROR_FRAGMENT_NAME, FOLIO_YJS_UPDATE_MAX_BYTES, FolioDocumentPrivacyArchiveError, FolioDocumentStoryNotFoundError, FolioDocxPackageInspectionError, FolioDocxReviewer, FolioDocxXmlPatchApplicationError, FolioYjsDocxMaterializationError, HEADING_LEVELS, InvalidBilingualDocumentOptionsError, InvalidFolioDocumentOperationBatchError, InvalidFolioDocumentPrivacyOptionsError, InvalidFolioDocxXmlPatchProposalError, InvalidFolioDocxXmlPatchProposalOptionsError, InvalidFolioReportBuilderOptionsError, InvalidFolioVersionComparisonOptionsError, InvalidGenerateRedlineDocxOptionsError, STELLA_STYLE_SET_NAME, UnsupportedFolioDocumentOperationVersionError, UnsupportedFolioDocxXmlPatchApplicationProfileError, UnsupportedFolioReviewedViewError, applyDocxXmlPatchProposal, applyFolioAIEditsToBuffer, applyFolioVersionDiffPrivacy, assertSupportedFolioDocumentOperationVersion, bookmark, compareDocxVersions, createBilingualDocument, createBilingualDocx, createDocx, createEmptyDocument, createFolioAITextRangeHandle, createStellaStyleDocumentPreset, createStellaStyleSet, createTableOfContentsField, deriveBlockId, docxToMarkdown, endnote, ensureParaIds, evaluateDocxXmlPatchProposal, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractDocxText, generateRedlineDocx, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioDocumentOutline, getFolioParaIdFromBlockId, hashFolioAIBlockText, heading, hyperlink, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxPackage, isFolioBlockId, isFolioDocumentOperationModeSupported, isFolioDocumentPrivacyTransform, isFolioResolvedReviewedView, isFolioReviewedView, isFolioVersionComparisonPrivacyTransform, isFolioVersionComparisonScope, isSequentialFolioBlockId, isSupportedFolioDocumentOperationVersion, materializeYjsDocx, normalizeFolioAIBlockText, pageBreak, paragraph, parseDocx, parseFolioDocumentOperationBatch, parseFolioDocxXmlPatchProposal, readBilingualDocument, readBilingualDocx, readFolioDocumentSection, replyToComment, rewriteDocxMetadataPrivacy, run, table, validateDocxConformance };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stll/folio-core",
3
- "version": "0.30.0",
3
+ "version": "0.31.1",
4
4
  "description": "Headless, framework-neutral core of folio: the OOXML (.docx) parser, document model, ProseMirror integration, and page-layout engine. No React.",
5
5
  "keywords": [
6
6
  "document-model",