@stll/folio-core 0.33.1 → 0.34.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 (121) hide show
  1. package/dist/ai-edits/apply.d.ts +15 -0
  2. package/dist/ai-edits/apply.js +271 -48
  3. package/dist/ai-edits/headless.d.ts +47 -3
  4. package/dist/ai-edits/headless.js +53 -3
  5. package/dist/ai-edits/index.d.ts +1 -1
  6. package/dist/ai-edits/snapshot.d.ts +19 -1
  7. package/dist/ai-edits/snapshot.js +49 -5
  8. package/dist/ai-edits/table-geometry.d.ts +56 -0
  9. package/dist/ai-edits/table-geometry.js +217 -0
  10. package/dist/ai-edits/table-row-column-mutations.d.ts +34 -16
  11. package/dist/ai-edits/table-row-column-mutations.js +12 -4
  12. package/dist/ai-edits/table-template.d.ts +60 -0
  13. package/dist/ai-edits/table-template.js +176 -0
  14. package/dist/ai-edits/types.d.ts +13 -6
  15. package/dist/compare/__fixtures__/body-sequence.d.ts +61 -2
  16. package/dist/compare/__fixtures__/body-sequence.js +94 -6
  17. package/dist/compare/compare.d.ts +14 -7
  18. package/dist/compare/compare.js +136 -38
  19. package/dist/compare/formatting.d.ts +1 -1
  20. package/dist/compare/formatting.js +38 -9
  21. package/dist/compare/plan.d.ts +31 -1
  22. package/dist/compare/plan.js +233 -66
  23. package/dist/compare/types.d.ts +9 -7
  24. package/dist/compare/types.js +7 -5
  25. package/dist/compare/verification.d.ts +31 -12
  26. package/dist/compare/verification.js +106 -18
  27. package/dist/compat/eigenpal.d.ts +4 -4
  28. package/dist/compat/eigenpal.js +2 -2
  29. package/dist/controller/headerFooterEditorManager.js +11 -9
  30. package/dist/controller/layoutPipeline.js +24 -3
  31. package/dist/display-list/build/watermarkPrimitives.js +15 -3
  32. package/dist/display-list/primitives.d.ts +1 -1
  33. package/dist/document-operations.d.ts +10 -1
  34. package/dist/document-operations.js +33 -5
  35. package/dist/docx/appVersionNormalization.d.ts +49 -0
  36. package/dist/docx/appVersionNormalization.js +74 -0
  37. package/dist/docx/blockContentParser.js +3 -2
  38. package/dist/docx/drawingUtils.js +4 -3
  39. package/dist/docx/headerFooterParser.js +8 -14
  40. package/dist/docx/paragraphParser.js +48 -2
  41. package/dist/docx/rezip.d.ts +10 -4
  42. package/dist/docx/rezip.js +54 -18
  43. package/dist/docx/runParser.js +9 -8
  44. package/dist/docx/sdtProperties.js +4 -3
  45. package/dist/docx/selectiveSave.js +7 -6
  46. package/dist/docx/serializer/commentSerializer.d.ts +1 -1
  47. package/dist/docx/serializer/commentSerializer.js +43 -19
  48. package/dist/docx/serializer/documentSerializer.d.ts +3 -1
  49. package/dist/docx/serializer/documentSerializer.js +42 -78
  50. package/dist/docx/serializer/fontTableSerializer.js +8 -5
  51. package/dist/docx/serializer/headerFooterSerializer.d.ts +4 -1
  52. package/dist/docx/serializer/headerFooterSerializer.js +55 -31
  53. package/dist/docx/serializer/noteSerializer.js +34 -30
  54. package/dist/docx/serializer/numberingSerializer.js +8 -4
  55. package/dist/docx/serializer/paragraphSerializer.d.ts +1 -1
  56. package/dist/docx/serializer/paragraphSerializer.js +22 -12
  57. package/dist/docx/serializer/partNamespaces.d.ts +78 -0
  58. package/dist/docx/serializer/partNamespaces.js +324 -0
  59. package/dist/docx/serializer/runSerializer.js +1 -1
  60. package/dist/docx/serializer/settingsSerializer.js +8 -2
  61. package/dist/docx/serializer/stylesSerializer.js +8 -5
  62. package/dist/docx/serializer/tableSerializer.js +83 -18
  63. package/dist/docx/serializer/themeSerializer.js +10 -2
  64. package/dist/docx/server/build.d.ts +1 -1
  65. package/dist/docx/settingsParser.js +3 -0
  66. package/dist/docx/strictValueEncodings.gen.d.ts +15 -0
  67. package/dist/docx/strictValueEncodings.gen.js +275 -0
  68. package/dist/docx/tableParser.d.ts +0 -6
  69. package/dist/docx/tableParser.js +52 -7
  70. package/dist/docx/transitionalSpelling.d.ts +23 -0
  71. package/dist/docx/transitionalSpelling.js +36 -0
  72. package/dist/docx/universalMeasure.d.ts +20 -0
  73. package/dist/docx/universalMeasure.js +32 -0
  74. package/dist/docx/verbatimCapture.d.ts +20 -0
  75. package/dist/docx/verbatimCapture.js +131 -0
  76. package/dist/docx/vmlImageParser.js +4 -3
  77. package/dist/docx/watermarkParser.d.ts +2 -4
  78. package/dist/docx/watermarkParser.js +8 -9
  79. package/dist/docx/xmlParser.d.ts +23 -2
  80. package/dist/docx/xmlParser.js +43 -11
  81. package/dist/headless-layout.js +14 -2
  82. package/dist/index.d.ts +4 -4
  83. package/dist/index.js +2 -2
  84. package/dist/layout-bridge/convert/footnoteLayout.d.ts +2 -2
  85. package/dist/layout-bridge/convert/footnoteLayout.js +23 -10
  86. package/dist/layout-bridge/convert/headerFooterLayout.js +13 -2
  87. package/dist/layout-bridge/convert/toFlowBlocks.js +96 -13
  88. package/dist/layout-engine/index.js +11 -4
  89. package/dist/layout-engine/justifiedLineFit.d.ts +4 -4
  90. package/dist/layout-engine/justifiedLineFit.js +4 -4
  91. package/dist/layout-engine/measure/lineBreakProvider.js +1 -0
  92. package/dist/layout-engine/measure/measureBlocks.js +1 -1
  93. package/dist/layout-engine/measure/measureParagraph.js +29 -29
  94. package/dist/layout-painter/renderPage.js +6 -1
  95. package/dist/layout-painter/renderParagraph.js +18 -8
  96. package/dist/layout-painter/renderWatermark.js +11 -4
  97. package/dist/model.d.ts +3 -3
  98. package/dist/model.js +2 -2
  99. package/dist/prosemirror/attrs/index.js +11 -0
  100. package/dist/prosemirror/commands/comments.js +24 -3
  101. package/dist/prosemirror/containerFinalParagraph.d.ts +47 -0
  102. package/dist/prosemirror/containerFinalParagraph.js +92 -0
  103. package/dist/prosemirror/conversion/fromProseDoc.d.ts +8 -1
  104. package/dist/prosemirror/conversion/fromProseDoc.js +47 -9
  105. package/dist/prosemirror/conversion/toProseDoc.js +61 -14
  106. package/dist/prosemirror/extensions/core/DocExtension.js +7 -1
  107. package/dist/prosemirror/extensions/core/ParagraphExtension.js +1 -0
  108. package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.js +1 -0
  109. package/dist/prosemirror/extensions/nodes/TableExtension.js +5 -0
  110. package/dist/prosemirror/schema/marks.d.ts +3 -9
  111. package/dist/prosemirror/schema/nodes.d.ts +22 -0
  112. package/dist/server.d.ts +1 -1
  113. package/dist/types/block-id.d.ts +12 -1
  114. package/dist/types/block-id.js +17 -1
  115. package/dist/utils/canonicalJson.d.ts +14 -0
  116. package/dist/utils/canonicalJson.js +19 -0
  117. package/dist/utils/fontResolver.js +51 -0
  118. package/dist/utils/formatToStyle.d.ts +1 -1
  119. package/dist/utils/formatToStyle.js +41 -1
  120. package/dist/watermark/index.js +7 -0
  121. package/package.json +2 -2
@@ -1,4 +1,21 @@
1
+ import { resolveColorToHex } from "../utils/colorResolver.js";
2
+ import { PARAGRAPH_MARK_CHANGE_KINDS } from "@stll/docx-core/model";
1
3
  //#region src/compare/verification.ts
4
+ /**
5
+ * What the round-trip self-check found, and how to say it safely.
6
+ *
7
+ * The check compares two block projections: what accepting the generated
8
+ * revisions leaves against the target, and what rejecting them leaves against
9
+ * the base. A projection carries each block's container, style, list level and
10
+ * text, so WHICH field diverged names which part of the pipeline lost the
11
+ * difference — and that is worth reporting as a typed cause rather than as one
12
+ * opaque "did not reproduce".
13
+ *
14
+ * Every `detail` string here is structural: counts, offsets, container kinds.
15
+ * Never a phrase of either document, because a caller may log it, put it in a
16
+ * report, or quote it in a review.
17
+ */
18
+ const normalizeInlineFormattingColor = (color) => resolveColorToHex(color === void 0 ? void 0 : { rgb: color }, null);
2
19
  /** The two directions of the round trip, each an invariant of its own. */
3
20
  const COMPARE_VERIFICATION_INVARIANTS = Object.freeze(["accept-reproduces-target", "reject-reproduces-base"]);
4
21
  /**
@@ -10,13 +27,29 @@ const COMPARE_VERIFICATION_CAUSES = Object.freeze([
10
27
  "invisible-structure",
11
28
  "block-count",
12
29
  "container",
30
+ "table-geometry",
13
31
  "style",
14
32
  "list-level",
15
33
  "inline-formatting",
16
34
  "whitespace",
17
35
  "text"
18
36
  ]);
19
- const supportedInlineStyle = ({ bold, italic, underline, strike }) => `${bold === true ? "b" : ""}${italic === true ? "i" : ""}${underline === true ? "u" : ""}${strike === true ? "s" : ""}`;
37
+ const supportedInlineStyle = ({ bold, italic, underline, strike, fontFamily, fontSizePt, color, directFormatting }) => JSON.stringify([
38
+ bold === true,
39
+ italic === true,
40
+ underline === true,
41
+ strike === true,
42
+ fontFamily ?? null,
43
+ fontSizePt ?? null,
44
+ normalizeInlineFormattingColor(color) ?? null,
45
+ directFormatting?.bold === true,
46
+ directFormatting?.italic === true,
47
+ directFormatting?.underline === true,
48
+ directFormatting?.strike === true,
49
+ directFormatting?.fontFamily ?? null,
50
+ directFormatting?.fontSizePt ?? null,
51
+ normalizeInlineFormattingColor(directFormatting?.color ?? void 0) ?? null
52
+ ]);
20
53
  /** Effective supported formatting with equivalent adjacent runs normalized. */
21
54
  const projectSupportedInlineFormatting = ({ text, previewRuns }) => {
22
55
  const projected = [];
@@ -116,6 +149,21 @@ const firstDivergence = (actual, expected) => {
116
149
  };
117
150
  };
118
151
  /**
152
+ * The failure two table-geometry projections describe, or `null` when they
153
+ * agree. One line per table, so the detail names which table diverged and
154
+ * whether the count itself did — never a property value, which could carry a
155
+ * style name either document chose.
156
+ */
157
+ const classifyGeometryMismatch = ({ invariant, story, actual, expected }) => {
158
+ if (sameProjection(actual, expected)) return null;
159
+ return {
160
+ invariant,
161
+ cause: "table-geometry",
162
+ story,
163
+ detail: actual.length === expected.length ? `table ${String(actual.findIndex((entry, index) => entry !== expected[index]))} of ${String(actual.length)} carries different properties` : `${String(actual.length)} tables against ${String(expected.length)}`
164
+ };
165
+ };
166
+ /**
119
167
  * The failure two projections describe, or `null` when they agree.
120
168
  *
121
169
  * Total over the causes by construction: the last branch is unconditional, so
@@ -142,48 +190,88 @@ const classifyProjectionMismatch = ({ invariant, story, actual, expected }) => {
142
190
  if (actual.length !== expected.length) return failure("block-count", `${counts}, first differing ${at}`);
143
191
  return failure("text", `a ${containerKind(left.container)} block's text does not match ${at}, length ${String(left.text.length)} against ${String(right.text.length)} (${counts})`);
144
192
  };
145
- /** The mark kinds that resolve by joining the paragraph with the one after it. */
146
- const JOINS_FORWARD_ON_ACCEPT = Object.freeze(["del", "moveFrom"]);
147
- const joinsForwardOnAccept = (value) => JOINS_FORWARD_ON_ACCEPT.some((kind) => kind === value);
193
+ const isAParagraphMarkChangeKind = (value) => PARAGRAPH_MARK_CHANGE_KINDS.some((kind) => kind === value);
148
194
  const isRecord = (value) => typeof value === "object" && value !== null;
149
195
  const isParagraph = (value) => isRecord(value) && value["type"] === "paragraph";
150
196
  /**
151
- * Every container in a package whose final paragraph mark carries a deletion.
197
+ * A row the package marks deleted, whose cells' marks go with it.
198
+ *
199
+ * A deleted table row is written as `w:trPr/w:del` PLUS a deletion on every
200
+ * mark the row's cells end with: accepting takes the whole row away, so those
201
+ * marks never have to join anything and are the shape the format asks for.
202
+ */
203
+ const isADeletedTableRow = (value) => {
204
+ const change = value["structuralChange"];
205
+ return isRecord(change) && change["type"] === "tableRowDeletion";
206
+ };
207
+ /**
208
+ * Every container in a package whose final paragraph mark carries a revision.
152
209
  *
153
- * A deleted paragraph mark says "join this paragraph with the one after it".
154
- * The last paragraph of a body, a table cell, a header or footer, a note or a
155
- * text box has no paragraph after it, so the mark states an edit that cannot
156
- * be carried out, and a consumer refuses the package rather than opening it.
210
+ * A deleted paragraph mark says "join this paragraph with the one after it",
211
+ * and an inserted one says that break was ADDED, so rejecting it closes the
212
+ * paragraph back over the next one. The last paragraph of a body, a table
213
+ * cell, a header or footer, a note or a text box has no paragraph after it, so
214
+ * neither direction states an edit that can be carried out: a consumer refuses
215
+ * the package, or opens it and leaves a revision standing that neither
216
+ * accepting nor rejecting everything can clear. The exception is a cell of a
217
+ * row the package is DELETING: there the mark leaves with its row.
157
218
  *
158
219
  * The walk is over the package model rather than over a list of the containers
159
220
  * known today: a container is any sequence that ends in a paragraph, so a part
160
221
  * the model grows later is covered the day it arrives instead of the day
161
222
  * someone remembers this function.
223
+ *
224
+ * `since` scopes it to the revisions a comparison MINTED: a base may arrive
225
+ * carrying one of these on a paragraph in a part no story mounts, which folio
226
+ * preserves the way it preserves everything else it parses. What this proves
227
+ * is that the comparison writes none of its own.
162
228
  */
163
- const deletedFinalParagraphMarks = (packageModel) => {
229
+ const revisedFinalParagraphMarks = (packageModel, { since = 0 } = {}) => {
164
230
  const found = [];
165
- const visit = (value, path) => {
231
+ const trail = ["package"];
232
+ const pathOf = () => {
233
+ let path = "";
234
+ for (const segment of trail) path += typeof segment === "number" ? `[${String(segment)}]` : `.${segment}`;
235
+ return path.slice(1);
236
+ };
237
+ const visit = (value, insideADeletedRow) => {
166
238
  if (Array.isArray(value)) {
167
239
  const last = value.at(-1);
168
240
  const mark = isParagraph(last) ? last["pPrMark"] : void 0;
169
241
  const kind = isRecord(mark) ? mark["kind"] : void 0;
170
- if (joinsForwardOnAccept(kind)) found.push({
171
- container: path,
242
+ const info = isRecord(mark) ? mark["info"] : void 0;
243
+ const revisionId = isRecord(info) ? info["id"] : void 0;
244
+ const isOurs = typeof revisionId === "number" ? revisionId >= since : true;
245
+ if (isAParagraphMarkChangeKind(kind) && isOurs && !insideADeletedRow) found.push({
246
+ container: pathOf(),
172
247
  paragraphIndex: value.length - 1,
173
248
  kind
174
249
  });
175
- for (const [index, item] of value.entries()) visit(item, `${path}[${String(index)}]`);
250
+ for (const [index, item] of value.entries()) {
251
+ trail.push(index);
252
+ visit(item, insideADeletedRow);
253
+ trail.pop();
254
+ }
176
255
  return;
177
256
  }
178
257
  if (value instanceof Map) {
179
- for (const [key, item] of value) visit(item, `${path}.${String(key)}`);
258
+ for (const [key, item] of value) {
259
+ trail.push(String(key));
260
+ visit(item, insideADeletedRow);
261
+ trail.pop();
262
+ }
180
263
  return;
181
264
  }
182
265
  if (!isRecord(value) || value instanceof Date || ArrayBuffer.isView(value)) return;
183
- for (const [key, item] of Object.entries(value)) visit(item, `${path}.${key}`);
266
+ const inADeletedRow = insideADeletedRow || isADeletedTableRow(value);
267
+ for (const [key, item] of Object.entries(value)) {
268
+ trail.push(key);
269
+ visit(item, inADeletedRow);
270
+ trail.pop();
271
+ }
184
272
  };
185
- visit(packageModel, "package");
273
+ visit(packageModel, false);
186
274
  return found;
187
275
  };
188
276
  //#endregion
189
- export { COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, classifyProjectionMismatch, deletedFinalParagraphMarks, projectSupportedInlineFormatting, sameProjection };
277
+ export { COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, classifyGeometryMismatch, classifyProjectionMismatch, projectSupportedInlineFormatting, revisedFinalParagraphMarks, sameProjection };
@@ -1,15 +1,15 @@
1
+ import { document_d_exports } from "../types/document.js";
1
2
  import { FolioAIBlock, FolioAIBlockAnchor, FolioAIBlockKind, FolioAIBlockPreviewRun, FolioAIBlockTableLocation, FolioAIComment, FolioAIEditAppliedOperation, FolioAIEditApplyMode, FolioAIEditApplyResult, FolioAIEditNormalization, FolioAIEditNormalizationCode, FolioAIEditOperation, FolioAIEditPrecondition, FolioAIEditReviewMeta, FolioAIEditSeverity, FolioAIEditSkipReason, FolioAIEditSkippedOperation, FolioAIEditSnapshot, FolioAISignatureParty } from "../ai-edits/types.js";
2
3
  import { WORD_DIFF_GRANULARITIES, WordDiffGranularity, WordDiffNormalization, WordDiffOptions, WordDiffSegment, diffWordSegments } from "../ai-edits/word-diff.js";
3
4
  import { FolioAIEditApplyOutcome, FolioRevisionStamp, FolioWordDiffOptions, applyFolioAIEditOperations } from "../ai-edits/apply.js";
4
- import { document_d_exports } from "../types/document.js";
5
5
  import { ApplyFolioDocumentOperationsOptions, 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, FolioDocumentOperation, FolioDocumentOperationAffectedTarget, FolioDocumentOperationBatch, FolioDocumentOperationCapabilities, FolioDocumentOperationIssue, FolioDocumentOperationMode, FolioDocumentOperationPrecondition, FolioDocumentOperationReceipt, FolioDocumentOperationRecovery, FolioDocumentOperationResult, FolioDocumentOperationResultBase, FolioDocumentOperationStatus, FolioDocumentOperationStory, FolioDocumentOperationType, FolioDocumentOperationUndoFailureReason, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch } from "../document-operations.js";
6
6
  import { createFolioAIEditSnapshot, hashFolioAIBlockText, isFolioAIContentBlock, normalizeFolioAIBlockText } from "../ai-edits/snapshot.js";
7
- import { DeriveBlockIdInput, FolioBlockId, deriveBlockId, getFolioParaIdFromBlockId, isFolioBlockId, isSequentialFolioBlockId } from "../types/block-id.js";
7
+ import { DeriveBlockIdInput, FolioBlockId, currentFolioBlockId, deriveBlockId, getFolioParaIdFromBlockId, isFolioBlockId, isSequentialFolioBlockId } from "../types/block-id.js";
8
8
  import { AIBarStatus, AIChatMode, AICitation, AICitationSource, AIGenerateInput, AISuggestion, AISuggestionApplyMode, AISuggestionPreset, AISuggestionSeverity, AISuggestionStatus, DEFAULT_AI_SUGGESTION_PRESETS } from "../ai-suggestions/types.js";
9
9
  import { ApplyResult, applySuggestions } from "../ai-suggestions/apply.js";
10
10
  import { ResolvedAnchor, isSuggestionStale, resolveSuggestionAnchor } from "../ai-suggestions/conflict.js";
11
11
  import { PositionalText, buildPositionalText } from "../ai-suggestions/text-positions.js";
12
- import { COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, CompareVerification, CompareVerificationCause, CompareVerificationFailure, CompareVerificationInvariant, FinalParagraphMarkDeletion } from "../compare/verification.js";
12
+ import { COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, CompareVerification, CompareVerificationCause, CompareVerificationFailure, CompareVerificationInvariant, FinalParagraphMarkRevision } from "../compare/verification.js";
13
13
  import { COMPARE_UNSUPPORTED_REASONS, CompareChange, CompareChangeLocation, CompareDocxApplyError, CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, CompareFormatRange, CompareResult, CompareUnsupportedPart, CompareUnsupportedReason, InvalidCompareDocxOptionsError } from "../compare/types.js";
14
14
  import { MAX_COMPARE_OPERATIONS, compareDocx } from "../compare/compare.js";
15
15
  import { DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DocumentPreset, DocumentStyleSet } from "../style-sets/types.js";
@@ -37,4 +37,4 @@ import { getGoogleFontsEnabled, setEmbeddedFontFamilyMap, setGoogleFontsEnabled
37
37
  import { DOCX_CONFORMANCE_CLASSES } from "../index.js";
38
38
  type Document = document_d_exports.Document;
39
39
  type DocxConformanceClass = document_d_exports.DocxConformanceClass;
40
- export { type AIBarStatus, type AIChatMode, type AICitation, type AICitationRange, type AICitationSource, type AIGenerateInput, type AISuggestion, type AISuggestionApplyMode, type AISuggestionPreset, type AISuggestionSeverity, type AISuggestionStatus, type AcceptAutocompleteResult, type AnonymizationMatch, type AnonymizationTerm, type ApplyFolioDocumentOperationsOptions, type ApplyResult, type AutocompleteSuggestionPluginOptions, type AutocompleteSuggestionState, type AutocompleteSuggestionStatus, type AutocompleteTriggerCheck, type AutocompleteTriggerOptions, type AutocompleteTriggerSkipReason, type BlockRect, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, type CompareChange, type CompareChangeLocation, CompareDocxApplyError, type CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, type CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, type CompareFormatRange, type CompareResult, type CompareUnsupportedPart, type CompareUnsupportedReason, type CompareVerification, type CompareVerificationCause, type CompareVerificationFailure, type CompareVerificationInvariant, type CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocumentPreset, type DocumentStyleCatalog, type DocumentStyleCatalogEntry, type DocumentStyleSet, type DocxCompatibility, type DocxCompatibilityContext, type DocxCompatibilityIssue, type DocxCompatibilityLocation, type DocxCompatibilityPart, type DocxConformanceClass, type EmbeddedFont, type EmbeddedFontParts, type ExtractDocumentStyleSetOptions, 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, type FinalParagraphMarkDeletion, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIBlockTableLocation, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyOutcome, type FolioAIEditApplyResult, type FolioAIEditNormalization, type FolioAIEditNormalizationCode, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAISignatureParty, type FolioBlockId, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationResultBase, type FolioDocumentOperationStatus, type FolioDocumentOperationStory, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocxCompatibilityHost, type FolioDocxCompatibilityProfile, type FolioRevisionStamp, type FolioWordDiffOptions, type ImageMeta, type ImageRef, type InspectDocxCompatibilityOptions, InvalidCompareDocxOptionsError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, type MarkdownOptions, type MarkdownResult, type PositionalText, type ResolvedAnchor, STELLA_STYLE_SET_NAME, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, type WordDiffGranularity, type WordDiffNormalization, type WordDiffOptions, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
40
+ export { type AIBarStatus, type AIChatMode, type AICitation, type AICitationRange, type AICitationSource, type AIGenerateInput, type AISuggestion, type AISuggestionApplyMode, type AISuggestionPreset, type AISuggestionSeverity, type AISuggestionStatus, type AcceptAutocompleteResult, type AnonymizationMatch, type AnonymizationTerm, type ApplyFolioDocumentOperationsOptions, type ApplyResult, type AutocompleteSuggestionPluginOptions, type AutocompleteSuggestionState, type AutocompleteSuggestionStatus, type AutocompleteTriggerCheck, type AutocompleteTriggerOptions, type AutocompleteTriggerSkipReason, type BlockRect, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, type CompareChange, type CompareChangeLocation, CompareDocxApplyError, type CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, type CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, type CompareFormatRange, type CompareResult, type CompareUnsupportedPart, type CompareUnsupportedReason, type CompareVerification, type CompareVerificationCause, type CompareVerificationFailure, type CompareVerificationInvariant, type CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocumentPreset, type DocumentStyleCatalog, type DocumentStyleCatalogEntry, type DocumentStyleSet, type DocxCompatibility, type DocxCompatibilityContext, type DocxCompatibilityIssue, type DocxCompatibilityLocation, type DocxCompatibilityPart, type DocxConformanceClass, type EmbeddedFont, type EmbeddedFontParts, type ExtractDocumentStyleSetOptions, 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, type FinalParagraphMarkRevision, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIBlockTableLocation, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyOutcome, type FolioAIEditApplyResult, type FolioAIEditNormalization, type FolioAIEditNormalizationCode, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAISignatureParty, type FolioBlockId, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationResultBase, type FolioDocumentOperationStatus, type FolioDocumentOperationStory, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocxCompatibilityHost, type FolioDocxCompatibilityProfile, type FolioRevisionStamp, type FolioWordDiffOptions, type ImageMeta, type ImageRef, type InspectDocxCompatibilityOptions, InvalidCompareDocxOptionsError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, type MarkdownOptions, type MarkdownResult, type PositionalText, type ResolvedAnchor, STELLA_STYLE_SET_NAME, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, type WordDiffGranularity, type WordDiffNormalization, type WordDiffOptions, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
@@ -27,8 +27,8 @@ import { clearTemplateSlashMenu, consumeTemplateSlashQuery, getTemplateSlashMenu
27
27
  import { extractDocumentStyleSet, extractDocumentStyleSetFromDocx, inspectDocumentStyles, inspectDocumentStylesFromDocx } from "../style-sets/extract.js";
28
28
  import { STELLA_STYLE_SET_NAME, createStellaStyleDocumentPreset, createStellaStyleSet } from "../style-sets/stellaStyle.js";
29
29
  import { DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION } from "../style-sets/types.js";
30
- import { deriveBlockId, getFolioParaIdFromBlockId, isFolioBlockId, isSequentialFolioBlockId } from "../types/block-id.js";
30
+ import { currentFolioBlockId, deriveBlockId, getFolioParaIdFromBlockId, isFolioBlockId, isSequentialFolioBlockId } from "../types/block-id.js";
31
31
  import { createEmptyDocument } from "../utils/createDocument.js";
32
32
  import { getGoogleFontsEnabled, setEmbeddedFontFamilyMap, setGoogleFontsEnabled } from "../utils/fontResolver.js";
33
33
  import { mergeDocumentContent } from "../utils/mergeDocumentContent.js";
34
- export { COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, CompareDocxApplyError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, 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, InvalidCompareDocxOptionsError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, STELLA_STYLE_SET_NAME, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
34
+ export { COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, CompareDocxApplyError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, 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, InvalidCompareDocxOptionsError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, STELLA_STYLE_SET_NAME, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
@@ -10,19 +10,21 @@ import { schema } from "../prosemirror/schema/index.js";
10
10
  import { EditorState } from "prosemirror-state";
11
11
  import { EditorView } from "prosemirror-view";
12
12
  //#region src/controller/headerFooterEditorManager.ts
13
- /**
14
- * Framework-neutral lifecycle owner for persistent header/footer EditorViews.
15
- *
16
- * Each distinct relationship id owns one off-screen ProseMirror view. Painted
17
- * header/footer instances that share that relationship therefore share live
18
- * editor state, and adapters only decide when to synchronize or destroy the
19
- * manager.
20
- */
13
+ const DETACHED_WATERMARK_HOST = Symbol.for("stll.detachedWatermarkHost");
14
+ const headerFooterToProseDocWithDetachedWatermarkHost = (headerFooter, options) => {
15
+ return headerFooterToProseDoc(headerFooter.content.map((block, blockIndex) => {
16
+ if (blockIndex !== headerFooter.watermarkBlockIndex || block.type !== "paragraph") return block;
17
+ return {
18
+ ...block,
19
+ [DETACHED_WATERMARK_HOST]: true
20
+ };
21
+ }), options);
22
+ };
21
23
  const buildInitialState = (headerFooter, styles, theme, manager) => {
22
24
  const proseDocOptions = {};
23
25
  if (styles) proseDocOptions.styles = styles;
24
26
  if (theme !== void 0) proseDocOptions.theme = theme;
25
- const document = headerFooterToProseDoc(headerFooter.content, proseDocOptions);
27
+ const document = headerFooter.watermarkBlockIndex === void 0 ? headerFooterToProseDoc(headerFooter.content, proseDocOptions) : headerFooterToProseDocWithDetachedWatermarkHost(headerFooter, proseDocOptions);
26
28
  return ensureBaseDirectionInState(ensureParaIdsInState(EditorState.create({
27
29
  doc: document,
28
30
  schema,
@@ -1,6 +1,7 @@
1
1
  import { createDisplayListPagePainter } from "../display-list/editor/displayListPagePainter.js";
2
2
  import { PAGE_RENDERER, displayListFurnitureFrom } from "../display-list/editor/pageRenderer.js";
3
3
  import { resolveDocumentGridLinePitch } from "../docx/documentGrid.js";
4
+ import { formatOoxmlCounter } from "../docx/ooxmlCounterFormatter.js";
4
5
  import { buildBookmarkPageMap } from "../fields/bookmarkPages.js";
5
6
  import { buildBookmarkText } from "../fields/bookmarkText.js";
6
7
  import { buildHeaderFooterFieldValues, fieldValuesEqual, resolveFieldValues } from "../fields/resolveFieldValues.js";
@@ -26,6 +27,17 @@ import { getMargins, getPageNumbering, getPageSize, twipsToPixels } from "../pag
26
27
  import { templatePreviewValuesKey } from "../prosemirror/plugins/templatePreviewValues.js";
27
28
  import { getDocumentWatermark } from "../watermark/index.js";
28
29
  //#region src/controller/layoutPipeline.ts
30
+ const formatEndnoteTexts = (numbers, formatNumber) => {
31
+ const texts = /* @__PURE__ */ new Map();
32
+ for (const [id, displayNumber] of numbers) texts.set(id, formatNumber(displayNumber));
33
+ return texts;
34
+ };
35
+ /** Resolve only package-owned picture-watermark bytes for the DOM painter. */
36
+ const resolveWatermarkImageSrc = (document, watermark) => {
37
+ if (watermark?.kind !== "picture" || watermark.imageTargetExternal === true) return;
38
+ const target = watermark.imageTarget;
39
+ return target === void 0 ? void 0 : document.package.media?.get(target)?.dataUrl;
40
+ };
29
41
  function bodyMarginsClearHeaderFooter({ authoredMargins, preparedHeader, preparedFooter }) {
30
42
  const headerBottom = preparedHeader ? (authoredMargins.header ?? 0) + (preparedHeader.marginPushBottom ?? preparedHeader.height) : authoredMargins.top;
31
43
  const footerClearance = preparedFooter ? (authoredMargins.footer ?? 0) + (preparedFooter.marginPushBottom ?? preparedFooter.height) : authoredMargins.bottom;
@@ -123,7 +135,10 @@ function runLayoutPipeline(deps, state, options = {}) {
123
135
  };
124
136
  const finalSectionDocumentGridLinePitchTwips = resolveDocumentGridLinePitch(document?.package.document.sections?.at(-1)?.properties.docGrid);
125
137
  if (finalSectionDocumentGridLinePitchTwips !== void 0) flowOpts.finalSectionDocumentGridLinePitchTwips = finalSectionDocumentGridLinePitchTwips;
126
- let newBlocks = toFlowBlocks(state.doc, flowOpts);
138
+ let newBlocks = toFlowBlocks(document === null ? state.doc.type.create({
139
+ ...state.doc.attrs,
140
+ _finalSectionStart: sectionProperties?.sectionStart ?? null
141
+ }, state.doc.content, state.doc.marks) : state.doc, flowOpts);
127
142
  const previewState = templatePreviewValuesKey.getState(state);
128
143
  const previewEntries = previewState?.entries ?? EMPTY_TEMPLATE_PREVIEW_ENTRIES;
129
144
  const previewMode = previewState?.preview?.mode ?? "plain";
@@ -144,9 +159,11 @@ function runLayoutPipeline(deps, state, options = {}) {
144
159
  const footnoteDisplayNumbers = documentFootnotes ? computeNoteDisplayNumbers(documentFootnotes, footnoteRefs.map((ref) => ref.footnoteId)) : void 0;
145
160
  const documentEndnotes = document?.package.endnotes;
146
161
  const endnoteDisplayNumbers = documentEndnotes ? computeNoteDisplayNumbers(documentEndnotes, collectEndnoteRefs(newBlocks).map((ref) => ref.endnoteId)) : void 0;
162
+ const endnoteNumberFormat = document?.package.document.sections?.at(-1)?.properties.endnotePr?.numFmt ?? "lowerRoman";
163
+ const endnoteTexts = endnoteDisplayNumbers ? formatEndnoteTexts(endnoteDisplayNumbers, (displayNumber) => formatOoxmlCounter(displayNumber, endnoteNumberFormat)) : void 0;
147
164
  newBlocks = remapNoteMarkerText(newBlocks, {
148
165
  ...footnoteDisplayNumbers ? { footnoteNumbers: footnoteDisplayNumbers } : {},
149
- ...endnoteDisplayNumbers ? { endnoteNumbers: endnoteDisplayNumbers } : {}
166
+ ...endnoteTexts ? { endnoteTexts } : {}
150
167
  });
151
168
  outcome.blocks = newBlocks;
152
169
  const hfMetricsHeader = {
@@ -479,12 +496,16 @@ function runLayoutPipeline(deps, state, options = {}) {
479
496
  if (document) {
480
497
  const watermark = getDocumentWatermark(document);
481
498
  if (watermark) renderOpts.watermark = watermark;
499
+ let watermarkByHeaderRId;
482
500
  const headers = document.package.headers;
483
501
  if (headers) {
484
- const watermarkByHeaderRId = /* @__PURE__ */ new Map();
502
+ watermarkByHeaderRId = /* @__PURE__ */ new Map();
485
503
  for (const [rId, header] of headers) if (header.watermark) watermarkByHeaderRId.set(rId, header.watermark);
486
504
  if (watermarkByHeaderRId.size > 0) renderOpts.watermarkByHeaderRId = watermarkByHeaderRId;
487
505
  }
506
+ const pictureSources = new Set([watermark, ...watermarkByHeaderRId?.values() ?? []].filter((candidate) => candidate !== void 0).map((candidate) => resolveWatermarkImageSrc(document, candidate)));
507
+ const watermarkImageSrc = pictureSources.size === 1 ? [...pictureSources].at(0) : void 0;
508
+ if (watermarkImageSrc !== void 0) renderOpts.watermarkImageSrc = watermarkImageSrc;
488
509
  }
489
510
  if (pageRenderer === PAGE_RENDERER.displayList) renderOpts.paintPage = createDisplayListPagePainter({
490
511
  layout: newLayout,
@@ -1,4 +1,4 @@
1
- import { pxToPt } from "../../layout-engine/measure/measureHelpers.js";
1
+ import { ptToPx, pxToPt } from "../../layout-engine/measure/measureHelpers.js";
2
2
  import { getFontMetrics } from "../../layout-engine/measure/measureProvider.js";
3
3
  import { parseDisplayColor } from "./colors.js";
4
4
  import { buildGlyphs, glyphRunText } from "./glyphs.js";
@@ -28,7 +28,7 @@ const TEXT_DEFAULT_COLOR = "#C0C0C0";
28
28
  const TEXT_DEFAULT_OPACITY = .5;
29
29
  const TEXT_DIAGONAL_DEGREES = -45;
30
30
  const PICTURE_NATIVE_SCALE = 1;
31
- const PICTURE_WASHOUT_OPACITY = .4;
31
+ const PICTURE_WASHOUT_OPACITY = .18;
32
32
  const paintTextWatermark = (watermark, page, context) => {
33
33
  if (watermark.text.length === 0) return [];
34
34
  const style = {
@@ -98,6 +98,18 @@ const containedRect = (page, scale, pixelWidth, pixelHeight) => {
98
98
  heightPx
99
99
  };
100
100
  };
101
+ /** The centred VML shape box, when both authored dimensions survived parsing. */
102
+ const authoredPictureRect = (page, widthPt, heightPt) => {
103
+ if (widthPt === void 0 || heightPt === void 0) return;
104
+ const widthPx = ptToPx(widthPt);
105
+ const heightPx = ptToPx(heightPt);
106
+ return {
107
+ xPx: (page.size.w - widthPx) / 2,
108
+ yPx: (page.size.h - heightPx) / 2,
109
+ widthPx,
110
+ heightPx
111
+ };
112
+ };
101
113
  const paintPictureWatermark = (watermark, page, imageSrc, context) => {
102
114
  if (imageSrc === void 0) {
103
115
  context.unsupported.report(UNSUPPORTED_CONSTRUCT.watermark, context.pageIndex, `picture watermark ${watermark.imageRId} has no resolved image source: the relationship id resolves in the package layer, not in the builder`);
@@ -113,7 +125,7 @@ const paintPictureWatermark = (watermark, page, imageSrc, context) => {
113
125
  return [{
114
126
  kind: "image",
115
127
  image: ref,
116
- rect: containedRect(page, watermark.scale ?? PICTURE_NATIVE_SCALE, source?.pixelWidth ?? 0, source?.pixelHeight ?? 0),
128
+ rect: authoredPictureRect(page, watermark.widthPt, watermark.heightPt) ?? containedRect(page, watermark.scale ?? PICTURE_NATIVE_SCALE, source?.pixelWidth ?? 0, source?.pixelHeight ?? 0),
117
129
  opacity: watermark.washout === false ? 1 : PICTURE_WASHOUT_OPACITY
118
130
  }];
119
131
  };
@@ -15,7 +15,7 @@ import { hasComplexScript, isComplexScriptCodePoint } from "../utils/scriptSegme
15
15
  * advances rightward from its origin whatever the paragraph does.
16
16
  */
17
17
  declare const glyphCellOffsetsPx: (run: DisplayGlyphRun) => readonly number[];
18
- declare const DISPLAY_PRIMITIVE_KINDS: ("line" | "rect" | "image" | "glyphRun" | "clipGroup" | "rotateGroup" | "opacityGroup")[];
18
+ declare const DISPLAY_PRIMITIVE_KINDS: ("glyphRun" | "rect" | "line" | "image" | "clipGroup" | "rotateGroup" | "opacityGroup")[];
19
19
  /**
20
20
  * Dash geometry of each stroke pattern, as multiples of the stroke thickness.
21
21
  *
@@ -1,3 +1,4 @@
1
+ import { FolioTableTemplates } from "./ai-edits/table-template.js";
1
2
  import { FolioAIEditAppliedOperation, FolioAIEditApplyMode, FolioAIEditNormalization, FolioAIEditOperation, FolioAIEditPrecondition, FolioAIEditSkippedOperation, FolioAIEditSnapshot, FolioAITextRangeHandle } from "./ai-edits/types.js";
2
3
  import { FolioAIEditView, FolioRevisionStamp, FolioWordDiffOptions } from "./ai-edits/apply.js";
3
4
  //#region src/document-operations.d.ts
@@ -266,7 +267,15 @@ type ApplyFolioDocumentOperationsOptions = {
266
267
  revisionStamp?: FolioRevisionStamp;
267
268
  /** Token size a replacement's redline is cut at. Word-level by default. */
268
269
  wordDiff?: FolioWordDiffOptions;
270
+ /**
271
+ * Tables and rows an `insertTable` / `insertTableRow` in the batch places
272
+ * verbatim, by operation id. Outside the serialized batch because a table
273
+ * node is not JSON: the contract still describes a table by its cell texts,
274
+ * and an in-process caller that already holds the table — a comparison
275
+ * copying the target document's — hands the whole thing over instead.
276
+ */
277
+ tableTemplates?: FolioTableTemplates;
269
278
  };
270
- declare const applyFolioDocumentOperations: ({ view, snapshot, batch, story, author, createCommentId, createUndoHandle, revisionStamp, wordDiff }: ApplyFolioDocumentOperationsOptions) => FolioDocumentOperationResult;
279
+ declare const applyFolioDocumentOperations: ({ view, snapshot, batch, story, author, createCommentId, createUndoHandle, revisionStamp, wordDiff, tableTemplates }: ApplyFolioDocumentOperationsOptions) => FolioDocumentOperationResult;
271
280
  //#endregion
272
281
  export { ApplyFolioDocumentOperationsOptions, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_BATCH_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_KEYS_BY_TYPE, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FolioDocumentOperation, FolioDocumentOperationAffectedTarget, FolioDocumentOperationBatch, FolioDocumentOperationBatchPrecondition, FolioDocumentOperationCapabilities, FolioDocumentOperationIssue, FolioDocumentOperationMode, FolioDocumentOperationPrecondition, FolioDocumentOperationQueuedOperation, FolioDocumentOperationReceipt, FolioDocumentOperationRecovery, FolioDocumentOperationResult, FolioDocumentOperationResultBase, FolioDocumentOperationStatus, FolioDocumentOperationStory, FolioDocumentOperationType, FolioDocumentOperationUndoFailureReason, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch };
@@ -143,6 +143,24 @@ const readOptionalBoolean = (value, key, path) => {
143
143
  if (typeof candidate === "boolean") return candidate;
144
144
  return invalidBatch(`${path}.${key}`, "expected a boolean when provided");
145
145
  };
146
+ const readClearableNonEmptyString = (value, key, path) => {
147
+ const candidate = value[key];
148
+ if (candidate === void 0 || candidate === null) return candidate;
149
+ if (typeof candidate === "string" && candidate.trim().length > 0) return candidate.trim();
150
+ return invalidBatch(`${path}.${key}`, "expected a non-empty string or null when provided");
151
+ };
152
+ const readClearableFontSize = (value, key, path) => {
153
+ const candidate = value[key];
154
+ if (candidate === void 0 || candidate === null) return candidate;
155
+ if (typeof candidate === "number" && candidate > 0 && Number.isInteger(candidate * 2)) return candidate;
156
+ return invalidBatch(`${path}.${key}`, "expected a positive half-point value or null");
157
+ };
158
+ const readClearableRgbColor = (value, key, path) => {
159
+ const candidate = value[key];
160
+ if (candidate === void 0 || candidate === null) return candidate;
161
+ if (typeof candidate === "string" && /^#?[0-9a-fA-F]{6}$/u.test(candidate)) return candidate.replace(/^#/u, "").toUpperCase();
162
+ return invalidBatch(`${path}.${key}`, "expected a six-digit RGB color or null");
163
+ };
146
164
  const readOptionalStringArray = (value, key, path) => {
147
165
  const candidate = value[key];
148
166
  if (candidate === void 0) return;
@@ -238,18 +256,27 @@ const readInlineFormatting = (value, path) => {
238
256
  "bold",
239
257
  "italic",
240
258
  "underline",
241
- "strike"
259
+ "strike",
260
+ "fontFamily",
261
+ "fontSizePt",
262
+ "color"
242
263
  ]);
243
264
  const bold = readOptionalBoolean(candidate, "bold", formattingPath);
244
265
  const italic = readOptionalBoolean(candidate, "italic", formattingPath);
245
266
  const underline = readOptionalBoolean(candidate, "underline", formattingPath);
246
267
  const strike = readOptionalBoolean(candidate, "strike", formattingPath);
247
- if (bold === void 0 && italic === void 0 && underline === void 0 && strike === void 0) return invalidBatch(formattingPath, "expected at least one formatting property");
268
+ const fontFamily = readClearableNonEmptyString(candidate, "fontFamily", formattingPath);
269
+ const fontSizePt = readClearableFontSize(candidate, "fontSizePt", formattingPath);
270
+ const color = readClearableRgbColor(candidate, "color", formattingPath);
271
+ if (bold === void 0 && italic === void 0 && underline === void 0 && strike === void 0 && fontFamily === void 0 && fontSizePt === void 0 && color === void 0) return invalidBatch(formattingPath, "expected at least one formatting property");
248
272
  return {
249
273
  ...bold !== void 0 && { bold },
250
274
  ...italic !== void 0 && { italic },
251
275
  ...underline !== void 0 && { underline },
252
- ...strike !== void 0 && { strike }
276
+ ...strike !== void 0 && { strike },
277
+ ...fontFamily !== void 0 && { fontFamily },
278
+ ...fontSizePt !== void 0 && { fontSizePt },
279
+ ...color !== void 0 && { color }
253
280
  };
254
281
  };
255
282
  const readOptionalComment = (value, path) => {
@@ -879,7 +906,7 @@ const getFolioDocumentOperationReceiptsForStory = ({ operations, applied, story
879
906
  });
880
907
  return receipts;
881
908
  };
882
- const applyFolioDocumentOperations = ({ view, snapshot, batch, story = "main", author, createCommentId, createUndoHandle, revisionStamp, wordDiff }) => {
909
+ const applyFolioDocumentOperations = ({ view, snapshot, batch, story = "main", author, createCommentId, createUndoHandle, revisionStamp, wordDiff, tableTemplates }) => {
883
910
  const parsedBatch = parseFolioDocumentOperationBatch(batch);
884
911
  const apply = ({ targetView, targetCreateCommentId = createCommentId, preview = false }) => {
885
912
  return (preview ? previewFolioAIEditOperations : applyFolioAIEditOperations)({
@@ -890,7 +917,8 @@ const applyFolioDocumentOperations = ({ view, snapshot, batch, story = "main", a
890
917
  ...author !== void 0 && { author },
891
918
  ...targetCreateCommentId !== void 0 && { createCommentId: targetCreateCommentId },
892
919
  ...revisionStamp !== void 0 && { revisionStamp },
893
- ...wordDiff !== void 0 && { wordDiff }
920
+ ...wordDiff !== void 0 && { wordDiff },
921
+ ...tableTemplates !== void 0 && { tableTemplates }
894
922
  });
895
923
  };
896
924
  const preview = () => apply({
@@ -0,0 +1,49 @@
1
+ //#region src/docx/appVersionNormalization.d.ts
2
+ /**
3
+ * Keep the application version a package states about itself in the form the
4
+ * schema gives it.
5
+ *
6
+ * `AppVersion` in the extended-properties part is `XX.YYYY`: a one- or
7
+ * two-digit integer, a dot, and four digits. Producers exist that write a
8
+ * three-part version there instead, and folio copies `docProps/app.xml`
9
+ * through verbatim when it saves a document it did not create — so a package
10
+ * can carry a value with two dots in, and a save that copies it out hands a
11
+ * consumer a package it refuses to open at all.
12
+ *
13
+ * {@link appVersionInSchemaForm} is the one mapping, and it is a pure function
14
+ * of the value alone: it keeps the leading integer where the value opens with
15
+ * one the form allows, and writes the build digits the form requires. Nothing
16
+ * else in the part is touched, and a package that carries no extended
17
+ * properties keeps carrying none — synthesizing metadata a document never
18
+ * stated is a different decision.
19
+ */
20
+ declare const AppVersionSchemaError_base: import("better-result").TaggedErrorClass<"AppVersionSchemaError">;
21
+ /**
22
+ * A value reached the package that the schema form does not accept.
23
+ *
24
+ * The normalization hands every value it writes to one choke point, which
25
+ * throws this rather than letting the package go out carrying a version a
26
+ * consumer refuses.
27
+ */
28
+ declare class AppVersionSchemaError extends AppVersionSchemaError_base<{
29
+ message: string;
30
+ appVersion: string;
31
+ }> {}
32
+ /**
33
+ * `value` when it already fits, and a value derived from it when it does not.
34
+ *
35
+ * The derivation reads the value and nothing else — not the package, not the
36
+ * clock, not folio's own version — so two saves of one document state the same
37
+ * application version.
38
+ */
39
+ declare const appVersionInSchemaForm: (value: string) => string;
40
+ /**
41
+ * Rewrite the application version an extended-properties part states.
42
+ *
43
+ * Returns the part unchanged when the value already fits and when the part
44
+ * states no version at all, so a save of a document that never carried a
45
+ * malformed one is byte-identical.
46
+ */
47
+ declare const normalizeAppVersionInExtendedProperties: (xml: string) => string;
48
+ //#endregion
49
+ export { AppVersionSchemaError, appVersionInSchemaForm, normalizeAppVersionInExtendedProperties };