@stll/folio-core 0.11.0 → 0.12.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 (194) hide show
  1. package/dist/ai-edits/apply.js +602 -50
  2. package/dist/ai-edits/block-identity.d.ts +4 -0
  3. package/dist/ai-edits/block-identity.js +9 -0
  4. package/dist/ai-edits/blockRange.d.ts +28 -1
  5. package/dist/ai-edits/blockRange.js +67 -1
  6. package/dist/ai-edits/headless.d.ts +4 -4
  7. package/dist/ai-edits/headless.js +9 -9
  8. package/dist/ai-edits/index.d.ts +2 -2
  9. package/dist/ai-edits/index.js +2 -2
  10. package/dist/ai-edits/read.d.ts +7 -7
  11. package/dist/ai-edits/read.js +110 -3
  12. package/dist/ai-edits/table-cell-mutations.d.ts +48 -0
  13. package/dist/ai-edits/table-cell-mutations.js +237 -0
  14. package/dist/ai-edits/table-mutation-plan.d.ts +38 -0
  15. package/dist/ai-edits/table-mutation-plan.js +90 -0
  16. package/dist/ai-edits/table-row-column-mutations.d.ts +100 -0
  17. package/dist/ai-edits/table-row-column-mutations.js +300 -0
  18. package/dist/ai-edits/table-targets.d.ts +32 -0
  19. package/dist/ai-edits/table-targets.js +70 -0
  20. package/dist/ai-edits/types.d.ts +34 -0
  21. package/dist/compat/eigenpal.js +1 -1
  22. package/dist/content-controls/mutateContentControls.js +1 -1
  23. package/dist/controller/activeEditorStory.d.ts +36 -0
  24. package/dist/controller/activeEditorStory.js +30 -0
  25. package/dist/controller/contentControlWidgetController.d.ts +55 -0
  26. package/dist/controller/contentControlWidgetController.js +141 -0
  27. package/dist/controller/fontReadiness.js +2 -0
  28. package/dist/controller/headerFooterEditorManager.js +1 -1
  29. package/dist/controller/hiddenEditorApi.js +2 -2
  30. package/dist/controller/hiddenEditorManager.d.ts +12 -1
  31. package/dist/controller/hiddenEditorManager.js +32 -11
  32. package/dist/controller/layoutPipeline.d.ts +2 -0
  33. package/dist/controller/layoutPipeline.js +16 -1
  34. package/dist/controller/noteEditorManager.d.ts +36 -0
  35. package/dist/controller/noteEditorManager.js +210 -0
  36. package/dist/document-operations.d.ts +35 -3
  37. package/dist/document-operations.js +161 -3
  38. package/dist/docx/blockContentParser.js +2 -2
  39. package/dist/docx/commentParser.js +6 -1
  40. package/dist/docx/conformance.js +8 -1
  41. package/dist/docx/documentGrid.d.ts +8 -0
  42. package/dist/docx/documentGrid.js +8 -0
  43. package/dist/docx/drawingUtils.js +1 -1
  44. package/dist/docx/ensureParaIds.js +1 -1
  45. package/dist/docx/fieldParser.js +1 -1
  46. package/dist/docx/notePropertiesParser.js +1 -1
  47. package/dist/docx/numberingParser.js +1 -1
  48. package/dist/docx/paragraphParser.js +63 -58
  49. package/dist/docx/paragraphTextBoxEnrichment.d.ts +2 -1
  50. package/dist/docx/paragraphTextBoxEnrichment.js +67 -13
  51. package/dist/docx/paragraphTraversal.js +1 -1
  52. package/dist/docx/parser.js +3 -3
  53. package/dist/docx/rezip.js +1 -1
  54. package/dist/docx/runParser.js +4 -2
  55. package/dist/docx/sdtProperties.js +1 -1
  56. package/dist/docx/sectionParser.js +1 -1
  57. package/dist/docx/selectiveSave.js +1 -1
  58. package/dist/docx/serializer/commentSerializer.js +1 -2
  59. package/dist/docx/serializer/documentSerializer.js +2 -2
  60. package/dist/docx/serializer/headerFooterSerializer.js +2 -2
  61. package/dist/docx/serializer/noteSerializer.js +2 -2
  62. package/dist/docx/serializer/paragraphSerializer.js +7 -1
  63. package/dist/docx/serializer/runSerializer.js +4 -2
  64. package/dist/docx/serializer/stylesSerializer.js +1 -1
  65. package/dist/docx/serializer/tableSerializer.d.ts +5 -4
  66. package/dist/docx/serializer/tableSerializer.js +17 -13
  67. package/dist/docx/server/applyDocxXmlPatchProposal.d.ts +87 -0
  68. package/dist/docx/server/applyDocxXmlPatchProposal.js +204 -0
  69. package/dist/docx/server/boundedArchive.d.ts +14 -3
  70. package/dist/docx/server/boundedArchive.js +56 -11
  71. package/dist/docx/server/evaluateDocxXmlPatchProposal.d.ts +85 -0
  72. package/dist/docx/server/evaluateDocxXmlPatchProposal.js +361 -0
  73. package/dist/docx/server/inspectDocxPackage.d.ts +70 -0
  74. package/dist/docx/server/inspectDocxPackage.js +217 -0
  75. package/dist/docx/server/validateDocxConformance.d.ts +41 -0
  76. package/dist/docx/server/validateDocxConformance.js +336 -0
  77. package/dist/docx/settingsParser.js +11 -1
  78. package/dist/docx/shapeParser.js +1 -1
  79. package/dist/docx/styleParser.js +4 -2
  80. package/dist/docx/tableParser.js +18 -7
  81. package/dist/docx/textBoxParser.d.ts +3 -3
  82. package/dist/docx/textBoxParser.js +16 -12
  83. package/dist/docx/xmlSafety.d.ts +5 -0
  84. package/dist/docx/xmlSafety.js +9 -0
  85. package/dist/fields/resolveFieldValues.js +1 -3
  86. package/dist/i18n/messages/catalogs.gen.d.ts +17 -0
  87. package/dist/i18n/messages/catalogs.gen.js +17 -0
  88. package/dist/i18n/messages/messages.gen.d.ts +1 -0
  89. package/dist/index.js +1 -1
  90. package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
  91. package/dist/layout-bridge/convert/footnoteLayout.js +47 -40
  92. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
  93. package/dist/layout-bridge/convert/headerFooterLayout.js +3 -0
  94. package/dist/layout-bridge/convert/templatePreviewFlow.js +3 -3
  95. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +4 -2
  96. package/dist/layout-bridge/convert/toFlowBlocks.js +136 -20
  97. package/dist/layout-bridge/dom/noteStoryDom.d.ts +6 -0
  98. package/dist/layout-bridge/dom/noteStoryDom.js +17 -0
  99. package/dist/layout-bridge/engine/clickToPosition.js +2 -2
  100. package/dist/layout-engine/index.d.ts +2 -2
  101. package/dist/layout-engine/index.js +43 -28
  102. package/dist/layout-engine/justificationCompatibility.d.ts +6 -0
  103. package/dist/layout-engine/justificationCompatibility.js +8 -0
  104. package/dist/layout-engine/keep-together.js +11 -1
  105. package/dist/layout-engine/measure/cache.js +21 -5
  106. package/dist/layout-engine/measure/lineBreakProvider.js +53 -34
  107. package/dist/layout-engine/measure/measureBlocks.js +6 -3
  108. package/dist/layout-engine/measure/measureContainer.js +1 -1
  109. package/dist/layout-engine/measure/measureHelpers.d.ts +1 -1
  110. package/dist/layout-engine/measure/measureHelpers.js +3 -3
  111. package/dist/layout-engine/measure/measureParagraph.js +69 -25
  112. package/dist/layout-engine/measure/measureProvider.js +4 -3
  113. package/dist/layout-engine/measure/tableCellFlow.js +5 -2
  114. package/dist/layout-engine/measure/textBoxParagraphLayout.d.ts +9 -7
  115. package/dist/layout-engine/measure/textBoxParagraphLayout.js +22 -6
  116. package/dist/layout-engine/measure/textMeasurementPolicy.d.ts +3 -1
  117. package/dist/layout-engine/measure/textMeasurementPolicy.js +7 -1
  118. package/dist/layout-engine/paginator.js +5 -1
  119. package/dist/layout-engine/paragraphSpacing.d.ts +28 -4
  120. package/dist/layout-engine/paragraphSpacing.js +107 -13
  121. package/dist/layout-engine/renderedBreakReconciliation.js +1 -1
  122. package/dist/layout-engine/types.d.ts +26 -13
  123. package/dist/layout-painter/registry/modules/textBox.js +5 -1
  124. package/dist/layout-painter/renderPage.d.ts +5 -2
  125. package/dist/layout-painter/renderPage.js +56 -12
  126. package/dist/layout-painter/renderParagraph.js +22 -6
  127. package/dist/layout-painter/renderTable.d.ts +5 -1
  128. package/dist/layout-painter/renderTable.js +5 -2
  129. package/dist/layout-painter/renderTextBox.d.ts +2 -1
  130. package/dist/layout-painter/renderTextBox.js +25 -14
  131. package/dist/managers/DocumentLoaderManager.js +1 -1
  132. package/dist/model.js +1 -1
  133. package/dist/prosemirror/attrs/index.d.ts +4 -2
  134. package/dist/prosemirror/attrs/index.js +154 -18
  135. package/dist/prosemirror/commands/comments.d.ts +3 -3
  136. package/dist/prosemirror/commands/comments.js +248 -12
  137. package/dist/prosemirror/commands/contentControls.js +1 -1
  138. package/dist/prosemirror/commands/index.js +1 -1
  139. package/dist/prosemirror/commands/pageBreak.js +1 -1
  140. package/dist/prosemirror/commands/propertyChangeScope.d.ts +2 -2
  141. package/dist/prosemirror/commands/propertyChangeScope.js +3 -2
  142. package/dist/prosemirror/commands/tableCellMergeResolution.d.ts +9 -0
  143. package/dist/prosemirror/commands/tableCellMergeResolution.js +181 -0
  144. package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -1
  145. package/dist/prosemirror/conversion/fromProseDoc.js +286 -61
  146. package/dist/prosemirror/conversion/sdtAttrs.d.ts +9 -0
  147. package/dist/prosemirror/conversion/sdtAttrs.js +49 -0
  148. package/dist/prosemirror/conversion/toProseDoc.d.ts +2 -1
  149. package/dist/prosemirror/conversion/toProseDoc.js +347 -98
  150. package/dist/prosemirror/extensions/ExtensionManager.js +1 -1
  151. package/dist/prosemirror/extensions/StarterKit.js +6 -1
  152. package/dist/prosemirror/extensions/core/ParagraphExtension.js +4 -1
  153. package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +1 -0
  154. package/dist/prosemirror/extensions/features/ListExtension.js +1 -1
  155. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +10 -1
  156. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +93 -2
  157. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +2 -1
  158. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +6 -2
  159. package/dist/prosemirror/extensions/marks/CharacterSpacingExtension.js +1 -1
  160. package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.d.ts +9 -1
  161. package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +24 -1
  162. package/dist/prosemirror/extensions/nodes/FieldExtension.js +1 -1
  163. package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.d.ts +7 -0
  164. package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.js +22 -0
  165. package/dist/prosemirror/extensions/nodes/TableExtension.js +9 -3
  166. package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.d.ts +13 -0
  167. package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.js +41 -0
  168. package/dist/prosemirror/extensions/nodes/TextBoxExtension.d.ts +5 -2
  169. package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +4 -1
  170. package/dist/prosemirror/plugins/contentControlWidgets.d.ts +34 -8
  171. package/dist/prosemirror/plugins/contentControlWidgets.js +125 -91
  172. package/dist/prosemirror/plugins/selectionTracker.js +1 -0
  173. package/dist/prosemirror/plugins/suggestionMode.js +1 -1
  174. package/dist/prosemirror/schema/index.d.ts +2 -2
  175. package/dist/prosemirror/schema/marks.d.ts +5 -1
  176. package/dist/prosemirror/schema/nodes.d.ts +64 -7
  177. package/dist/prosemirror/selectionState.js +1 -0
  178. package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
  179. package/dist/prosemirror/tableCellMergeRevision.d.ts +9 -0
  180. package/dist/prosemirror/tableCellMergeRevision.js +22 -0
  181. package/dist/prosemirror/textBoxAnchorAttrs.d.ts +9 -0
  182. package/dist/prosemirror/textBoxAnchorAttrs.js +33 -0
  183. package/dist/prosemirror/utils/extractTrackedChanges.d.ts +1 -1
  184. package/dist/prosemirror/utils/extractTrackedChanges.js +62 -14
  185. package/dist/prosemirror/validation.js +9 -1
  186. package/dist/server.d.ts +6 -2
  187. package/dist/server.js +5 -1
  188. package/dist/utils/fontFamilyMerge.js +9 -11
  189. package/dist/utils/fontLoader.js +3 -2
  190. package/dist/utils/fontResolver.js +22 -4
  191. package/dist/utils/fontWeights.d.ts +1 -1
  192. package/dist/utils/fontWeights.js +1 -1
  193. package/dist/utils/paragraphFormattingMerge.js +1 -0
  194. package/package.json +1 -1
@@ -72,26 +72,80 @@ const vmlWrapType = (positioned, zIndex) => {
72
72
  if (Number.isFinite(zIndex) && zIndex < 0) return "behind";
73
73
  return "inFront";
74
74
  };
75
- const enrichParagraphTextBoxes = (paragraph, paraXml, styles, theme, numbering, rels, media) => {
76
- const xmlChildren = getChildElements(paraXml);
75
+ const enrichParagraphTextBoxes = (paragraph, paraXml, styles, theme, numbering, rels, media, parseTable) => {
76
+ enrichTextBoxRuns({
77
+ content: paragraph.content,
78
+ xmlChildren: getChildElements(paraXml),
79
+ styles,
80
+ theme,
81
+ numbering,
82
+ rels,
83
+ media,
84
+ parseTable
85
+ });
86
+ };
87
+ const trackedChangeTypeFromXml = (localName) => {
88
+ if (localName === "ins") return "insertion";
89
+ if (localName === "del") return "deletion";
90
+ if (localName === "moveFrom" || localName === "moveTo") return localName;
91
+ };
92
+ const enrichTextBoxRuns = ({ content, xmlChildren, styles, theme, numbering, rels, media, parseTable }) => {
77
93
  let parsedIndex = 0;
78
94
  let lastConsumedRun;
79
95
  for (const xmlChild of xmlChildren) {
80
- if (getLocalName(xmlChild.name ?? "") !== "r") {
81
- if (parsedIndex < paragraph.content.length && paragraph.content[parsedIndex]?.type !== "run") parsedIndex += 1;
96
+ const localName = getLocalName(xmlChild.name ?? "");
97
+ if (localName === "pPr") continue;
98
+ const trackedChangeType = trackedChangeTypeFromXml(localName);
99
+ const parsedContent = content[parsedIndex];
100
+ if (trackedChangeType && parsedContent?.type === trackedChangeType) enrichTextBoxRuns({
101
+ content: parsedContent.content,
102
+ xmlChildren: getChildElements(xmlChild),
103
+ styles,
104
+ theme,
105
+ numbering,
106
+ rels,
107
+ media,
108
+ parseTable
109
+ });
110
+ if (localName === "sdt" && parsedContent?.type === "inlineSdt") {
111
+ const properties = parsedContent.properties;
112
+ const nestedContent = [];
113
+ let lastSegmentIndex = parsedIndex;
114
+ for (let index = parsedIndex; index < content.length; index += 1) {
115
+ const candidate = content[index];
116
+ if (candidate?.type !== "inlineSdt" || candidate.properties !== properties) continue;
117
+ nestedContent.push(...candidate.content);
118
+ lastSegmentIndex = index;
119
+ }
120
+ const sdtContent = getChildElements(xmlChild).find((child) => getLocalName(child.name ?? "") === "sdtContent");
121
+ if (sdtContent) enrichTextBoxRuns({
122
+ content: nestedContent,
123
+ xmlChildren: getChildElements(sdtContent),
124
+ styles,
125
+ theme,
126
+ numbering,
127
+ rels,
128
+ media,
129
+ parseTable
130
+ });
131
+ parsedIndex = lastSegmentIndex + 1;
132
+ continue;
133
+ }
134
+ if (localName !== "r") {
135
+ if (parsedIndex < content.length && parsedContent?.type !== "run") parsedIndex += 1;
82
136
  continue;
83
137
  }
84
138
  const { textBoxDrawings, vmlTextBoxes, hasNonTextBoxContent } = scanRunForTextBoxDrawings(xmlChild);
85
- const parsedContent = paragraph.content[parsedIndex];
86
139
  const parsedRun = parsedContent?.type === "run" ? parsedContent : void 0;
87
140
  const targetRun = parsedRun ?? (hasNonTextBoxContent ? lastConsumedRun : void 0);
141
+ const targetRunMatchesXml = targetRun !== void 0 && (hasNonTextBoxContent || parsedRun?.content.length === 0);
88
142
  for (const runEl of textBoxDrawings) {
89
143
  const textBox = parseTextBox(runEl);
90
144
  if (!textBox) continue;
91
145
  const wsp = findDeep(runEl, "wps", "wsp");
92
146
  if (wsp) {
93
147
  const txbxContentEl = getTextBoxContentElement(wsp);
94
- if (txbxContentEl) textBox.content = parseTextBoxContent(txbxContentEl, parseParagraph, null, styles, theme, numbering, rels ?? void 0, media ?? void 0);
148
+ if (txbxContentEl) textBox.content = parseTextBoxContent(txbxContentEl, parseParagraph, parseTable, styles, theme, numbering, rels, media);
95
149
  }
96
150
  const shape = {
97
151
  type: "shape",
@@ -112,31 +166,31 @@ const enrichParagraphTextBoxes = (paragraph, paraXml, styles, theme, numbering,
112
166
  type: "shape",
113
167
  shape
114
168
  };
115
- if (targetRun && hasNonTextBoxContent) targetRun.content.push(shapeContent);
169
+ if (targetRunMatchesXml) targetRun.content.push(shapeContent);
116
170
  else {
117
171
  const newRun = {
118
172
  type: "run",
119
173
  content: [shapeContent]
120
174
  };
121
- paragraph.content.splice(parsedIndex, 0, newRun);
175
+ content.splice(parsedIndex, 0, newRun);
122
176
  lastConsumedRun = newRun;
123
177
  parsedIndex += 1;
124
178
  }
125
179
  }
126
180
  for (const pictEl of vmlTextBoxes) {
127
- const shape = parseVmlTextBoxShape(pictEl, styles, theme, numbering, rels, media);
181
+ const shape = parseVmlTextBoxShape(pictEl, styles, theme, numbering, rels, media, parseTable);
128
182
  if (!shape) continue;
129
183
  const shapeContent = {
130
184
  type: "shape",
131
185
  shape
132
186
  };
133
- if (targetRun && hasNonTextBoxContent) targetRun.content.push(shapeContent);
187
+ if (targetRunMatchesXml) targetRun.content.push(shapeContent);
134
188
  else {
135
189
  const newRun = {
136
190
  type: "run",
137
191
  content: [shapeContent]
138
192
  };
139
- paragraph.content.splice(parsedIndex, 0, newRun);
193
+ content.splice(parsedIndex, 0, newRun);
140
194
  lastConsumedRun = newRun;
141
195
  parsedIndex += 1;
142
196
  }
@@ -196,7 +250,7 @@ const scanRunForTextBoxDrawings = (xmlRun) => {
196
250
  hasNonTextBoxContent
197
251
  };
198
252
  };
199
- const parseVmlTextBoxShape = (pictEl, styles, theme, numbering, rels, media) => {
253
+ const parseVmlTextBoxShape = (pictEl, styles, theme, numbering, rels, media, parseTable) => {
200
254
  const shapeEl = findDeep(pictEl, "v", "shape");
201
255
  const textBoxEl = shapeEl ? findDeep(shapeEl, "v", "textbox") : null;
202
256
  const contentEl = textBoxEl ? findDeep(textBoxEl, "w", "txbxContent") : null;
@@ -221,7 +275,7 @@ const parseVmlTextBoxShape = (pictEl, styles, theme, numbering, rels, media) =>
221
275
  ...fill === void 0 ? {} : { fill },
222
276
  wrap: { type: vmlWrapType(positioned, zIndex) },
223
277
  textBody: {
224
- content: parseTextBoxContent(contentEl, parseParagraph, null, styles, theme, numbering, rels ?? void 0, media ?? void 0),
278
+ content: parseTextBoxContent(contentEl, parseParagraph, parseTable, styles, theme, numbering, rels, media),
225
279
  ...margins === void 0 ? {} : { margins }
226
280
  }
227
281
  };
@@ -10,7 +10,7 @@ const visitDocxParagraphs = ({ documentBody, headers, footers, footnotes, endnot
10
10
  const visitRun = (run) => {
11
11
  for (const content of run.content) {
12
12
  if (content.type !== "shape" || !content.shape.textBody) continue;
13
- for (const paragraph of content.shape.textBody.content) visitParagraph(paragraph);
13
+ for (const block of content.shape.textBody.content) visitBlock(block);
14
14
  }
15
15
  };
16
16
  const visitHyperlink = (hyperlink) => {
@@ -1,13 +1,13 @@
1
+ import { parseNumbering } from "./numberingParser.js";
2
+ import { RELATIONSHIP_TYPES, parseRelationships, resolveRelativePath } from "./relsParser.js";
3
+ import { applyThemeFontLang, parseTheme } from "./themeParser.js";
1
4
  import { toArrayBuffer } from "../utils/docxInput.js";
2
5
  import { loadFontsWithMapping } from "../utils/fontLoader.js";
3
6
  import { convertTiffToPngDataUrl, isTiffMimeType } from "../utils/tiffConverter.js";
4
- import { RELATIONSHIP_TYPES, parseRelationships, resolveRelativePath } from "./relsParser.js";
5
- import { applyThemeFontLang, parseTheme } from "./themeParser.js";
6
7
  import { parseComments } from "./commentParser.js";
7
8
  import { normalizeCommentReferences } from "./commentReferenceNormalization.js";
8
9
  import { detectDocxConformanceClass } from "./conformance.js";
9
10
  import { parseCoreProperties } from "./corePropertiesParser.js";
10
- import { parseNumbering } from "./numberingParser.js";
11
11
  import { extractAllTemplateVariables, parseDocumentBody } from "./documentParser.js";
12
12
  import { parseEndnotes, parseFootnotes } from "./footnoteParser.js";
13
13
  import { parseFooter, parseHeader } from "./headerFooterParser.js";
@@ -1,5 +1,5 @@
1
- import { RELATIONSHIP_TYPES, parseRelationships, resolveRelativePath } from "./relsParser.js";
2
1
  import { parseNumbering } from "./numberingParser.js";
2
+ import { RELATIONSHIP_TYPES, parseRelationships, resolveRelativePath } from "./relsParser.js";
3
3
  import { parseEndnotes, parseFootnotes } from "./footnoteParser.js";
4
4
  import { assertValidFolioDocumentModel } from "./modelValidation.js";
5
5
  import { isPreservableDocxEntry } from "./unzip.js";
@@ -1,5 +1,5 @@
1
- import { cloneWithXmlnsDeclarations, elementToXml, findAllDeep, findChild, findChildren, getAttribute, getChildElements, getTextContent, mergeXmlnsDeclarations, parseBooleanElement, parseNumericAttribute } from "./xmlParser.js";
2
1
  import { EmphasisMarkSchema, FontThemeSchema, HighlightColorSchema, ShadingPatternSchema, TextEffectSchema, ThemeColorSlotSchema, UnderlineStyleSchema, narrowEnum } from "./parserEnums.js";
2
+ import { cloneWithXmlnsDeclarations, elementToXml, findAllDeep, findChild, findChildren, getAttribute, getChildElements, getTextContent, mergeXmlnsDeclarations, parseBooleanElement, parseNumericAttribute } from "./xmlParser.js";
3
3
  import { parseImage } from "./imageParser.js";
4
4
  import { parseGroupDrawing } from "./groupDrawingParser.js";
5
5
  import { parseShapeFromDrawing, shouldPreserveRawShapeDrawing } from "./shapeParser.js";
@@ -551,7 +551,9 @@ function parseRunContents(runElement, rels, media, rootXmlns = {}) {
551
551
  break;
552
552
  }
553
553
  case "rPr": break;
554
- case "lastRenderedPageBreak": break;
554
+ case "lastRenderedPageBreak":
555
+ contents.push({ type: "renderedPageBreak" });
556
+ break;
555
557
  case "cr":
556
558
  contents.push({
557
559
  type: "break",
@@ -1,5 +1,5 @@
1
- import { elementToXml, findChild, getAttributeAnyPrefix, getLocalName, parseBooleanElement } from "./xmlParser.js";
2
1
  import { SdtLockSchema, narrowEnum } from "./parserEnums.js";
2
+ import { elementToXml, findChild, getAttributeAnyPrefix, getLocalName, parseBooleanElement } from "./xmlParser.js";
3
3
  //#region src/docx/sdtProperties.ts
4
4
  function parseListItems(el) {
5
5
  const items = [];
@@ -1,5 +1,5 @@
1
- import { findChild, findChildren, getAttribute, getChildElements, getLocalName, parseBooleanElement, parseNumericAttribute } from "./xmlParser.js";
2
1
  import { BorderStyleSchema, ThemeColorSlotSchema, narrowEnum } from "./parserEnums.js";
2
+ import { findChild, findChildren, getAttribute, getChildElements, getLocalName, parseBooleanElement, parseNumericAttribute } from "./xmlParser.js";
3
3
  import { parseFooterReference, parseHeaderReference } from "./headerFooterRefParser.js";
4
4
  import { parseEndnoteProperties, parseFootnoteProperties } from "./notePropertiesParser.js";
5
5
  //#region src/docx/sectionParser.ts
@@ -1,6 +1,6 @@
1
+ import { parseNumbering } from "./numberingParser.js";
1
2
  import { RELATIONSHIP_TYPES } from "./relsParser.js";
2
3
  import { parseCommentsExtended } from "./commentParser.js";
3
- import { parseNumbering } from "./numberingParser.js";
4
4
  import { validateFolioDocumentModel } from "./modelValidation.js";
5
5
  import { hasUnsynthesizedReplyRanges } from "./commentReplyMarkers.js";
6
6
  import { buildPatchedDocumentXml, buildPatchedNoteXml, buildPatchedNumberingXml, collectChangedNumberingDefs, collectParaIds } from "./selectiveXmlPatch.js";
@@ -46,8 +46,7 @@ function serializeParagraphWithAnnotationRef(p) {
46
46
  return xml;
47
47
  }
48
48
  function serializeComment(comment) {
49
- const attrs = [`w:id="${comment.id}"`];
50
- if (comment.author) attrs.push(`w:author="${escapeXml(comment.author)}"`);
49
+ const attrs = [`w:id="${comment.id}"`, `w:author="${escapeXml(comment.author)}"`];
51
50
  if (comment.initials) attrs.push(`w:initials="${escapeXml(comment.initials)}"`);
52
51
  if (comment.date) attrs.push(`w:date="${escapeXml(comment.date)}"`);
53
52
  let xml = `<w:comment ${attrs.join(" ")}>`;
@@ -1,8 +1,8 @@
1
1
  import { serializeBlockSdt } from "./blockSdtSerializer.js";
2
+ import { serializeTable } from "./tableSerializer.js";
2
3
  import { resetAutoIdCounter } from "./runSerializer.js";
3
4
  import { serializeSectionProperties } from "./sectionPropertiesSerializer.js";
4
5
  import { serializeParagraph } from "./paragraphSerializer.js";
5
- import { serializeTable } from "./tableSerializer.js";
6
6
  //#region src/docx/serializer/documentSerializer.ts
7
7
  /**
8
8
  * Standard OOXML namespaces for document.xml
@@ -74,7 +74,7 @@ function buildNamespaceDeclarations() {
74
74
  */
75
75
  function serializeBlockContent(block) {
76
76
  if (block.type === "paragraph") return serializeParagraph(block);
77
- if (block.type === "table") return serializeTable(block);
77
+ if (block.type === "table") return serializeTable(block, serializeParagraph);
78
78
  return serializeBlockSdt(block, serializeBlockContent);
79
79
  }
80
80
  /**
@@ -1,8 +1,8 @@
1
1
  import { canReplayHeaderFooterVerbatim, getHeaderFooterVerbatimXml } from "../headerFooterVerbatim.js";
2
2
  import { escapeXml } from "./xmlUtils.js";
3
3
  import { serializeBlockSdt } from "./blockSdtSerializer.js";
4
- import { serializeParagraph } from "./paragraphSerializer.js";
5
4
  import { serializeTable } from "./tableSerializer.js";
5
+ import { serializeParagraph } from "./paragraphSerializer.js";
6
6
  //#region src/docx/serializer/headerFooterSerializer.ts
7
7
  const NAMESPACES = {
8
8
  wpc: "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas",
@@ -36,7 +36,7 @@ function buildNamespaceDeclarations() {
36
36
  */
37
37
  function serializeBlock(block) {
38
38
  if (block.type === "paragraph") return serializeParagraph(block);
39
- if (block.type === "table") return serializeTable(block);
39
+ if (block.type === "table") return serializeTable(block, serializeParagraph);
40
40
  return serializeBlockSdt(block, serializeBlock);
41
41
  }
42
42
  /**
@@ -1,6 +1,6 @@
1
1
  import { serializeBlockSdt } from "./blockSdtSerializer.js";
2
- import { serializeParagraph } from "./paragraphSerializer.js";
3
2
  import { serializeTable } from "./tableSerializer.js";
3
+ import { serializeParagraph } from "./paragraphSerializer.js";
4
4
  //#region src/docx/serializer/noteSerializer.ts
5
5
  const NAMESPACES = {
6
6
  wpc: "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas",
@@ -34,7 +34,7 @@ function buildNamespaceDeclarations() {
34
34
  */
35
35
  function serializeBlock(block) {
36
36
  if (block.type === "paragraph") return serializeParagraph(block);
37
- if (block.type === "table") return serializeTable(block);
37
+ if (block.type === "table") return serializeTable(block, serializeParagraph);
38
38
  return serializeBlockSdt(block, serializeBlock);
39
39
  }
40
40
  /**
@@ -155,6 +155,7 @@ function serializeParagraphFormatting(formatting, propertyChanges, pPrMark) {
155
155
  const frameXml = serializeFrameProperties(formatting.frame);
156
156
  if (frameXml) parts.push(frameXml);
157
157
  pushToggle("widowControl", formatting.widowControl);
158
+ pushToggle("snapToGrid", formatting.snapToGrid);
158
159
  const numPrXml = formatting.numPrFromStyle != null && numPrEqual(formatting.numPr, formatting.numPrFromStyle) ? "" : serializeNumbering(formatting.numPr);
159
160
  if (numPrXml) parts.push(numPrXml);
160
161
  const bordersXml = serializeParagraphBorders(formatting.borders);
@@ -354,6 +355,8 @@ function serializeInlineSdt(sdt) {
354
355
  case "inlineSdt": return serializeInlineSdt(item);
355
356
  case "insertion": return serializeTrackedChange("ins", item);
356
357
  case "deletion": return serializeTrackedChange("del", item);
358
+ case "moveFrom": return serializeTrackedChange("moveFrom", item);
359
+ case "moveTo": return serializeTrackedChange("moveTo", item);
357
360
  case "mathEquation": return item.ommlXml || "";
358
361
  default: return item;
359
362
  }
@@ -478,7 +481,10 @@ function serializeParagraph(paragraph) {
478
481
  }
479
482
  function injectRenderedPageBreakIntoFirstRun(xml) {
480
483
  const runOpeningTag = /<w:r(?=[\s>/])[^>]*>/u;
481
- if (!runOpeningTag.test(xml)) return null;
484
+ const openingTag = runOpeningTag.exec(xml);
485
+ if (!openingTag) return null;
486
+ const runEnd = xml.indexOf("</w:r>", openingTag.index + openingTag[0].length);
487
+ if (runEnd !== -1 && xml.slice(openingTag.index + openingTag[0].length, runEnd).includes("<w:lastRenderedPageBreak/>")) return xml;
482
488
  return xml.replace(runOpeningTag, (match) => `${match}<w:lastRenderedPageBreak/>`);
483
489
  }
484
490
  /**
@@ -1,5 +1,6 @@
1
1
  import { HIGHLIGHT_COLOR_VALUES } from "../../types/documentEnumValues.js";
2
2
  import { escapeXml, intAttr } from "./xmlUtils.js";
3
+ import { serializeTable } from "./tableSerializer.js";
3
4
  import { serializeParagraph } from "./paragraphSerializer.js";
4
5
  import { panic } from "better-result";
5
6
  //#region src/docx/serializer/runSerializer.ts
@@ -418,8 +419,8 @@ function serializeDrawingContent(content) {
418
419
  ].join("");
419
420
  }
420
421
  /** Serialize text body content for shapes/textboxes */
421
- function serializeShapeTextBody(paragraphs) {
422
- return paragraphs.map((p) => serializeParagraph(p)).join("");
422
+ function serializeShapeTextBody(blocks) {
423
+ return blocks.map((block) => block.type === "paragraph" ? serializeParagraph(block) : serializeTable(block, serializeParagraph)).join("");
423
424
  }
424
425
  /**
425
426
  * Serialize shape content to full DrawingML XML (wps:wsp inside w:drawing)
@@ -534,6 +535,7 @@ function serializeRunContent(content) {
534
535
  case "instrText": return serializeInstrText(content);
535
536
  case "softHyphen": return serializeSoftHyphen(content);
536
537
  case "noBreakHyphen": return serializeNoBreakHyphen(content);
538
+ case "renderedPageBreak": return "<w:lastRenderedPageBreak/>";
537
539
  case "drawing":
538
540
  if (content.rawXml) return content.rawXml;
539
541
  return serializeDrawingContent(content);
@@ -1,7 +1,7 @@
1
1
  import { escapeXml } from "./xmlUtils.js";
2
+ import { serializeTableCellFormatting, serializeTableFormatting, serializeTableRowFormatting } from "./tableSerializer.js";
2
3
  import { serializeTextFormatting } from "./runSerializer.js";
3
4
  import { serializeParagraphFormatting } from "./paragraphSerializer.js";
4
- import { serializeTableCellFormatting, serializeTableFormatting, serializeTableRowFormatting } from "./tableSerializer.js";
5
5
  //#region src/docx/serializer/stylesSerializer.ts
6
6
  const W_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
7
7
  const serializeStylesXml = (definitions) => {
@@ -1,6 +1,7 @@
1
1
  import { document_d_exports } from "../../types/document.js";
2
2
 
3
3
  //#region src/docx/serializer/tableSerializer.d.ts
4
+ type ParagraphSerializer = (paragraph: document_d_exports.Paragraph) => string;
4
5
  /**
5
6
  * Serialize table formatting properties (w:tblPr)
6
7
  */
@@ -16,25 +17,25 @@ declare function serializeTableCellFormatting(formatting: document_d_exports.Tab
16
17
  /**
17
18
  * Serialize a table cell (w:tc)
18
19
  */
19
- declare function serializeTableCell(cell: document_d_exports.TableCell): string;
20
+ declare function serializeTableCell(cell: document_d_exports.TableCell, serializeParagraph: ParagraphSerializer): string;
20
21
  /**
21
22
  * Serialize a table row (w:tr)
22
23
  */
23
- declare function serializeTableRow(row: document_d_exports.TableRow): string;
24
+ declare function serializeTableRow(row: document_d_exports.TableRow, serializeParagraph: ParagraphSerializer): string;
24
25
  /**
25
26
  * Serialize a table to OOXML XML (w:tbl)
26
27
  *
27
28
  * @param table - The table to serialize
28
29
  * @returns XML string for the table
29
30
  */
30
- declare function serializeTable(table: document_d_exports.Table): string;
31
+ declare function serializeTable(table: document_d_exports.Table, serializeParagraph: ParagraphSerializer): string;
31
32
  /**
32
33
  * Serialize multiple tables to OOXML XML
33
34
  *
34
35
  * @param tables - The tables to serialize
35
36
  * @returns XML string for all tables
36
37
  */
37
- declare function serializeTables(tables: document_d_exports.Table[]): string;
38
+ declare function serializeTables(tables: document_d_exports.Table[], serializeParagraph: ParagraphSerializer): string;
38
39
  /**
39
40
  * Check if a table has any rows
40
41
  */
@@ -1,6 +1,5 @@
1
1
  import { escapeXml, intAttr } from "./xmlUtils.js";
2
2
  import { serializeBorder } from "./borderSerializer.js";
3
- import { serializeParagraph } from "./paragraphSerializer.js";
4
3
  //#region src/docx/serializer/tableSerializer.ts
5
4
  function normalizeTrackedChangeInfo(info) {
6
5
  const normalizedId = Number.isInteger(info.id) && info.id >= 0 ? info.id : 0;
@@ -247,12 +246,17 @@ function serializeTableCellFormatting(formatting, propertyChanges, structuralCha
247
246
  if (formatting.textDirection) parts.push(`<w:textDirection w:val="${formatting.textDirection}"/>`);
248
247
  if (formatting.fitText) parts.push("<w:tcFitText/>");
249
248
  if (formatting.verticalAlign) parts.push(`<w:vAlign w:val="${formatting.verticalAlign}"/>`);
250
- if (formatting.hideMark) parts.push("<w:hideMark/>");
249
+ if (formatting.hideMark !== void 0) parts.push(formatting.hideMark ? "<w:hideMark/>" : "<w:hideMark w:val=\"false\"/>");
251
250
  }
252
251
  if (structuralChange) {
253
252
  if (structuralChange.type === "tableCellInsertion") parts.push(`<w:cellIns ${serializeTrackedChangeAttributes(structuralChange.info)}/>`);
254
253
  else if (structuralChange.type === "tableCellDeletion") parts.push(`<w:cellDel ${serializeTrackedChangeAttributes(structuralChange.info)}/>`);
255
- else if (structuralChange.type === "tableCellMerge") parts.push(`<w:cellMerge ${serializeTrackedChangeAttributes(structuralChange.info)}/>`);
254
+ else if (structuralChange.type === "tableCellMerge") {
255
+ const attrs = [serializeTrackedChangeAttributes(structuralChange.info)];
256
+ if (structuralChange.verticalMerge) attrs.push(`w:vMerge="${structuralChange.verticalMerge === "continue" ? "cont" : "rest"}"`);
257
+ if (structuralChange.verticalMergeOriginal) attrs.push(`w:vMergeOrig="${structuralChange.verticalMergeOriginal === "continue" ? "cont" : "rest"}"`);
258
+ parts.push(`<w:cellMerge ${attrs.join(" ")}/>`);
259
+ }
256
260
  }
257
261
  if (propertyChanges && propertyChanges.length > 0) parts.push(...propertyChanges.map((change) => serializeTableCellPropertyChange(change)));
258
262
  if (parts.length === 0) return "";
@@ -277,31 +281,31 @@ function serializeTableGrid(columnWidths) {
277
281
  /**
278
282
  * Serialize cell content (paragraphs, nested tables)
279
283
  */
280
- function serializeCellContent(content) {
284
+ function serializeCellContent(content, serializeParagraph) {
281
285
  const parts = [];
282
286
  for (const item of content) if (item.type === "paragraph") parts.push(serializeParagraph(item));
283
- else parts.push(serializeTable(item));
287
+ else parts.push(serializeTable(item, serializeParagraph));
284
288
  if (parts.length === 0) parts.push("<w:p/>");
285
289
  return parts.join("");
286
290
  }
287
291
  /**
288
292
  * Serialize a table cell (w:tc)
289
293
  */
290
- function serializeTableCell(cell) {
294
+ function serializeTableCell(cell, serializeParagraph) {
291
295
  const parts = [];
292
296
  const tcPrXml = serializeTableCellFormatting(cell.formatting, cell.propertyChanges, cell.structuralChange);
293
297
  if (tcPrXml) parts.push(tcPrXml);
294
- parts.push(serializeCellContent(cell.content));
298
+ parts.push(serializeCellContent(cell.content, serializeParagraph));
295
299
  return `<w:tc>${parts.join("")}</w:tc>`;
296
300
  }
297
301
  /**
298
302
  * Serialize a table row (w:tr)
299
303
  */
300
- function serializeTableRow(row) {
304
+ function serializeTableRow(row, serializeParagraph) {
301
305
  const parts = [];
302
306
  const trPrXml = serializeTableRowFormatting(row.formatting, row.propertyChanges, row.structuralChange);
303
307
  if (trPrXml) parts.push(trPrXml);
304
- for (const cell of row.cells) parts.push(serializeTableCell(cell));
308
+ for (const cell of row.cells) parts.push(serializeTableCell(cell, serializeParagraph));
305
309
  return `<w:tr>${parts.join("")}</w:tr>`;
306
310
  }
307
311
  /**
@@ -310,13 +314,13 @@ function serializeTableRow(row) {
310
314
  * @param table - The table to serialize
311
315
  * @returns XML string for the table
312
316
  */
313
- function serializeTable(table) {
317
+ function serializeTable(table, serializeParagraph) {
314
318
  const parts = [];
315
319
  const tblPrXml = serializeTableFormatting(table.formatting, table.propertyChanges);
316
320
  if (tblPrXml) parts.push(tblPrXml);
317
321
  const tblGridXml = serializeTableGrid(table.columnWidths);
318
322
  if (tblGridXml) parts.push(tblGridXml);
319
- for (const row of table.rows) parts.push(serializeTableRow(row));
323
+ for (const row of table.rows) parts.push(serializeTableRow(row, serializeParagraph));
320
324
  return `<w:tbl>${parts.join("")}</w:tbl>`;
321
325
  }
322
326
  /**
@@ -325,8 +329,8 @@ function serializeTable(table) {
325
329
  * @param tables - The tables to serialize
326
330
  * @returns XML string for all tables
327
331
  */
328
- function serializeTables(tables) {
329
- return tables.map(serializeTable).join("");
332
+ function serializeTables(tables, serializeParagraph) {
333
+ return tables.map((table) => serializeTable(table, serializeParagraph)).join("");
330
334
  }
331
335
  /**
332
336
  * Check if a table has any rows
@@ -0,0 +1,87 @@
1
+ import { DocxArchiveOptions } from "./boundedArchive.js";
2
+ import { FOLIO_DOCX_XML_PATCH_PROPOSAL_PROFILE, FolioDocxPreparedXmlReplacement, FolioDocxXmlPatchProposalEvaluation, FolioDocxXmlPatchProposalLimits } from "./evaluateDocxXmlPatchProposal.js";
3
+ import { FOLIO_DOCX_CONFORMANCE_PROFILE, FolioDocxConformanceReport } from "./validateDocxConformance.js";
4
+
5
+ //#region src/docx/server/applyDocxXmlPatchProposal.d.ts
6
+ declare const FOLIO_DOCX_XML_PATCH_APPLICATION_VERSION: 1;
7
+ declare const FOLIO_DOCX_XML_PATCH_APPLICATION_PROFILE: "folio-xml-patch-application-v1";
8
+ type ApplyDocxXmlPatchProposalArgs = {
9
+ readonly bytes: ArrayBuffer | Uint8Array;
10
+ readonly proposal: unknown; /** Exact package paths authorized by the server-side caller. */
11
+ readonly allowedParts: readonly string[];
12
+ readonly validationProfile: typeof FOLIO_DOCX_CONFORMANCE_PROFILE;
13
+ readonly archive?: DocxArchiveOptions;
14
+ readonly limits?: FolioDocxXmlPatchProposalLimits;
15
+ };
16
+ type FolioDocxXmlPatchApplicationReceipt = {
17
+ readonly version: typeof FOLIO_DOCX_XML_PATCH_APPLICATION_VERSION;
18
+ readonly profile: typeof FOLIO_DOCX_XML_PATCH_APPLICATION_PROFILE;
19
+ readonly proposalProfile: typeof FOLIO_DOCX_XML_PATCH_PROPOSAL_PROFILE;
20
+ readonly validationProfile: typeof FOLIO_DOCX_CONFORMANCE_PROFILE;
21
+ readonly input: {
22
+ readonly sha256: string;
23
+ readonly byteLength: number;
24
+ };
25
+ readonly output: {
26
+ readonly sha256: string;
27
+ readonly byteLength: number;
28
+ };
29
+ readonly replacements: readonly [FolioDocxPreparedXmlReplacement, ...FolioDocxPreparedXmlReplacement[]];
30
+ };
31
+ type FolioDocxXmlPatchApplication = {
32
+ readonly version: typeof FOLIO_DOCX_XML_PATCH_APPLICATION_VERSION;
33
+ readonly profile: typeof FOLIO_DOCX_XML_PATCH_APPLICATION_PROFILE;
34
+ readonly status: "proposal-rejected";
35
+ readonly producesOutput: false;
36
+ readonly evaluation: Extract<FolioDocxXmlPatchProposalEvaluation, {
37
+ status: "rejected";
38
+ }>;
39
+ readonly conformance: null;
40
+ readonly receipt: null;
41
+ } | {
42
+ readonly version: typeof FOLIO_DOCX_XML_PATCH_APPLICATION_VERSION;
43
+ readonly profile: typeof FOLIO_DOCX_XML_PATCH_APPLICATION_PROFILE;
44
+ readonly status: "output-rejected";
45
+ readonly producesOutput: false;
46
+ readonly evaluation: Extract<FolioDocxXmlPatchProposalEvaluation, {
47
+ status: "accepted";
48
+ }>;
49
+ readonly conformance: FolioDocxConformanceReport;
50
+ readonly receipt: null;
51
+ } | {
52
+ readonly version: typeof FOLIO_DOCX_XML_PATCH_APPLICATION_VERSION;
53
+ readonly profile: typeof FOLIO_DOCX_XML_PATCH_APPLICATION_PROFILE;
54
+ readonly status: "applied";
55
+ readonly producesOutput: true;
56
+ readonly evaluation: Extract<FolioDocxXmlPatchProposalEvaluation, {
57
+ status: "accepted";
58
+ }>;
59
+ readonly conformance: FolioDocxConformanceReport & {
60
+ readonly status: "conformant";
61
+ };
62
+ readonly receipt: FolioDocxXmlPatchApplicationReceipt;
63
+ readonly bytes: Uint8Array;
64
+ };
65
+ declare const UnsupportedFolioDocxXmlPatchApplicationProfileError_base: import("better-result").TaggedErrorClass<"UnsupportedFolioDocxXmlPatchApplicationProfileError", {
66
+ message: string;
67
+ profile: unknown;
68
+ }>;
69
+ declare class UnsupportedFolioDocxXmlPatchApplicationProfileError extends UnsupportedFolioDocxXmlPatchApplicationProfileError_base {}
70
+ declare const FolioDocxXmlPatchApplicationError_base: import("better-result").TaggedErrorClass<"FolioDocxXmlPatchApplicationError", {
71
+ message: string;
72
+ stage: "verify" | "load" | "replace" | "generate";
73
+ part?: string;
74
+ cause?: unknown;
75
+ }>;
76
+ declare class FolioDocxXmlPatchApplicationError extends FolioDocxXmlPatchApplicationError_base {}
77
+ /** Apply a guarded XML proposal and return output only after full profile validation. */
78
+ declare const applyDocxXmlPatchProposal: ({
79
+ bytes,
80
+ proposal: rawProposal,
81
+ allowedParts,
82
+ validationProfile,
83
+ archive,
84
+ limits
85
+ }: ApplyDocxXmlPatchProposalArgs) => Promise<FolioDocxXmlPatchApplication>;
86
+ //#endregion
87
+ export { ApplyDocxXmlPatchProposalArgs, FOLIO_DOCX_XML_PATCH_APPLICATION_PROFILE, FOLIO_DOCX_XML_PATCH_APPLICATION_VERSION, FolioDocxXmlPatchApplication, FolioDocxXmlPatchApplicationError, FolioDocxXmlPatchApplicationReceipt, UnsupportedFolioDocxXmlPatchApplicationProfileError, applyDocxXmlPatchProposal };