@stll/folio-core 0.25.4 → 0.26.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 (36) hide show
  1. package/dist/docx/compatibility.js +2 -2
  2. package/dist/docx/runParser.js +3 -2
  3. package/dist/docx/serializer/paragraphSerializer.js +1 -1
  4. package/dist/docx/serializer/runSerializer.js +6 -2
  5. package/dist/docx/serializer/sectionPropertiesSerializer.js +3 -3
  6. package/dist/docx/server/createBilingualDocument.d.ts +10 -5
  7. package/dist/docx/server/createBilingualDocument.js +39 -9
  8. package/dist/docx/server/createBilingualDocx.d.ts +3 -2
  9. package/dist/docx/server/createBilingualDocx.js +13 -4
  10. package/dist/docx/shapeParser.js +26 -3
  11. package/dist/docx/unzip.js +4 -4
  12. package/dist/layout-bridge/convert/toFlowBlocks.js +2 -7
  13. package/dist/prosemirror/attrs/index.js +9 -1
  14. package/dist/prosemirror/commands/image.js +2 -1
  15. package/dist/prosemirror/conversion/fromProseDoc.js +26 -6
  16. package/dist/prosemirror/conversion/toProseDoc.js +17 -6
  17. package/dist/prosemirror/extensions/core/ParagraphExtension.d.ts +2 -0
  18. package/dist/prosemirror/extensions/core/ParagraphExtension.js +15 -3
  19. package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +6 -1
  20. package/dist/prosemirror/extensions/nodes/ImageExtension.js +1 -0
  21. package/dist/prosemirror/extensions/nodes/ShapeExtension.d.ts +7 -1
  22. package/dist/prosemirror/extensions/nodes/ShapeExtension.js +55 -3
  23. package/dist/prosemirror/schema/nodes.d.ts +6 -0
  24. package/dist/prosemirror/shapeGeometryAdjustments.d.ts +5 -0
  25. package/dist/prosemirror/shapeGeometryAdjustments.js +24 -0
  26. package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +5 -1
  27. package/dist/prosemirror/styles/resolvedStyleAttrs.js +4 -2
  28. package/dist/redline.js +13 -6
  29. package/dist/redlineOperationLimit.d.ts +8 -0
  30. package/dist/redlineOperationLimit.js +6 -0
  31. package/dist/server.d.ts +2 -2
  32. package/dist/types/content.d.ts +2 -2
  33. package/dist/types/index.d.ts +3 -1
  34. package/dist/utils/tableOfContentsStyle.d.ts +9 -0
  35. package/dist/utils/tableOfContentsStyle.js +14 -0
  36. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
- import { DOCX_CONFORMANCE_CLASSES } from "@stll/docx-core/model";
1
+ import { DOCX_CONFORMANCE_CLASSES, DRAWING_RAW_XML_MODES } from "@stll/docx-core/model";
2
2
  //#region src/docx/compatibility.ts
3
3
  const resolveCompatibilityContext = (doc, options) => ({
4
4
  host: options.host ?? "unknown",
@@ -146,7 +146,7 @@ function inspectHyperlink(hyperlink, context) {
146
146
  });
147
147
  }
148
148
  function inspectRun(run, context) {
149
- for (const [contentIndex, content] of run.content.entries()) if (content.type === "drawing" && content.rawXml) context.record({
149
+ for (const [contentIndex, content] of run.content.entries()) if (content.type === "drawing" && content.rawXml && content.rawXmlMode !== DRAWING_RAW_XML_MODES.PRESERVE_ONLY) context.record({
150
150
  ...context.blockId === void 0 ? {} : { blockId: context.blockId },
151
151
  part: context.part,
152
152
  path: `${context.path}.content[${contentIndex}]`
@@ -7,7 +7,7 @@ import { requiresXmlSpacePreserve } from "./textWhitespace.js";
7
7
  import { resolveThemeFontRef } from "./themeParser.js";
8
8
  import { parseVmlImageContent } from "./vmlImageParser.js";
9
9
  import { cloneWithXmlnsDeclarations, elementToXml, findAllDeep, findChild, findChildren, getAttribute, getChildElements, getLocalName, getTextContent, mergeXmlnsDeclarations, parseBooleanElement, parseNumericAttribute } from "./xmlParser.js";
10
- import { normalizeRevisionId } from "@stll/docx-core/model";
10
+ import { DRAWING_RAW_XML_MODES, normalizeRevisionId } from "@stll/docx-core/model";
11
11
  //#region src/docx/runParser.ts
12
12
  /**
13
13
  * Sanity cap on `w:lang` `@w:val`/`@w:eastAsia`/`@w:bidi` tag length. BCP-47
@@ -500,7 +500,8 @@ function parseDrawingContent(element, rels, media) {
500
500
  },
501
501
  wrap: { type: "inline" }
502
502
  },
503
- rawXml: elementToXml(element)
503
+ rawXml: elementToXml(element),
504
+ rawXmlMode: DRAWING_RAW_XML_MODES.PRESERVE_ONLY
504
505
  };
505
506
  const shape = parseShapeFromDrawing(element);
506
507
  if (shape) return {
@@ -215,7 +215,7 @@ function serializeParagraphPropertyChange(change) {
215
215
  */
216
216
  function serializeHyperlink(hyperlink) {
217
217
  const attrs = [];
218
- if (hyperlink.rId) attrs.push(`r:id="${hyperlink.rId}"`);
218
+ if (hyperlink.rId) attrs.push(`r:id="${escapeXml(hyperlink.rId)}"`);
219
219
  if (hyperlink.anchor) attrs.push(`w:anchor="${escapeXml(hyperlink.anchor)}"`);
220
220
  if (hyperlink.tooltip) attrs.push(`w:tooltip="${escapeXml(hyperlink.tooltip)}"`);
221
221
  if (hyperlink.target) attrs.push(`w:tgtFrame="${escapeXml(hyperlink.target)}"`);
@@ -338,7 +338,7 @@ function serializeWrap(wrap) {
338
338
  function serializePicGraphic(image, sharedId) {
339
339
  const cx = image.size.width;
340
340
  const cy = image.size.height;
341
- const rId = image.rId || "rId1";
341
+ const rId = escapeXml(image.rId || "rId1");
342
342
  const id = sharedId;
343
343
  const name = image.filename || `image${id}`;
344
344
  let xfrmAttrs = "";
@@ -448,6 +448,10 @@ function serializeDrawingContent(content) {
448
448
  function serializeShapeTextBody(blocks) {
449
449
  return blocks.map((block) => block.type === "paragraph" ? serializeParagraph(block) : serializeTable(block, serializeParagraph)).join("");
450
450
  }
451
+ function serializeGeometryAdjustments(shape) {
452
+ if (!shape.geometryAdjustments || shape.geometryAdjustments.length === 0) return "<a:avLst/>";
453
+ return `<a:avLst>${shape.geometryAdjustments.map(({ name, formula }) => `<a:gd name="${escapeXml(name)}" fmla="${escapeXml(formula)}"/>`).join("")}</a:avLst>`;
454
+ }
451
455
  /**
452
456
  * Serialize shape content to full DrawingML XML (wps:wsp inside w:drawing)
453
457
  */
@@ -470,7 +474,7 @@ function serializeShapeContent(content) {
470
474
  "<a:off x=\"0\" y=\"0\"/>",
471
475
  `<a:ext cx="${intAttr(cx)}" cy="${intAttr(cy)}"/>`,
472
476
  "</a:xfrm>",
473
- `<a:prstGeom prst="${shape.shapeType === "textBox" ? "rect" : shape.shapeType}"><a:avLst/></a:prstGeom>`,
477
+ `<a:prstGeom prst="${shape.shapeType === "textBox" ? "rect" : shape.shapeType}">${serializeGeometryAdjustments(shape)}</a:prstGeom>`,
474
478
  serializeFill(shape.fill),
475
479
  serializeOutline(shape.outline),
476
480
  "</wps:spPr>"
@@ -3,8 +3,8 @@ import { serializeBorder } from "./borderSerializer.js";
3
3
  import { escapeXml, intAttr } from "./xmlUtils.js";
4
4
  import { normalizeRevisionId } from "@stll/docx-core/model";
5
5
  //#region src/docx/serializer/sectionPropertiesSerializer.ts
6
- const serializeHeaderReference = (ref) => `<w:headerReference w:type="${ref.type}" r:id="${ref.rId}"/>`;
7
- const serializeFooterReference = (ref) => `<w:footerReference w:type="${ref.type}" r:id="${ref.rId}"/>`;
6
+ const serializeHeaderReference = (ref) => `<w:headerReference w:type="${ref.type}" r:id="${escapeXml(ref.rId)}"/>`;
7
+ const serializeFooterReference = (ref) => `<w:footerReference w:type="${ref.type}" r:id="${escapeXml(ref.rId)}"/>`;
8
8
  function serializeFootnoteProperties(props) {
9
9
  if (!props) return "";
10
10
  const parts = [];
@@ -178,7 +178,7 @@ function serializeSectionProperties(props) {
178
178
  serializeOnOffElement(props.noEndnote, "noEndnote"),
179
179
  serializeOnOffElement(props.rtlGutter, "rtlGutter")
180
180
  ]) if (xml) parts.push(xml);
181
- if (props.printerSettingsRelationshipId) parts.push(`<w:printerSettings r:id="${props.printerSettingsRelationshipId}"/>`);
181
+ if (props.printerSettingsRelationshipId) parts.push(`<w:printerSettings r:id="${escapeXml(props.printerSettingsRelationshipId)}"/>`);
182
182
  for (const change of props.propertyChanges ?? []) parts.push(serializeSectionPropertyChange(change));
183
183
  const unserializedChildNames = getUnserializedSectionPropertyChildNames(props);
184
184
  if (unserializedChildNames && unserializedChildNames.length > 0) return "";
@@ -37,6 +37,11 @@ type CreateBilingualDocumentOptions = {
37
37
  targetStyleSuffix: string;
38
38
  /** Table borders; legal practice is usually `"none"`. Default `"none"`. */
39
39
  borders?: BilingualBorders;
40
+ /**
41
+ * Paragraph handles exposed by Folio's canonical AI-edit snapshot for the
42
+ * source DOCX. Only these paragraphs may become translation rows.
43
+ */
44
+ editableParagraphIds: ReadonlySet<string>;
40
45
  };
41
46
  type CreateBilingualDocumentResult = {
42
47
  document: document_d_exports.Document;
@@ -52,11 +57,11 @@ declare class InvalidBilingualDocumentOptionsError extends InvalidBilingualDocum
52
57
  declare function createBilingualDocument(source: document_d_exports.Document, options: CreateBilingualDocumentOptions): CreateBilingualDocumentResult;
53
58
  /**
54
59
  * Re-derive the row manifest from a document produced by
55
- * {@link createBilingualDocument}. Detection is structural: a top-level table
56
- * whose rows are all either a left | right pair of single-paragraph cells or
57
- * one cell spanning both columns. Rows are returned in document order; the
58
- * right paragraph's `paraId` is the row handle, as at creation.
60
+ * {@link createBilingualDocument}. A dedicated table-style discriminator keeps
61
+ * ordinary two-column source tables from being mistaken for bilingual output;
62
+ * 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.
59
64
  */
60
- declare function readBilingualDocument(document: document_d_exports.Document): BilingualRow[];
65
+ declare function readBilingualDocument(document: document_d_exports.Document, editableParagraphIds: ReadonlySet<string>): BilingualRow[];
61
66
  //#endregion
62
67
  export { BilingualBorders, BilingualParagraphRef, BilingualRow, BilingualRowKind, BilingualTableParagraphRef, CreateBilingualDocumentOptions, CreateBilingualDocumentResult, InvalidBilingualDocumentOptionsError, createBilingualDocument, readBilingualDocument };
@@ -17,13 +17,17 @@ import { TaggedError } from "better-result";
17
17
  * and the break paragraph stays between the tables. A source table (parties,
18
18
  * signature block) is kept once, in a row spanning both columns: it is signed
19
19
  * and read once, and its labels are translated inline rather than duplicated.
20
+ * Structural-only paragraphs are also kept once between tables; they have no
21
+ * independently editable text for a translation row to address.
20
22
  */
21
23
  const STYLE_SUFFIX_PATTERN = /^[A-Za-z0-9-]+$/u;
22
24
  var InvalidBilingualDocumentOptionsError = class extends TaggedError("InvalidBilingualDocumentOptionsError") {};
25
+ var UneditableBilingualManifestError = class extends TaggedError("UneditableBilingualManifestError") {};
23
26
  const FULL_WIDTH_PCT = 5e3;
24
27
  const HALF_WIDTH_PCT = 2500;
25
28
  const A4_TEXT_WIDTH_TWIPS = 9072;
26
29
  const ROW_ID_NAMESPACE = "folio-bilingual";
30
+ const BILINGUAL_TABLE_STYLE_ID = "FolioBilingualTranslation";
27
31
  const GRID_BORDER = {
28
32
  style: "single",
29
33
  size: 4,
@@ -96,6 +100,11 @@ function createBilingualDocument(source, options) {
96
100
  }
97
101
  if (block.type === "paragraph") {
98
102
  if (isEmptyParagraph(block)) continue;
103
+ if (block.paraId === void 0 || !options.editableParagraphIds.has(block.paraId)) {
104
+ flushSection();
105
+ content.push(block);
106
+ continue;
107
+ }
99
108
  const { copy, ref } = copyParagraph(block);
100
109
  rows.push({
101
110
  kind: classifyParagraph(block, styleById),
@@ -105,10 +114,15 @@ function createBilingualDocument(source, options) {
105
114
  sectionRows.push(buildRow(block, copy));
106
115
  continue;
107
116
  }
108
- const paragraphs = collectTableParagraphs(block).map((paragraph) => ({
117
+ const paragraphs = collectTableParagraphs(block).filter((paragraph) => paragraph.paraId !== void 0 && options.editableParagraphIds.has(paragraph.paraId)).map((paragraph) => ({
109
118
  paraId: paragraph.paraId,
110
119
  sourceText: getParagraphText(paragraph)
111
120
  }));
121
+ if (paragraphs.length === 0) {
122
+ flushSection();
123
+ content.push(block);
124
+ continue;
125
+ }
112
126
  rows.push({
113
127
  kind: "table",
114
128
  rowId: paragraphs.at(0)?.paraId ?? tableRowHandle(rows.length),
@@ -152,7 +166,7 @@ const flattenBlocks = (content) => {
152
166
  };
153
167
  const isEmptyParagraph = (paragraph) => {
154
168
  if (getParagraphText(paragraph).trim().length > 0) return false;
155
- return paragraph.content.every((item) => item.type === "run" && item.content.every((part) => part.type === "text"));
169
+ return paragraph.content.every((item) => item.type === "run" && item.formatting?.hidden !== true && item.content.every((part) => part.type === "text"));
156
170
  };
157
171
  /** Heading style families across Word UI languages (en, cs/sk, de, fr, pl). */
158
172
  const HEADING_STYLE_PATTERN = /heading|nadpis|berschrift|titre|nag[łl]/iu;
@@ -391,6 +405,7 @@ const buildTable = (rows, borders, textWidth) => ({
391
405
  value: FULL_WIDTH_PCT,
392
406
  type: "pct"
393
407
  },
408
+ styleId: BILINGUAL_TABLE_STYLE_ID,
394
409
  layout: "fixed",
395
410
  borders: TABLE_BORDERS[borders],
396
411
  look: {
@@ -453,21 +468,22 @@ const createParaIdMinter = (taken) => {
453
468
  };
454
469
  /**
455
470
  * Re-derive the row manifest from a document produced by
456
- * {@link createBilingualDocument}. Detection is structural: a top-level table
457
- * whose rows are all either a left | right pair of single-paragraph cells or
458
- * one cell spanning both columns. Rows are returned in document order; the
459
- * right paragraph's `paraId` is the row handle, as at creation.
471
+ * {@link createBilingualDocument}. A dedicated table-style discriminator keeps
472
+ * ordinary two-column source tables from being mistaken for bilingual output;
473
+ * the expected row structure is validated as a second check. Rows are returned
474
+ * in document order; the right paragraph's `paraId` is the row handle.
460
475
  */
461
- function readBilingualDocument(document) {
476
+ function readBilingualDocument(document, editableParagraphIds) {
462
477
  const styleById = new Map((document.package.styles?.styles ?? []).map((style) => [style.styleId, style]));
463
478
  const rows = [];
479
+ let missingHandleCount = 0;
464
480
  for (const block of flattenBlocks(document.package.document.content)) {
465
481
  if (block.type !== "table" || !isBilingualTable(block)) continue;
466
482
  for (const row of block.rows) {
467
483
  const [left, right] = row.cells;
468
484
  if (!left) continue;
469
485
  if (!right) {
470
- const paragraphs = left.content.filter((item) => item.type === "table").flatMap(collectTableParagraphs).map((paragraph) => ({
486
+ const paragraphs = left.content.filter((item) => item.type === "table").flatMap(collectTableParagraphs).filter((paragraph) => paragraph.paraId !== void 0 && editableParagraphIds.has(paragraph.paraId)).map((paragraph) => ({
471
487
  paraId: paragraph.paraId,
472
488
  sourceText: getParagraphText(paragraph)
473
489
  }));
@@ -480,7 +496,16 @@ function readBilingualDocument(document) {
480
496
  }
481
497
  const source = left.content.at(0);
482
498
  const target = right.content.at(0);
483
- if (source?.type !== "paragraph" || target?.type !== "paragraph" || !target.paraId) continue;
499
+ if (source?.type !== "paragraph" || target?.type !== "paragraph") continue;
500
+ if (target.paraId === void 0) {
501
+ missingHandleCount += 1;
502
+ continue;
503
+ }
504
+ const sourceMissing = source.paraId === void 0 || !editableParagraphIds.has(source.paraId);
505
+ const targetMissing = !editableParagraphIds.has(target.paraId);
506
+ if (sourceMissing) missingHandleCount += 1;
507
+ if (targetMissing) missingHandleCount += 1;
508
+ if (sourceMissing || targetMissing) continue;
484
509
  rows.push({
485
510
  kind: classifyParagraph(source, styleById),
486
511
  rowId: target.paraId,
@@ -490,9 +515,14 @@ function readBilingualDocument(document) {
490
515
  });
491
516
  }
492
517
  }
518
+ if (missingHandleCount > 0) throw new UneditableBilingualManifestError({
519
+ message: "Bilingual manifest contains handles absent from the Folio AI-edit snapshot.",
520
+ missingHandleCount
521
+ });
493
522
  return rows;
494
523
  }
495
524
  const isBilingualTable = (table) => {
525
+ if (table.formatting?.styleId !== BILINGUAL_TABLE_STYLE_ID) return false;
496
526
  let pairs = 0;
497
527
  for (const row of table.rows) {
498
528
  const cells = row.cells;
@@ -1,5 +1,6 @@
1
1
  import { BilingualRow, CreateBilingualDocumentOptions } from "./createBilingualDocument.js";
2
2
  //#region src/docx/server/createBilingualDocx.d.ts
3
+ type CreateBilingualDocxOptions = Omit<CreateBilingualDocumentOptions, "editableParagraphIds">;
3
4
  type CreateBilingualDocxResult = {
4
5
  buffer: ArrayBuffer;
5
6
  rows: BilingualRow[];
@@ -12,8 +13,8 @@ type CreateBilingualDocxResult = {
12
13
  * as a two-column table, and repack onto the original package so theme, fonts,
13
14
  * media, headers and footers carry over untouched.
14
15
  */
15
- declare function createBilingualDocx(input: ArrayBuffer | Uint8Array, options: CreateBilingualDocumentOptions): Promise<CreateBilingualDocxResult>;
16
+ declare function createBilingualDocx(input: ArrayBuffer | Uint8Array, options: CreateBilingualDocxOptions): Promise<CreateBilingualDocxResult>;
16
17
  /** Bytes-in form of {@link readBilingualDocument}. */
17
18
  declare function readBilingualDocx(input: ArrayBuffer | Uint8Array): Promise<BilingualRow[]>;
18
19
  //#endregion
19
- export { CreateBilingualDocxResult, createBilingualDocx, readBilingualDocx };
20
+ export { CreateBilingualDocxOptions, CreateBilingualDocxResult, createBilingualDocx, readBilingualDocx };
@@ -1,3 +1,5 @@
1
+ import { FolioDocxReviewer } from "../../ai-edits/headless.js";
2
+ import { toArrayBuffer } from "../../utils/docxInput.js";
1
3
  import { ensureParaIds } from "../ensureParaIds.js";
2
4
  import { parseDocx } from "../parser.js";
3
5
  import { createDocx } from "../rezip.js";
@@ -11,16 +13,23 @@ import { createBilingualDocument, readBilingualDocument } from "./createBilingua
11
13
  * media, headers and footers carry over untouched.
12
14
  */
13
15
  async function createBilingualDocx(input, options) {
14
- const { document, rows, warnings } = createBilingualDocument(await parseDocx((await ensureParaIds(input)).docx, { preloadFonts: false }), options);
16
+ const stampedBuffer = await toArrayBuffer((await ensureParaIds(input)).docx);
17
+ const editableParagraphIds = new Set((await FolioDocxReviewer.fromBuffer(stampedBuffer)).snapshot().blocks.map(({ id }) => id));
18
+ const { document, warnings } = createBilingualDocument(await parseDocx(stampedBuffer, { preloadFonts: false }), {
19
+ ...options,
20
+ editableParagraphIds
21
+ });
22
+ const buffer = await createDocx(document);
15
23
  return {
16
- buffer: await createDocx(document),
17
- rows,
24
+ buffer,
25
+ rows: await readBilingualDocx(buffer),
18
26
  warnings
19
27
  };
20
28
  }
21
29
  /** Bytes-in form of {@link readBilingualDocument}. */
22
30
  async function readBilingualDocx(input) {
23
- return readBilingualDocument(await parseDocx(input, { preloadFonts: false }));
31
+ const buffer = await toArrayBuffer(input);
32
+ return readBilingualDocument(await parseDocx(buffer, { preloadFonts: false }), new Set((await FolioDocxReviewer.fromBuffer(buffer)).snapshot().blocks.map(({ id }) => id)));
24
33
  }
25
34
  //#endregion
26
35
  export { createBilingualDocx, readBilingualDocx };
@@ -1,6 +1,6 @@
1
1
  import { parseAnchorPosition, parseAnchorWrap, parseFill, parseOutline } from "./drawingUtils.js";
2
2
  import { ShapeTypeSchema, narrowEnum } from "./parserEnums.js";
3
- import { findAllDeep, findChildByLocalName, getAttribute, parseNumericAttribute } from "./xmlParser.js";
3
+ import { findAllDeep, findChildByLocalName, findChildren, getAttribute, getChildElements, parseNumericAttribute } from "./xmlParser.js";
4
4
  //#region src/docx/shapeParser.ts
5
5
  /** Convert OOXML rotation (1/60000ths of a degree) to degrees. */
6
6
  function rotToDegrees(rot) {
@@ -56,8 +56,29 @@ function hasUnsupportedGeometry(spPr) {
56
56
  if (!spPr) return false;
57
57
  const prstGeom = findChildByLocalName(spPr, "prstGeom");
58
58
  if (!prstGeom) return findChildByLocalName(spPr, "custGeom") !== null;
59
- if (findChildByLocalName(prstGeom, "avLst")?.elements?.some((child) => child.type === "element")) return true;
60
- return narrowEnum(getAttribute(prstGeom, null, "prst"), ShapeTypeSchema) === void 0;
59
+ const avLst = findChildByLocalName(prstGeom, "avLst");
60
+ const prst = getAttribute(prstGeom, null, "prst");
61
+ if (narrowEnum(prst, ShapeTypeSchema) === void 0) return true;
62
+ const adjustmentChildren = avLst ? getChildElements(avLst) : [];
63
+ if (adjustmentChildren.length === 0) return false;
64
+ const adjustments = findChildren(avLst, "a", "gd");
65
+ const adjustmentNames = new Set(adjustments.map((adjustment) => getAttribute(adjustment, null, "name")));
66
+ return !(prst === "rightBrace" && adjustments.length === 2 && adjustmentChildren.length === adjustments.length && adjustmentNames.size === 2 && adjustmentNames.has("adj1") && adjustmentNames.has("adj2") && adjustments.every((adjustment) => /^val\s+-?\d+$/u.test(getAttribute(adjustment, null, "fmla") ?? "")));
67
+ }
68
+ function parseGeometryAdjustments(spPr) {
69
+ const prstGeom = spPr ? findChildByLocalName(spPr, "prstGeom") : null;
70
+ const avLst = prstGeom ? findChildByLocalName(prstGeom, "avLst") : null;
71
+ if (!avLst) return;
72
+ const adjustments = [];
73
+ for (const adjustment of findChildren(avLst, "a", "gd")) {
74
+ const name = getAttribute(adjustment, null, "name");
75
+ const formula = getAttribute(adjustment, null, "fmla");
76
+ if (name !== null && formula !== null) adjustments.push({
77
+ name,
78
+ formula
79
+ });
80
+ }
81
+ return adjustments.length === 0 ? void 0 : adjustments;
61
82
  }
62
83
  function hasUnsupportedRgbColorModifiers(spPr) {
63
84
  for (const color of findAllDeep(spPr, "a", "srgbClr")) if (color.elements?.some((child) => child.type === "element")) return true;
@@ -94,6 +115,8 @@ function parseShape(node) {
94
115
  shapeType,
95
116
  size
96
117
  };
118
+ const geometryAdjustments = parseGeometryAdjustments(spPr);
119
+ if (geometryAdjustments !== void 0) shape.geometryAdjustments = geometryAdjustments;
97
120
  if (id !== void 0) shape.id = id;
98
121
  if (name !== void 0) shape.name = name;
99
122
  if (fill !== void 0) shape.fill = fill;
@@ -147,7 +147,7 @@ async function unzipDocx(buffer, options = {}) {
147
147
  if (lowerPath.endsWith(".xml") || lowerPath.endsWith(".rels")) {
148
148
  assertEntrySize(path, declaredSize, limits.maxXmlBytes);
149
149
  if (options.extractAllXml === false && !shouldExtractXmlPart(lowerPath)) continue;
150
- extractionTasks.push(file.async("text").then((xmlContent) => {
150
+ extractionTasks.push(() => file.async("text").then((xmlContent) => {
151
151
  assertExtractedSize(path, xmlContent.length, limits.maxXmlBytes);
152
152
  return {
153
153
  type: "xml",
@@ -163,7 +163,7 @@ async function unzipDocx(buffer, options = {}) {
163
163
  content.warnings.push(`Skipped oversized media file: ${path}; original entry preserved for round-trip.`);
164
164
  continue;
165
165
  }
166
- extractionTasks.push(file.async("arraybuffer").then((binaryContent) => {
166
+ extractionTasks.push(() => file.async("arraybuffer").then((binaryContent) => {
167
167
  if (binaryContent.byteLength > limits.maxMediaBytes) {
168
168
  content.warnings.push(`Skipped oversized media file: ${path}; original entry preserved for round-trip.`);
169
169
  return null;
@@ -178,7 +178,7 @@ async function unzipDocx(buffer, options = {}) {
178
178
  }));
179
179
  } else if (lowerPath.startsWith("word/fonts/")) {
180
180
  if (isEntryTooLarge(declaredSize, limits.maxFontBytes)) continue;
181
- extractionTasks.push(file.async("arraybuffer").then((binaryContent) => {
181
+ extractionTasks.push(() => file.async("arraybuffer").then((binaryContent) => {
182
182
  if (binaryContent.byteLength > limits.maxFontBytes) return null;
183
183
  return {
184
184
  type: "font",
@@ -188,7 +188,7 @@ async function unzipDocx(buffer, options = {}) {
188
188
  }));
189
189
  }
190
190
  }
191
- for (const extracted of await Promise.all(extractionTasks)) {
191
+ for (const extracted of await Promise.all(extractionTasks.map((extract) => extract()))) {
192
192
  if (!extracted) continue;
193
193
  if (extracted.type === "xml") {
194
194
  assignXmlContent(content, extracted);
@@ -15,6 +15,7 @@ import { resolveColor, resolveHighlightToCss } from "../../utils/colorResolver.j
15
15
  import { resolveThemeFont } from "../../utils/fontResolver.js";
16
16
  import { resolveShadingFill } from "../../utils/formatToStyle.js";
17
17
  import { decodeOoxmlSymbolCharacter } from "../../utils/ooxmlSymbol.js";
18
+ import { tableOfContentsStyleLevel } from "../../utils/tableOfContentsStyle.js";
18
19
  import { AUTO_PARAGRAPH_SPACING_PX, halfPointsToPixels, halfPointsToPoints, pointsToPixels } from "../../utils/units.js";
19
20
  import { getColumns } from "../sectionColumns.js";
20
21
  import { groupParagraphFrames } from "./paragraphFrames.js";
@@ -454,12 +455,6 @@ function buildImageRun(attrs, constrained, pmStart, pmEnd, trackedChange) {
454
455
  return run;
455
456
  }
456
457
  /**
457
- * Paragraph styleId pattern used by Word for TOC entries (TOC, TOC1, TOC2, …).
458
- * Hyperlinks inside these paragraphs must render in the paragraph's own colour,
459
- * not the Hyperlink character style — see {@link stripTocHyperlinkStyle}.
460
- */
461
- const TOC_STYLE_ID = /^TOC\d*$/iu;
462
- /**
463
458
  * In TOC paragraphs, strip the resolved Hyperlink character-style colour and
464
459
  * underline so the painter's link fallback doesn't fire. The PM doc keeps the
465
460
  * original marks so copy/paste out of a TOC still carries the Hyperlink
@@ -484,7 +479,7 @@ function paragraphToRuns(node, startPos, _options) {
484
479
  const pmAttrs = expectParagraphAttrs(node);
485
480
  const paraDefaults = paragraphRunDefaults(pmAttrs, theme);
486
481
  const paragraphStyleId = pmAttrs.styleId;
487
- const inTocParagraph = typeof paragraphStyleId === "string" && TOC_STYLE_ID.test(paragraphStyleId);
482
+ const inTocParagraph = pmAttrs._tableOfContentsLevel !== void 0 || tableOfContentsStyleLevel({ styleId: paragraphStyleId }) !== void 0;
488
483
  let leadingRenderedPageBreakPending = pmAttrs.renderedPageBreakBefore === true;
489
484
  function pushRunsForChild(child, childPos) {
490
485
  if (child.type.name === "renderedPageBreak") {
@@ -2,7 +2,7 @@ import { EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FONT_HINT_VALUES, FONT_THEME_V
2
2
  import { isParagraphDirection } from "../paragraphDirection.js";
3
3
  import { TRACKED_CHANGE_PROVENANCE_VALUES } from "../schema/marks.js";
4
4
  import { panic } from "better-result";
5
- import { isOoxmlSymbolCharacter } from "@stll/docx-core/model";
5
+ import { DRAWING_RAW_XML_MODES, isOoxmlSymbolCharacter } from "@stll/docx-core/model";
6
6
  //#region src/prosemirror/attrs/index.ts
7
7
  const SECTION_BREAK_TYPES = [
8
8
  "nextPage",
@@ -143,6 +143,7 @@ const readParagraphAttrs = (node) => {
143
143
  optionalString(attrs, "textId", "paragraph.attrs.textId", issues);
144
144
  optionalOneOf(attrs, "alignment", "paragraph.attrs.alignment", issues, PARAGRAPH_ALIGNMENT_VALUES);
145
145
  optionalString(attrs, "styleId", "paragraph.attrs.styleId", issues);
146
+ optionalNumber(attrs, "_tableOfContentsLevel", "paragraph.attrs._tableOfContentsLevel", issues);
146
147
  optionalBoolean(attrs, "kinsoku", "paragraph.attrs.kinsoku", issues);
147
148
  optionalBoolean(attrs, "overflowPunctuation", "paragraph.attrs.overflowPunctuation", issues);
148
149
  optionalBoolean(attrs, "suppressAutoHyphens", "paragraph.attrs.suppressAutoHyphens", issues);
@@ -357,6 +358,12 @@ const readImageAttrs = (node) => {
357
358
  optionalString(attrs, "hlinkHref", "image.attrs.hlinkHref", issues);
358
359
  optionalString(attrs, "hlinkRId", "image.attrs.hlinkRId", issues);
359
360
  optionalString(attrs, "_docxRawXml", "image.attrs._docxRawXml", issues);
361
+ optionalOneOf(attrs, "_docxRawXmlMode", "image.attrs._docxRawXmlMode", issues, Object.values(DRAWING_RAW_XML_MODES));
362
+ const rawXml = attrs["_docxRawXml"];
363
+ if (attrs["_docxRawXmlMode"] === DRAWING_RAW_XML_MODES.PRESERVE_ONLY && (typeof rawXml !== "string" || rawXml.trim().length === 0)) issues.push({
364
+ path: "image.attrs._docxRawXml",
365
+ message: "Preservation-only drawings require raw XML."
366
+ });
360
367
  optionalBoolean(attrs, "_docxObjectPreview", "image.attrs._docxObjectPreview", issues);
361
368
  return attrsResult(attrs, issues);
362
369
  };
@@ -422,6 +429,7 @@ const readShapeAttrs = (node) => {
422
429
  const issues = [];
423
430
  expectNodeType(node, "shape", issues);
424
431
  optionalString(attrs, "shapeType", "shape.attrs.shapeType", issues);
432
+ optionalString(attrs, "geometryAdjustments", "shape.attrs.geometryAdjustments", issues);
425
433
  optionalString(attrs, "shapeId", "shape.attrs.shapeId", issues);
426
434
  optionalNumber(attrs, "width", "shape.attrs.width", issues);
427
435
  optionalNumber(attrs, "height", "shape.attrs.height", issues);
@@ -105,7 +105,8 @@ const constrainImageSize = (width, height) => {
105
105
  };
106
106
  const imageNodeAt = (view, pos) => {
107
107
  const node = view.state.doc.nodeAt(pos);
108
- return node && node.type.name === "image" ? node : null;
108
+ if (!node || node.type.name !== "image") return null;
109
+ return expectImageAttrs(node)._docxRawXmlMode ? null : node;
109
110
  };
110
111
  /** Change the wrap mode of the image at `pos`. Returns whether it applied. */
111
112
  const applyImageWrapType = (view, pos, wrapType) => {
@@ -7,13 +7,27 @@ import { autospacingMatchesBase, hasAutospacingBaseSide } from "../autospacingBa
7
7
  import { applyRunFormattingOverrideAttrs } from "../extensions/marks/RunFormattingOverrideExtension.js";
8
8
  import { directionToBidi } from "../paragraphDirection.js";
9
9
  import { RUN_FORMATTING_MARK_NAMES } from "../runFormattingMarkNames.js";
10
+ import { parseShapeGeometryAdjustments } from "../shapeGeometryAdjustments.js";
10
11
  import { expectTextBoxAnchorAttrs } from "../textBoxAnchorAttrs.js";
11
12
  import { assertValidProseMirrorDocument } from "../validation.js";
12
13
  import { runShadingAttrsToShading } from "./runShadingMark.js";
13
14
  import { decodeSdtListItems, sdtPropertiesFromAttrs, sdtPropertiesMatchAttrs } from "./sdtAttrs.js";
14
15
  import { textFormattingToMarks } from "./toProseDoc.js";
16
+ import { panic } from "better-result";
17
+ import { DRAWING_RAW_XML_MODES } from "@stll/docx-core/model";
15
18
  import { Fragment } from "prosemirror-model";
16
19
  //#region src/prosemirror/conversion/fromProseDoc.ts
20
+ /**
21
+ * ProseMirror to Document Conversion
22
+ *
23
+ * Converts a ProseMirror document back to our Document type.
24
+ * This enables round-trip editing: DOCX -> Document -> PM -> Document -> DOCX
25
+ *
26
+ * Key responsibilities:
27
+ * - Coalesce consecutive text with same marks into single Runs
28
+ * - Preserve paragraph attributes (paraId, textId, formatting)
29
+ * - Handle marks -> TextFormatting conversion
30
+ */
17
31
  function normalizeShapeOutlineStyle(style) {
18
32
  if (!style) return;
19
33
  if (style in OUTLINE_STYLE_CSS_ALIASES) return OUTLINE_STYLE_CSS_ALIASES[style];
@@ -1256,14 +1270,18 @@ function createImageRun(node) {
1256
1270
  if (cropLeft !== void 0) crop.left = cropLeft;
1257
1271
  image.crop = crop;
1258
1272
  }
1259
- const drawingContent = {
1260
- type: "drawing",
1261
- image
1262
- };
1263
- if (attrs._docxRawXml) drawingContent.rawXml = attrs._docxRawXml;
1264
1273
  return {
1265
1274
  type: "run",
1266
- content: [drawingContent]
1275
+ content: [attrs._docxRawXmlMode === DRAWING_RAW_XML_MODES.PRESERVE_ONLY ? {
1276
+ type: "drawing",
1277
+ image,
1278
+ rawXml: attrs._docxRawXml ?? panic("Preservation-only ProseMirror image attrs must include raw XML."),
1279
+ rawXmlMode: DRAWING_RAW_XML_MODES.PRESERVE_ONLY
1280
+ } : {
1281
+ type: "drawing",
1282
+ image,
1283
+ ...attrs._docxRawXml ? { rawXml: attrs._docxRawXml } : {}
1284
+ }]
1267
1285
  };
1268
1286
  }
1269
1287
  /**
@@ -1280,6 +1298,8 @@ function createShapeRun(node) {
1280
1298
  }
1281
1299
  };
1282
1300
  if (attrs.shapeId) shape.id = attrs.shapeId;
1301
+ const geometryAdjustments = parseShapeGeometryAdjustments(attrs.geometryAdjustments);
1302
+ if (geometryAdjustments !== void 0) shape.geometryAdjustments = geometryAdjustments;
1283
1303
  const shapeTransform = parseTransformAttr(attrs.transform);
1284
1304
  if (shapeTransform) shape.transform = shapeTransform;
1285
1305
  const wrap = { type: attrs.wrapType || "inline" };
@@ -1,6 +1,7 @@
1
1
  import { resolveColorValueToHex } from "../../docx/drawingUtils.js";
2
2
  import { createStyleEngine } from "../../style-engine/styleEngine.js";
3
3
  import { mergeParagraphFormatting, mergeParagraphTabStops } from "../../utils/paragraphFormattingMerge.js";
4
+ import { tableOfContentsStyleLevel } from "../../utils/tableOfContentsStyle.js";
4
5
  import { mergeTextFormatting } from "../../utils/textFormattingMerge.js";
5
6
  import { emuToPixels } from "../../utils/units.js";
6
7
  import { setAutospacingBaseValue } from "../autospacingBase.js";
@@ -13,8 +14,6 @@ import { marksToTextFormatting } from "./fromProseDoc.js";
13
14
  import { shadingToRunShadingAttrs } from "./runShadingMark.js";
14
15
  import { sdtAttrsFromProperties } from "./sdtAttrs.js";
15
16
  //#region src/prosemirror/conversion/toProseDoc.ts
16
- const TOC_STYLE_ID = /^TOC\d*$/iu;
17
- const isTocStyleId = (styleId) => styleId !== void 0 && TOC_STYLE_ID.test(styleId);
18
17
  /**
19
18
  * Build a `nextTextBoxGroupId()` generator salted with a random per-load
20
19
  * nonce, so minted text-box anchor ids (`<salt>:<group>:<index>`) are unique
@@ -128,7 +127,7 @@ function convertBlockSdt(blockSdt, convertBlocks) {
128
127
  */
129
128
  function convertParagraph(paragraph, styleResolver, nextHyperlinkInstanceIndex, activeCommentIds, extraRunFormatting, tableParagraphOverlay, textBoxAnchors) {
130
129
  const attrs = paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOverlay);
131
- const isTocParagraph = isTocStyleId(paragraph.formatting?.styleId);
130
+ const isTocParagraph = attrs._tableOfContentsLevel !== void 0;
132
131
  const inlineNodes = [];
133
132
  let inlineOffset = 0;
134
133
  let bookmarksArr;
@@ -280,10 +279,16 @@ function canCarryTrackedRunMark(node, markType) {
280
279
  function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOverlay) {
281
280
  const formatting = paragraph.formatting;
282
281
  const styleId = formatting?.styleId;
282
+ const styleName = styleId ? styleResolver?.getStyle(styleId)?.name : void 0;
283
+ const tableOfContentsLevel = tableOfContentsStyleLevel({
284
+ styleId,
285
+ ...styleName ? { styleName } : {}
286
+ });
283
287
  const attrs = {};
284
288
  if (paragraph.paraId) attrs.paraId = paragraph.paraId;
285
289
  if (paragraph.textId) attrs.textId = paragraph.textId;
286
290
  if (styleId) attrs.styleId = styleId;
291
+ if (tableOfContentsLevel !== void 0) attrs._tableOfContentsLevel = tableOfContentsLevel;
287
292
  if (formatting?.numPr) attrs.numPr = formatting.numPr;
288
293
  if (formatting?.numPrFromStyle) attrs.numPrFromStyle = formatting.numPrFromStyle;
289
294
  if (paragraph.listRendering?.numFmt) attrs.listNumFmt = paragraph.listRendering.numFmt;
@@ -350,7 +355,7 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
350
355
  set("runInWithNext", formatting?.runInWithNext ?? stylePpr?.runInWithNext);
351
356
  set("outlineLevel", formatting?.outlineLevel ?? stylePpr?.outlineLevel);
352
357
  set("direction", directionFromBidi(formatting?.bidi ?? stylePpr?.bidi));
353
- set("defaultTextFormatting", resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolver, { includeParagraphMarkRunProperties: !isTocStyleId(styleId) }));
358
+ set("defaultTextFormatting", resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolver, { includeParagraphMarkRunProperties: tableOfContentsLevel === void 0 }));
354
359
  if (!formatting?.numPr && stylePpr?.numPr && stylePpr.numPr.numId !== 0) {
355
360
  attrs.numPr = stylePpr.numPr;
356
361
  attrs.numPrFromStyle = stylePpr.numPr;
@@ -1050,7 +1055,11 @@ function convertRunContent(content, marks, formatting, textBoxAnchors) {
1050
1055
  return [];
1051
1056
  case "renderedPageBreak": return [schema.node("renderedPageBreak").mark(marks)];
1052
1057
  case "tab": return [schema.node("tab", content.positional ? { positional: content.positional } : void 0).mark(marks)];
1053
- case "drawing": return [withHyperlinkBoundaryMarks(convertImage(content.image, content.rawXml), marks)];
1058
+ case "drawing": return [withHyperlinkBoundaryMarks(convertImage({
1059
+ image: content.image,
1060
+ rawXml: content.rawXml,
1061
+ rawXmlMode: content.rawXmlMode
1062
+ }), marks)];
1054
1063
  case "shape": {
1055
1064
  const shp = content.shape;
1056
1065
  if (shp.textBody) {
@@ -1089,7 +1098,7 @@ function withHyperlinkBoundaryMarks(node, marks) {
1089
1098
  if (!marks.some((mark) => mark.type.name === "hyperlink")) return node;
1090
1099
  return node.mark(marks);
1091
1100
  }
1092
- function convertImage(image, rawXml) {
1101
+ function convertImage({ image, rawXml, rawXmlMode }) {
1093
1102
  const imageSize = image.size;
1094
1103
  const widthPx = imageSize?.width ? emuToPixels(imageSize.width) : void 0;
1095
1104
  const heightPx = imageSize?.height ? emuToPixels(imageSize.height) : void 0;
@@ -1190,6 +1199,7 @@ function convertImage(image, rawXml) {
1190
1199
  hlinkHref: image.hlinkHref,
1191
1200
  hlinkRId: image.hlinkRId,
1192
1201
  _docxRawXml: rawXml,
1202
+ _docxRawXmlMode: rawXmlMode,
1193
1203
  _docxObjectPreview: rawXml !== void 0 && /<(?:[A-Za-z_][\w.-]*:)?object(?:\s|>)/u.test(rawXml)
1194
1204
  });
1195
1205
  }
@@ -1347,6 +1357,7 @@ function convertShape(shape) {
1347
1357
  };
1348
1358
  return schema.node("shape", {
1349
1359
  shapeType: shapeAttrs.shapeType ?? "rect",
1360
+ geometryAdjustments: shape.geometryAdjustments === void 0 ? void 0 : JSON.stringify(shape.geometryAdjustments),
1350
1361
  shapeId: shape.id,
1351
1362
  width: widthPx,
1352
1363
  height: heightPx,
@@ -6,6 +6,8 @@ import { EditorState } from "prosemirror-state";
6
6
  type ResolvedStyleAttrs = {
7
7
  paragraphFormatting?: document_d_exports.ParagraphFormatting;
8
8
  runFormatting?: document_d_exports.TextFormatting;
9
+ /** Canonical OOXML style name, used when the document-local style id is localized. */
10
+ styleName?: string;
9
11
  /**
10
12
  * Numbering definitions from the document package. When the applied style
11
13
  * carries a `w:numPr`, these resolve the numbering level into the list
@@ -1,5 +1,6 @@
1
1
  import { paragraphToStyle } from "../../../utils/formatToStyle.js";
2
2
  import { collectHeadings } from "../../../utils/headingCollector.js";
3
+ import { tableOfContentsStyleLevel } from "../../../utils/tableOfContentsStyle.js";
3
4
  import { expectParagraphAttrs } from "../../attrs/index.js";
4
5
  import { autospacingMatchesBase } from "../../autospacingBase.js";
5
6
  import { directionIsRtl } from "../../paragraphDirection.js";
@@ -215,6 +216,7 @@ const paragraphNodeSpec = {
215
216
  listAbstractNumId: { default: null },
216
217
  listStartOverride: { default: null },
217
218
  styleId: { default: null },
219
+ _tableOfContentsLevel: { default: null },
218
220
  borders: { default: null },
219
221
  shading: { default: null },
220
222
  tabs: { default: null },
@@ -248,11 +250,13 @@ const paragraphNodeSpec = {
248
250
  const paraId = element.dataset["paraId"];
249
251
  const alignment = element.dataset["alignment"];
250
252
  const styleId = element.dataset["styleId"];
253
+ const tableOfContentsLevel = Number(element.dataset["tableOfContentsLevel"]);
251
254
  const sectionBreakType = element.dataset["sectionBreak"];
252
255
  const attrs = {
253
256
  ...paraId ? { paraId } : {},
254
257
  ...alignment ? { alignment } : {},
255
258
  ...styleId ? { styleId } : {},
259
+ ...Number.isSafeInteger(tableOfContentsLevel) && tableOfContentsLevel > 0 ? { _tableOfContentsLevel: tableOfContentsLevel } : {},
256
260
  ...sectionBreakType ? { sectionBreakType } : {}
257
261
  };
258
262
  const styleAttrs = extractParagraphAttrsFromStyle(element);
@@ -291,6 +295,7 @@ const paragraphNodeSpec = {
291
295
  if (attrs.paraId) domAttrs["data-para-id"] = attrs.paraId;
292
296
  if (attrs.alignment) domAttrs["data-alignment"] = attrs.alignment;
293
297
  if (attrs.styleId) domAttrs["data-style-id"] = attrs.styleId;
298
+ if (typeof attrs._tableOfContentsLevel === "number") domAttrs["data-table-of-contents-level"] = String(attrs._tableOfContentsLevel);
294
299
  if (attrs.listMarker) domAttrs["data-list-marker"] = attrs.listMarker;
295
300
  if (directionIsRtl(attrs.direction)) domAttrs["dir"] = "rtl";
296
301
  if (attrs.sectionBreakType) {
@@ -460,10 +465,14 @@ function makeApplyStyle(schema) {
460
465
  seen.add(pos);
461
466
  const newAttrs = {
462
467
  ...node.attrs,
463
- styleId
468
+ styleId,
469
+ _tableOfContentsLevel: tableOfContentsStyleLevel({ styleId }) ?? null
464
470
  };
465
471
  if (resolvedAttrs) {
466
- Object.assign(newAttrs, paragraphAttrsFromResolvedStyle(resolvedAttrs));
472
+ Object.assign(newAttrs, paragraphAttrsFromResolvedStyle(resolvedAttrs, {
473
+ styleId,
474
+ ...resolvedAttrs.styleName ? { styleName: resolvedAttrs.styleName } : {}
475
+ }));
467
476
  const listAttrs = listAttrsFromResolvedStyle(resolvedAttrs, resolvedAttrs.numbering);
468
477
  if (listAttrs) Object.assign(newAttrs, listAttrs);
469
478
  }
@@ -534,7 +543,10 @@ const ParagraphExtension = createNodeExtension({
534
543
  hangingIndent: hanging ?? false
535
544
  }),
536
545
  applyStyle: (styleId, resolvedAttrs) => applyStyleFn(styleId, resolvedAttrs),
537
- clearStyle: () => setParagraphAttr("styleId", null),
546
+ clearStyle: () => setParagraphAttrsCmd({
547
+ styleId: null,
548
+ _tableOfContentsLevel: null
549
+ }),
538
550
  insertSectionBreak: (breakType) => setParagraphAttr("sectionBreakType", breakType),
539
551
  removeSectionBreak: () => setParagraphAttr("sectionBreakType", null),
540
552
  generateTOC: () => (state, dispatch) => {
@@ -53,6 +53,7 @@ const clearIndentOnBackspace = (state, dispatch) => {
53
53
  const INHERITED_PARA_ATTRS = [
54
54
  "defaultTextFormatting",
55
55
  "styleId",
56
+ "_tableOfContentsLevel",
56
57
  "lineSpacing",
57
58
  "lineSpacingRule",
58
59
  "snapToGrid",
@@ -77,11 +78,15 @@ function applyNextParagraphStyle(tr, sourcePara, newPara, resolver) {
77
78
  const nextStyleId = resolver.getNextStyleId(sourcePara.attrs["styleId"]);
78
79
  if (!nextStyleId) return false;
79
80
  const resolved = resolver.resolveParagraphStyle(nextStyleId);
81
+ const styleName = resolver.getStyle(nextStyleId)?.name;
80
82
  const { $from } = tr.selection;
81
83
  tr.setNodeMarkup($from.before(), void 0, {
82
84
  ...newPara.attrs,
83
85
  styleId: nextStyleId,
84
- ...paragraphAttrsFromResolvedStyle(resolved)
86
+ ...paragraphAttrsFromResolvedStyle(resolved, {
87
+ styleId: nextStyleId,
88
+ ...styleName ? { styleName } : {}
89
+ })
85
90
  });
86
91
  tr.setStoredMarks(resolved.runFormatting ? textFormattingToMarks(resolved.runFormatting, tr.doc.type.schema) : []);
87
92
  return true;
@@ -42,6 +42,7 @@ const ImageExtension = createNodeExtension({
42
42
  hlinkHref: { default: null },
43
43
  hlinkRId: { default: null },
44
44
  _docxRawXml: { default: null },
45
+ _docxRawXmlMode: { default: null },
45
46
  _docxObjectPreview: { default: null }
46
47
  },
47
48
  parseDOM: [{
@@ -1,3 +1,4 @@
1
+ import { document_d_exports } from "../../../types/document.js";
1
2
  import { ShapeAttrs as ShapeAttrs$1 } from "../../schema/nodes.js";
2
3
  import { NodeExtension } from "../types.js";
3
4
  //#region src/prosemirror/extensions/nodes/ShapeExtension.d.ts
@@ -7,6 +8,11 @@ declare function sanitizeTransform(value: string | null | undefined): string | n
7
8
  declare function sanitizeSvgId(value: string | null | undefined): string | null;
8
9
  declare function sanitizeShapeDimension(value: number | null | undefined, fallback: number): number;
9
10
  declare function strokeDashArrayForOutlineStyle(outlineStyle: string | undefined): string | undefined;
11
+ type RightBracePaths = {
12
+ fill: string;
13
+ outline: string;
14
+ };
15
+ declare function buildRightBracePaths(w: number, h: number, adjustments: readonly document_d_exports.ShapeGeometryAdjustment[]): RightBracePaths;
10
16
  /**
11
17
  * Build the `points` string for a polygon-based shape preset.
12
18
  *
@@ -26,4 +32,4 @@ type GradientStop = {
26
32
  declare function parseGradientStops(raw: string | undefined): GradientStop[];
27
33
  declare const ShapeExtension: (options?: Partial<Record<string, unknown>> | undefined) => NodeExtension;
28
34
  //#endregion
29
- export { ShapeAttrs, ShapeExtension, buildShapePolygonPoints, parseGradientStops, sanitizeColor, sanitizeShapeDimension, sanitizeSvgId, sanitizeTransform, strokeDashArrayForOutlineStyle };
35
+ export { ShapeAttrs, ShapeExtension, buildRightBracePaths, buildShapePolygonPoints, parseGradientStops, sanitizeColor, sanitizeShapeDimension, sanitizeSvgId, sanitizeTransform, strokeDashArrayForOutlineStyle };
@@ -1,4 +1,5 @@
1
1
  import { expectShapeAttrs } from "../../attrs/index.js";
2
+ import { parseShapeGeometryAdjustments } from "../../shapeGeometryAdjustments.js";
2
3
  import { createNodeExtension } from "../create.js";
3
4
  //#region src/prosemirror/extensions/nodes/ShapeExtension.ts
4
5
  /**
@@ -123,6 +124,40 @@ function setNum(el, name, value) {
123
124
  function fmt(n) {
124
125
  return Number.isInteger(n) ? String(n) : Number(n.toFixed(3)).toString();
125
126
  }
127
+ const RIGHT_BRACE_DEFAULT_THICKNESS = 8333;
128
+ const RIGHT_BRACE_DEFAULT_CUSP = 5e4;
129
+ const GEOMETRY_PERCENT_SCALE = 1e5;
130
+ const geometryAdjustment = (adjustments, name, fallback) => {
131
+ const authored = adjustments.find((adjustment) => adjustment.name === name);
132
+ if (!authored) return fallback;
133
+ const match = /^val\s+(-?\d+)$/u.exec(authored.formula);
134
+ if (!match) return fallback;
135
+ return Number(match.at(1));
136
+ };
137
+ function buildRightBracePaths(w, h, adjustments) {
138
+ const shortSide = Math.min(w, h);
139
+ const cuspAdjustment = Math.min(GEOMETRY_PERCENT_SCALE, Math.max(0, geometryAdjustment(adjustments, "adj2", RIGHT_BRACE_DEFAULT_CUSP)));
140
+ const maxThickness = Math.min(cuspAdjustment, GEOMETRY_PERCENT_SCALE - cuspAdjustment) / 2 * h / shortSide;
141
+ const radius = shortSide * Math.min(maxThickness, Math.max(0, geometryAdjustment(adjustments, "adj1", RIGHT_BRACE_DEFAULT_THICKNESS))) / GEOMETRY_PERCENT_SCALE;
142
+ const halfWidth = w / 2;
143
+ const cusp = h * cuspAdjustment / GEOMETRY_PERCENT_SCALE;
144
+ const upperStemEnd = cusp - radius;
145
+ const lowerStemStart = cusp + radius;
146
+ const bottomCurveStart = h - radius;
147
+ const commands = [
148
+ "M 0 0",
149
+ `A ${fmt(halfWidth)} ${fmt(radius)} 0 0 1 ${fmt(halfWidth)} ${fmt(radius)}`,
150
+ `L ${fmt(halfWidth)} ${fmt(upperStemEnd)}`,
151
+ `A ${fmt(halfWidth)} ${fmt(radius)} 0 0 0 ${fmt(w)} ${fmt(cusp)}`,
152
+ `A ${fmt(halfWidth)} ${fmt(radius)} 0 0 0 ${fmt(halfWidth)} ${fmt(lowerStemStart)}`,
153
+ `L ${fmt(halfWidth)} ${fmt(bottomCurveStart)}`,
154
+ `A ${fmt(halfWidth)} ${fmt(radius)} 0 0 1 0 ${fmt(h)}`
155
+ ].join(" ");
156
+ return {
157
+ fill: `${commands} Z`,
158
+ outline: commands
159
+ };
160
+ }
126
161
  /**
127
162
  * Build the `points` string for a polygon-based shape preset.
128
163
  *
@@ -209,7 +244,7 @@ function buildShapePolygonPoints(type, w, h) {
209
244
  * displays. The original `<a:prstGeom prst>` value round-trips through the
210
245
  * model regardless of what the renderer chooses to draw.
211
246
  */
212
- function createShapeElement(type, w, h) {
247
+ function createShapeElement(type, w, h, adjustments) {
213
248
  switch (type) {
214
249
  case "ellipse":
215
250
  case "oval": {
@@ -238,6 +273,19 @@ function createShapeElement(type, w, h) {
238
273
  setNum(el, "y2", h / 2);
239
274
  return el;
240
275
  }
276
+ case "rightBrace": {
277
+ const paths = buildRightBracePaths(w, h, adjustments);
278
+ const group = document.createElementNS(SVG_NS, "g");
279
+ const fill = document.createElementNS(SVG_NS, "path");
280
+ fill.setAttribute("d", paths.fill);
281
+ fill.setAttribute("stroke", "none");
282
+ group.append(fill);
283
+ const outline = document.createElementNS(SVG_NS, "path");
284
+ outline.setAttribute("d", paths.outline);
285
+ outline.setAttribute("fill", "none");
286
+ group.append(outline);
287
+ return group;
288
+ }
241
289
  default: {
242
290
  const points = buildShapePolygonPoints(type, w, h);
243
291
  if (points !== null) {
@@ -320,6 +368,7 @@ const ShapeExtension = createNodeExtension({
320
368
  atom: true,
321
369
  attrs: {
322
370
  shapeType: { default: "rect" },
371
+ geometryAdjustments: { default: null },
323
372
  shapeId: { default: null },
324
373
  width: { default: 100 },
325
374
  height: { default: 80 },
@@ -362,6 +411,7 @@ const ShapeExtension = createNodeExtension({
362
411
  const outlineTailEnd = parseShapeLineEnd(d["outlineTailEnd"]);
363
412
  return {
364
413
  shapeType: d["shapeType"] || "rect",
414
+ ...d["geometryAdjustments"] ? { geometryAdjustments: d["geometryAdjustments"] } : {},
365
415
  ...d["shapeId"] ? { shapeId: d["shapeId"] } : {},
366
416
  ...d["width"] ? { width: Number(d["width"]) } : {},
367
417
  ...d["height"] ? { height: Number(d["height"]) } : {},
@@ -403,6 +453,7 @@ const ShapeExtension = createNodeExtension({
403
453
  class: "docx-shape",
404
454
  "data-shape-type": attrs.shapeType || "rect"
405
455
  };
456
+ if (attrs.geometryAdjustments) domAttrs["data-geometry-adjustments"] = attrs.geometryAdjustments;
406
457
  if (attrs.shapeId) domAttrs["data-shape-id"] = attrs.shapeId;
407
458
  domAttrs["data-width"] = String(w);
408
459
  domAttrs["data-height"] = String(h);
@@ -489,7 +540,8 @@ const ShapeExtension = createNodeExtension({
489
540
  defs.append(gradient);
490
541
  svg.append(defs);
491
542
  }
492
- const shapeEl = createShapeElement(attrs.shapeType || "rect", w, h);
543
+ const geometryAdjustments = parseShapeGeometryAdjustments(attrs.geometryAdjustments) ?? [];
544
+ const shapeEl = createShapeElement(attrs.shapeType || "rect", w, h, geometryAdjustments);
493
545
  const strokeDasharray = strokeDashArrayForOutlineStyle(attrs.outlineStyle);
494
546
  if (strokeDasharray) shapeEl.setAttribute("stroke-dasharray", strokeDasharray);
495
547
  svg.append(shapeEl);
@@ -501,4 +553,4 @@ const ShapeExtension = createNodeExtension({
501
553
  }
502
554
  });
503
555
  //#endregion
504
- export { ShapeExtension, buildShapePolygonPoints, parseGradientStops, sanitizeColor, sanitizeShapeDimension, sanitizeSvgId, sanitizeTransform, strokeDashArrayForOutlineStyle };
556
+ export { ShapeExtension, buildRightBracePaths, buildShapePolygonPoints, parseGradientStops, sanitizeColor, sanitizeShapeDimension, sanitizeSvgId, sanitizeTransform, strokeDashArrayForOutlineStyle };
@@ -102,6 +102,8 @@ type ParagraphAttrs = {
102
102
  /** Numbering start override for this numId/level. */
103
103
  listStartOverride?: number;
104
104
  styleId?: string;
105
+ /** Imported built-in TOC entry level, resolved from the canonical style name. */
106
+ _tableOfContentsLevel?: number;
105
107
  borders?: {
106
108
  top?: document_d_exports.BorderSpec;
107
109
  bottom?: document_d_exports.BorderSpec;
@@ -275,6 +277,8 @@ type ImageAttrs = {
275
277
  hlinkRId?: string;
276
278
  /** Original OOXML for opaque/unsupported DOCX drawings. */
277
279
  _docxRawXml?: string;
280
+ /** Raw XML preserved without an editable image projection. */
281
+ _docxRawXmlMode?: document_d_exports.DrawingRawXmlMode;
278
282
  /** Embedded-object previews use their authored box as the exact line height. */
279
283
  _docxObjectPreview?: boolean;
280
284
  };
@@ -382,6 +386,8 @@ type BlockSdtAttrs = {
382
386
  type ShapeAttrs = {
383
387
  /** Shape type preset */
384
388
  shapeType?: string;
389
+ /** Preset geometry adjustments serialized as JSON. */
390
+ geometryAdjustments?: string;
385
391
  /** Unique identifier */
386
392
  shapeId?: string;
387
393
  /** Width in pixels */
@@ -0,0 +1,5 @@
1
+ import { document_d_exports } from "../types/document.js";
2
+ //#region src/prosemirror/shapeGeometryAdjustments.d.ts
3
+ declare const parseShapeGeometryAdjustments: (raw: string | undefined) => document_d_exports.ShapeGeometryAdjustment[] | undefined;
4
+ //#endregion
5
+ export { parseShapeGeometryAdjustments };
@@ -0,0 +1,24 @@
1
+ //#region src/prosemirror/shapeGeometryAdjustments.ts
2
+ const MAX_ADJUSTMENT_COUNT = 32;
3
+ const MAX_ADJUSTMENT_NAME_LENGTH = 64;
4
+ const MAX_ADJUSTMENT_FORMULA_LENGTH = 128;
5
+ const parseShapeGeometryAdjustments = (raw) => {
6
+ if (!raw) return;
7
+ try {
8
+ const parsed = JSON.parse(raw);
9
+ if (!Array.isArray(parsed) || parsed.length > MAX_ADJUSTMENT_COUNT) return;
10
+ const adjustments = [];
11
+ for (const item of parsed) {
12
+ if (typeof item !== "object" || item === null || !("name" in item) || typeof item.name !== "string" || item.name.length === 0 || item.name.length > MAX_ADJUSTMENT_NAME_LENGTH || !("formula" in item) || typeof item.formula !== "string" || item.formula.length === 0 || item.formula.length > MAX_ADJUSTMENT_FORMULA_LENGTH) return;
13
+ adjustments.push({
14
+ name: item.name,
15
+ formula: item.formula
16
+ });
17
+ }
18
+ return adjustments.length === 0 ? void 0 : adjustments;
19
+ } catch {
20
+ return;
21
+ }
22
+ };
23
+ //#endregion
24
+ export { parseShapeGeometryAdjustments };
@@ -1,13 +1,17 @@
1
1
  import { NumberingMap } from "../../docx/numberingParser.js";
2
2
  import { ResolvedParagraphStyle } from "./styleResolver.js";
3
3
  //#region src/prosemirror/styles/resolvedStyleAttrs.d.ts
4
+ type ResolvedStyleIdentity = {
5
+ styleId: string;
6
+ styleName?: string;
7
+ };
4
8
  /**
5
9
  * The paragraph attrs a style definition controls. Applying a style resets
6
10
  * every one of these to the style's value (or `null` to clear), so a prior
7
11
  * style's properties (e.g. a heading's spacing) never leak through. Returns
8
12
  * a partial attrs object to merge over the paragraph's existing attrs.
9
13
  */
10
- declare function paragraphAttrsFromResolvedStyle(resolved: ResolvedParagraphStyle): Record<string, unknown>;
14
+ declare function paragraphAttrsFromResolvedStyle(resolved: ResolvedParagraphStyle, identity: ResolvedStyleIdentity): Record<string, unknown>;
11
15
  /**
12
16
  * The list attrs a style's `w:pPr/w:numPr` controls (numbering reference plus
13
17
  * the baked marker-rendering attrs that `toProseDoc` normally derives from
@@ -1,4 +1,5 @@
1
1
  import { computeListRendering } from "../../docx/numberingParser.js";
2
+ import { tableOfContentsStyleLevel } from "../../utils/tableOfContentsStyle.js";
2
3
  import { setAutospacingBaseValue } from "../autospacingBase.js";
3
4
  //#region src/prosemirror/styles/resolvedStyleAttrs.ts
4
5
  /**
@@ -17,7 +18,7 @@ import { setAutospacingBaseValue } from "../autospacingBase.js";
17
18
  * style's properties (e.g. a heading's spacing) never leak through. Returns
18
19
  * a partial attrs object to merge over the paragraph's existing attrs.
19
20
  */
20
- function paragraphAttrsFromResolvedStyle(resolved) {
21
+ function paragraphAttrsFromResolvedStyle(resolved, identity) {
21
22
  const ppr = resolved.paragraphFormatting;
22
23
  const runFormatting = resolved.runFormatting;
23
24
  const hasRunFormatting = !!runFormatting && Object.keys(runFormatting).length > 0;
@@ -40,7 +41,8 @@ function paragraphAttrsFromResolvedStyle(resolved) {
40
41
  outlineLevel: ppr?.outlineLevel ?? null,
41
42
  borders: ppr?.borders ?? null,
42
43
  defaultTextFormatting: hasRunFormatting ? runFormatting : null,
43
- _autospacingBase: autospacingBaseFromResolvedParagraphFormatting(ppr)
44
+ _autospacingBase: autospacingBaseFromResolvedParagraphFormatting(ppr),
45
+ _tableOfContentsLevel: tableOfContentsStyleLevel(identity) ?? null
44
46
  };
45
47
  }
46
48
  function autospacingBaseFromResolvedParagraphFormatting(ppr) {
package/dist/redline.js CHANGED
@@ -3,6 +3,7 @@ import { createFolioAITextRangeHandle } from "./ai-edits/snapshot.js";
3
3
  import "./document-operations.js";
4
4
  import { pairFolioDocumentStories } from "./document-stories.js";
5
5
  import { resolveFolioDocumentPrivacyTransforms, rewriteDocxMetadataPrivacy } from "./docx/metadataPrivacy.js";
6
+ import { GenerateRedlineDocxOperationLimitError } from "./redlineOperationLimit.js";
6
7
  import { alignFolioBlocks } from "./version-comparison.js";
7
8
  import { TaggedError, panic } from "better-result";
8
9
  //#region src/redline.ts
@@ -71,11 +72,14 @@ const formattingSegments = (baseBlock, revisedBlock) => {
71
72
  if (hasInlineFormatting(formatting)) {
72
73
  const previous = segments.at(-1);
73
74
  if (previous && previous.endOffset === textOffset && sameInlineFormatting(previous.formatting, formatting)) previous.endOffset += length;
74
- else segments.push({
75
- startOffset: textOffset,
76
- endOffset: textOffset + length,
77
- formatting
78
- });
75
+ else {
76
+ if (segments.length >= 1e4) throw new GenerateRedlineDocxOperationLimitError({ message: "The document comparison exceeds the generated operation limit." });
77
+ segments.push({
78
+ startOffset: textOffset,
79
+ endOffset: textOffset + length,
80
+ formatting
81
+ });
82
+ }
79
83
  }
80
84
  textOffset += length;
81
85
  baseRunOffset += length;
@@ -199,7 +203,10 @@ const generateRedlineDocx = async (base, revised, options = {}) => {
199
203
  const skipped = [];
200
204
  const unprocessedStories = [];
201
205
  let operationSequence = 0;
202
- const nextOperationId = () => `redline-${++operationSequence}`;
206
+ const nextOperationId = () => {
207
+ if (operationSequence >= 1e4) throw new GenerateRedlineDocxOperationLimitError({ message: "The document comparison exceeds the generated operation limit." });
208
+ return `redline-${++operationSequence}`;
209
+ };
203
210
  for (const pair of pairFolioDocumentStories(baseStories, revisedStories)) {
204
211
  if (!pair.baseStory) {
205
212
  unprocessedStories.push({
@@ -0,0 +1,8 @@
1
+ //#region src/redlineOperationLimit.d.ts
2
+ declare const MAX_GENERATED_REDLINE_OPERATIONS = 10000;
3
+ declare const GenerateRedlineDocxOperationLimitError_base: import("better-result").TaggedErrorClass<"GenerateRedlineDocxOperationLimitError">;
4
+ declare class GenerateRedlineDocxOperationLimitError extends GenerateRedlineDocxOperationLimitError_base<{
5
+ message: string;
6
+ }> {}
7
+ //#endregion
8
+ export { GenerateRedlineDocxOperationLimitError, MAX_GENERATED_REDLINE_OPERATIONS };
@@ -0,0 +1,6 @@
1
+ import { TaggedError } from "better-result";
2
+ //#region src/redlineOperationLimit.ts
3
+ const MAX_GENERATED_REDLINE_OPERATIONS = 1e4;
4
+ var GenerateRedlineDocxOperationLimitError = class extends TaggedError("GenerateRedlineDocxOperationLimitError") {};
5
+ //#endregion
6
+ export { GenerateRedlineDocxOperationLimitError, MAX_GENERATED_REDLINE_OPERATIONS };
package/dist/server.d.ts CHANGED
@@ -20,10 +20,10 @@ import { FOLIO_DOCX_CONFORMANCE_CHECKS, FOLIO_DOCX_CONFORMANCE_ISSUE_CODES, FOLI
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
22
  import { BilingualBorders, BilingualParagraphRef, BilingualRow, BilingualRowKind, BilingualTableParagraphRef, CreateBilingualDocumentOptions, CreateBilingualDocumentResult, InvalidBilingualDocumentOptionsError, createBilingualDocument, readBilingualDocument } from "./docx/server/createBilingualDocument.js";
23
- import { CreateBilingualDocxResult, createBilingualDocx, readBilingualDocx } from "./docx/server/createBilingualDocx.js";
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";
26
26
  import { FOLIO_DOCX_PACKAGE_INSPECTION_DEFAULTS, FOLIO_DOCX_PACKAGE_INSPECTION_ERROR_CODES, FOLIO_DOCX_PACKAGE_INSPECTION_VERSION, FolioDocxInspectedXmlPart, FolioDocxPackageInspection, FolioDocxPackageInspectionError, FolioDocxPackageInspectionErrorCode, FolioDocxPackageInspectionLimits, FolioDocxPackagePart, FolioDocxPackagePartKind, InspectDocxPackageOptions, inspectDocxPackage } from "./docx/server/inspectDocxPackage.js";
27
27
  import { GenerateRedlineDocxOptions, GenerateRedlineDocxResult, GenerateRedlineUnprocessedStory, InvalidGenerateRedlineDocxOptionsError, generateRedlineDocx } from "./redline.js";
28
28
  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";
29
- export { type ApplyDocxXmlPatchProposalArgs, type ApplyFolioAIEditsToBufferOptions, type ApplyFolioAIEditsToBufferResult, type BilingualBorders, type BilingualParagraphRef, type BilingualRow, type BilingualRowKind, type BilingualTableParagraphRef, type CreateBilingualDocumentOptions, type CreateBilingualDocumentResult, 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, 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, type GenerateRedlineDocxOptions, type GenerateRedlineDocxResult, type GenerateRedlineUnprocessedStory, HEADING_LEVELS, type HeadingLevel, type InspectDocxPackageOptions, InvalidBilingualDocumentOptionsError, InvalidFolioDocumentOperationBatchError, InvalidFolioDocumentPrivacyOptionsError, InvalidFolioDocxXmlPatchProposalError, InvalidFolioDocxXmlPatchProposalOptionsError, InvalidFolioReportBuilderOptionsError, InvalidFolioVersionComparisonOptionsError, InvalidGenerateRedlineDocxOptionsError, 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, normalizeFolioAIBlockText, pageBreak, paragraph, parseDocx, parseFolioDocumentOperationBatch, parseFolioDocxXmlPatchProposal, readBilingualDocument, readBilingualDocx, readFolioDocumentSection, replyToComment, rewriteDocxMetadataPrivacy, run, table, validateDocxConformance };
29
+ 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, 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, type GenerateRedlineDocxOptions, type GenerateRedlineDocxResult, type GenerateRedlineUnprocessedStory, HEADING_LEVELS, type HeadingLevel, type InspectDocxPackageOptions, InvalidBilingualDocumentOptionsError, InvalidFolioDocumentOperationBatchError, InvalidFolioDocumentPrivacyOptionsError, InvalidFolioDocxXmlPatchProposalError, InvalidFolioDocxXmlPatchProposalOptionsError, InvalidFolioReportBuilderOptionsError, InvalidFolioVersionComparisonOptionsError, InvalidGenerateRedlineDocxOptionsError, 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, normalizeFolioAIBlockText, pageBreak, paragraph, parseDocx, parseFolioDocumentOperationBatch, parseFolioDocxXmlPatchProposal, readBilingualDocument, readBilingualDocx, readFolioDocumentSection, replyToComment, rewriteDocxMetadataPrivacy, run, table, validateDocxConformance };
@@ -1,2 +1,2 @@
1
- import { BlockContent, BlockSdt, BookmarkEnd, BookmarkStart, BreakContent, Column, Comment, CommentRangeEnd, CommentRangeStart, CommentReference, ComplexField, Deletion, DocumentBody, DrawingContent, Endnote, EndnotePosition, EndnoteProperties, Field, FieldCharContent, FieldType, FooterReference, Footnote, FootnotePosition, FootnoteProperties, HeaderFooter, HeaderFooterType, HeaderReference, Hyperlink, Image, ImageCrop, ImagePadding, ImagePosition, ImageSize, ImageTransform, ImageWrap, InlineSdt, Insertion, InstrTextContent, LineNumberRestart, MathEquation, MoveFrom, MoveFromRangeEnd, MoveFromRangeStart, MoveTo, MoveToRangeEnd, MoveToRangeStart, NoBreakHyphenContent, NoteNumberRestart, NoteReferenceContent, PageOrientation, Paragraph, ParagraphContent, ParagraphPropertyChange, PositionalTab, PropertyChangeInfo, Run, RunContent, RunPropertyChange, SdtProperties, SdtType, Section, SectionProperties, SectionStart, Shape, ShapeContent, ShapeFill, ShapeOutline, ShapeTextBody, ShapeType, SimpleField, SoftHyphenContent, SymbolContent, TabContent, Table, TableCell, TableCellPropertyChange, TableRow, TableRowPropertyChange, TableStructuralChangeInfo, TextBox, TextContent, TrackedChangeInfo, TrackedRunChange, VerticalAlign } from "@stll/docx-core/model";
2
- export type { BlockContent, BlockSdt, BookmarkEnd, BookmarkStart, BreakContent, Column, Comment, CommentRangeEnd, CommentRangeStart, CommentReference, ComplexField, Deletion, DocumentBody, DrawingContent, Endnote, EndnotePosition, EndnoteProperties, Field, FieldCharContent, FieldType, FooterReference, Footnote, FootnotePosition, FootnoteProperties, HeaderFooter, HeaderFooterType, HeaderReference, Hyperlink, Image, ImageCrop, ImagePadding, ImagePosition, ImageSize, ImageTransform, ImageWrap, InlineSdt, Insertion, InstrTextContent, LineNumberRestart, MathEquation, MoveFrom, MoveFromRangeEnd, MoveFromRangeStart, MoveTo, MoveToRangeEnd, MoveToRangeStart, NoBreakHyphenContent, NoteNumberRestart, NoteReferenceContent, PageOrientation, Paragraph, ParagraphContent, ParagraphPropertyChange, PositionalTab, PropertyChangeInfo, Run, RunContent, RunPropertyChange, SdtProperties, SdtType, Section, SectionProperties, SectionStart, Shape, ShapeContent, ShapeFill, ShapeOutline, ShapeTextBody, ShapeType, SimpleField, SoftHyphenContent, SymbolContent, TabContent, Table, TableCell, TableCellPropertyChange, TableRow, TableRowPropertyChange, TableStructuralChangeInfo, TextBox, TextContent, TrackedChangeInfo, TrackedRunChange, VerticalAlign };
1
+ import { BlockContent, BlockSdt, BookmarkEnd, BookmarkStart, BreakContent, Column, Comment, CommentRangeEnd, CommentRangeStart, CommentReference, ComplexField, Deletion, DocumentBody, DrawingContent, DrawingRawXmlMode, Endnote, EndnotePosition, EndnoteProperties, Field, FieldCharContent, FieldType, FooterReference, Footnote, FootnotePosition, FootnoteProperties, HeaderFooter, HeaderFooterType, HeaderReference, Hyperlink, Image, ImageCrop, ImagePadding, ImagePosition, ImageSize, ImageTransform, ImageWrap, InlineSdt, Insertion, InstrTextContent, LineNumberRestart, MathEquation, MoveFrom, MoveFromRangeEnd, MoveFromRangeStart, MoveTo, MoveToRangeEnd, MoveToRangeStart, NoBreakHyphenContent, NoteNumberRestart, NoteReferenceContent, PageOrientation, Paragraph, ParagraphContent, ParagraphPropertyChange, PositionalTab, PropertyChangeInfo, Run, RunContent, RunPropertyChange, SdtProperties, SdtType, Section, SectionProperties, SectionStart, Shape, ShapeContent, ShapeFill, ShapeGeometryAdjustment, ShapeOutline, ShapeTextBody, ShapeType, SimpleField, SoftHyphenContent, SymbolContent, TabContent, Table, TableCell, TableCellPropertyChange, TableRow, TableRowPropertyChange, TableStructuralChangeInfo, TextBox, TextContent, TrackedChangeInfo, TrackedRunChange, VerticalAlign } from "@stll/docx-core/model";
2
+ export type { BlockContent, BlockSdt, BookmarkEnd, BookmarkStart, BreakContent, Column, Comment, CommentRangeEnd, CommentRangeStart, CommentReference, ComplexField, Deletion, DocumentBody, DrawingContent, DrawingRawXmlMode, Endnote, EndnotePosition, EndnoteProperties, Field, FieldCharContent, FieldType, FooterReference, Footnote, FootnotePosition, FootnoteProperties, HeaderFooter, HeaderFooterType, HeaderReference, Hyperlink, Image, ImageCrop, ImagePadding, ImagePosition, ImageSize, ImageTransform, ImageWrap, InlineSdt, Insertion, InstrTextContent, LineNumberRestart, MathEquation, MoveFrom, MoveFromRangeEnd, MoveFromRangeStart, MoveTo, MoveToRangeEnd, MoveToRangeStart, NoBreakHyphenContent, NoteNumberRestart, NoteReferenceContent, PageOrientation, Paragraph, ParagraphContent, ParagraphPropertyChange, PositionalTab, PropertyChangeInfo, Run, RunContent, RunPropertyChange, SdtProperties, SdtType, Section, SectionProperties, SectionStart, Shape, ShapeContent, ShapeFill, ShapeGeometryAdjustment, ShapeOutline, ShapeTextBody, ShapeType, SimpleField, SoftHyphenContent, SymbolContent, TabContent, Table, TableCell, TableCellPropertyChange, TableRow, TableRowPropertyChange, TableStructuralChangeInfo, TextBox, TextContent, TrackedChangeInfo, TrackedRunChange, VerticalAlign };
@@ -16,6 +16,7 @@ type DocumentBody = document_d_exports.DocumentBody;
16
16
  type DocxConformanceClass = document_d_exports.DocxConformanceClass;
17
17
  type DocxPackage = document_d_exports.DocxPackage;
18
18
  type DrawingContent = document_d_exports.DrawingContent;
19
+ type DrawingRawXmlMode = document_d_exports.DrawingRawXmlMode;
19
20
  type EmphasisMark = document_d_exports.EmphasisMark;
20
21
  type Endnote = document_d_exports.Endnote;
21
22
  type EndnotePosition = document_d_exports.EndnotePosition;
@@ -72,6 +73,7 @@ type ShadingProperties = document_d_exports.ShadingProperties;
72
73
  type Shape = document_d_exports.Shape;
73
74
  type ShapeContent = document_d_exports.ShapeContent;
74
75
  type ShapeFill = document_d_exports.ShapeFill;
76
+ type ShapeGeometryAdjustment = document_d_exports.ShapeGeometryAdjustment;
75
77
  type ShapeOutline = document_d_exports.ShapeOutline;
76
78
  type ShapeTextBody = document_d_exports.ShapeTextBody;
77
79
  type ShapeType = document_d_exports.ShapeType;
@@ -106,4 +108,4 @@ type ThemeFont = document_d_exports.ThemeFont;
106
108
  type ThemeFontScheme = document_d_exports.ThemeFontScheme;
107
109
  type UnderlineStyle = document_d_exports.UnderlineStyle;
108
110
  type VerticalAlign = document_d_exports.VerticalAlign;
109
- export type { AbstractNumbering, BlockContent, BookmarkEnd, BookmarkStart, BorderSpec, BreakContent, CellMargins, ColorValue, Column, ComplexField, ConditionalFormatStyle, DocDefaults, Document, DocumentBody, DocxConformanceClass, DocxPackage, DrawingContent, EmphasisMark, Endnote, EndnotePosition, EndnoteProperties, Field, FieldCharContent, FieldType, FloatingTableProperties, FontInfo, FontTable, FooterReference, Footnote, FootnotePosition, FootnoteProperties, HeaderFooter, HeaderFooterType, HeaderReference, Hyperlink, Image, ImageCrop, ImagePadding, ImagePosition, ImageSize, ImageTransform, ImageWrap, InstrTextContent, LevelSuffix, LineNumberRestart, LineSpacingRule, ListLevel, ListRendering, MediaFile, NoBreakHyphenContent, NoteNumberRestart, NoteReferenceContent, NumberFormat, NumberingDefinitions, NumberingInstance, PageOrientation, Paragraph, ParagraphAlignment, ParagraphContent, ParagraphFormatting, PositionalTab, Relationship, RelationshipMap, RelationshipType, Run, RunContent, Section, SectionProperties, SectionStart, ShadingProperties, Shape, ShapeContent, ShapeFill, ShapeOutline, ShapeTextBody, ShapeType, SimpleField, SoftHyphenContent, Style, StyleDefinitions, StyleType, SymbolContent, TabContent, TabLeader, TabStop, TabStopAlignment, Table, TableBorders, TableCell, TableCellFormatting, TableFormatting, TableLook, TableMeasurement, TableRow, TableRowFormatting, TableWidthType, TextBox, TextContent, TextEffect, TextFormatting, Theme, ThemeColorScheme, ThemeColorSlot, ThemeFont, ThemeFontScheme, UnderlineStyle, VerticalAlign };
111
+ export type { AbstractNumbering, BlockContent, BookmarkEnd, BookmarkStart, BorderSpec, BreakContent, CellMargins, ColorValue, Column, ComplexField, ConditionalFormatStyle, DocDefaults, Document, DocumentBody, DocxConformanceClass, DocxPackage, DrawingContent, DrawingRawXmlMode, EmphasisMark, Endnote, EndnotePosition, EndnoteProperties, Field, FieldCharContent, FieldType, FloatingTableProperties, FontInfo, FontTable, FooterReference, Footnote, FootnotePosition, FootnoteProperties, HeaderFooter, HeaderFooterType, HeaderReference, Hyperlink, Image, ImageCrop, ImagePadding, ImagePosition, ImageSize, ImageTransform, ImageWrap, InstrTextContent, LevelSuffix, LineNumberRestart, LineSpacingRule, ListLevel, ListRendering, MediaFile, NoBreakHyphenContent, NoteNumberRestart, NoteReferenceContent, NumberFormat, NumberingDefinitions, NumberingInstance, PageOrientation, Paragraph, ParagraphAlignment, ParagraphContent, ParagraphFormatting, PositionalTab, Relationship, RelationshipMap, RelationshipType, Run, RunContent, Section, SectionProperties, SectionStart, ShadingProperties, Shape, ShapeContent, ShapeFill, ShapeGeometryAdjustment, ShapeOutline, ShapeTextBody, ShapeType, SimpleField, SoftHyphenContent, Style, StyleDefinitions, StyleType, SymbolContent, TabContent, TabLeader, TabStop, TabStopAlignment, Table, TableBorders, TableCell, TableCellFormatting, TableFormatting, TableLook, TableMeasurement, TableRow, TableRowFormatting, TableWidthType, TextBox, TextContent, TextEffect, TextFormatting, Theme, ThemeColorScheme, ThemeColorSlot, ThemeFont, ThemeFontScheme, UnderlineStyle, VerticalAlign };
@@ -0,0 +1,9 @@
1
+ //#region src/utils/tableOfContentsStyle.d.ts
2
+ type TableOfContentsStyleIdentity = {
3
+ styleId: string | undefined;
4
+ styleName?: string;
5
+ };
6
+ /** Resolve a built-in TOC entry style without relying on its localized style id. */
7
+ declare const tableOfContentsStyleLevel: ({ styleId, styleName }: TableOfContentsStyleIdentity) => number | undefined;
8
+ //#endregion
9
+ export { tableOfContentsStyleLevel };
@@ -0,0 +1,14 @@
1
+ //#region src/utils/tableOfContentsStyle.ts
2
+ const TABLE_OF_CONTENTS_STYLE_ID = /^TOC(?<level>\d*)$/iu;
3
+ const TABLE_OF_CONTENTS_STYLE_NAME = /^toc\s+(?<level>\d+)$/iu;
4
+ const parsedLevel = (match) => {
5
+ if (!match) return;
6
+ const rawLevel = match.groups?.["level"];
7
+ if (rawLevel === "") return 1;
8
+ const level = Number(rawLevel);
9
+ return Number.isSafeInteger(level) && level > 0 ? level : void 0;
10
+ };
11
+ /** Resolve a built-in TOC entry style without relying on its localized style id. */
12
+ const tableOfContentsStyleLevel = ({ styleId, styleName }) => parsedLevel(TABLE_OF_CONTENTS_STYLE_ID.exec(styleId ?? "")) ?? parsedLevel(TABLE_OF_CONTENTS_STYLE_NAME.exec(styleName ?? ""));
13
+ //#endregion
14
+ export { tableOfContentsStyleLevel };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stll/folio-core",
3
- "version": "0.25.4",
3
+ "version": "0.26.0",
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",
@@ -113,7 +113,7 @@
113
113
  "perf": "bun scripts/profile-editor.ts"
114
114
  },
115
115
  "dependencies": {
116
- "@stll/docx-core": "^0.17.0",
116
+ "@stll/docx-core": "^0.17.1",
117
117
  "@stll/docx-utils": "^0.1.0",
118
118
  "@stll/template-conditions": "^0.1.0",
119
119
  "better-result": "3.0.1",