@stll/folio-core 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/ai-edits/headless.d.ts +5 -1
  2. package/dist/ai-edits/headless.js +53 -3
  3. package/dist/ai-edits/index.d.ts +2 -2
  4. package/dist/compat/eigenpal.d.ts +2 -2
  5. package/dist/controller/layoutPipeline.js +17 -6
  6. package/dist/document-operations.d.ts +20 -3
  7. package/dist/document-operations.js +7 -4
  8. package/dist/docx/blockContentParser.js +2 -100
  9. package/dist/docx/paragraphTextBoxEnrichment.d.ts +9 -0
  10. package/dist/docx/paragraphTextBoxEnrichment.js +104 -0
  11. package/dist/docx/tableParser.js +2 -0
  12. package/dist/i18n/messages/catalogs.gen.d.ts +1054 -34
  13. package/dist/i18n/messages/catalogs.gen.js +1122 -68
  14. package/dist/i18n/messages/messages.gen.d.ts +62 -2
  15. package/dist/index.d.ts +2 -2
  16. package/dist/layout-bridge/convert/toFlowBlocks.js +15 -13
  17. package/dist/layout-bridge/sectionColumns.js +6 -1
  18. package/dist/layout-engine/index.js +63 -11
  19. package/dist/layout-engine/measure/measureBlocks.js +25 -2
  20. package/dist/layout-engine/paginator.d.ts +2 -0
  21. package/dist/layout-engine/paginator.js +17 -13
  22. package/dist/layout-engine/tableRowBreak.js +3 -0
  23. package/dist/layout-engine/types.d.ts +5 -2
  24. package/dist/layout-painter/index.js +1 -1
  25. package/dist/layout-painter/renderPage.js +7 -2
  26. package/dist/layout-painter/renderParagraph.js +5 -4
  27. package/dist/layout-painter/renderTable.js +88 -10
  28. package/dist/managers/TableSelectionManager.js +1 -1
  29. package/dist/paged-layout/sectionBlockWidths.js +11 -3
  30. package/dist/prosemirror/commands/index.js +1 -1
  31. package/dist/prosemirror/conversion/fromProseDoc.js +11 -2
  32. package/dist/prosemirror/conversion/toProseDoc.js +26 -20
  33. package/dist/prosemirror/extensions/nodes/TableExtension.js +2 -2
  34. package/dist/prosemirror/index.js +1 -1
  35. package/dist/prosemirror/insertOperations.js +1 -1
  36. package/dist/server.d.ts +2 -2
  37. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import { FolioAIBlock, FolioAIEditApplyMode, FolioAIEditApplyResult, FolioAIEditOperation, FolioAIEditSnapshot } from "./types.js";
2
2
  import { document_d_exports } from "../types/document.js";
3
- import { FolioDocumentOperationBatch, FolioDocumentOperationResult } from "../document-operations.js";
3
+ import { FolioDocumentOperationBatch, FolioDocumentOperationResult, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult } from "../document-operations.js";
4
4
  import { FolioReviewChange, FolioReviewChangeKind } from "./read.js";
5
5
 
6
6
  //#region src/ai-edits/headless.d.ts
@@ -98,6 +98,7 @@ declare class FolioDocxReviewer {
98
98
  private readonly originalBuffer;
99
99
  private state;
100
100
  private readonly createdComments;
101
+ private readonly documentOperationUndoEntries;
101
102
  /**
102
103
  * Resolved-state overrides recorded by {@link resolveComment}, keyed by
103
104
  * comment id. Applied on read ({@link getComments}) and on write
@@ -128,6 +129,9 @@ declare class FolioDocxReviewer {
128
129
  * edit semantics.
129
130
  */
130
131
  applyDocumentOperations(batch: FolioDocumentOperationBatch, options?: FolioApplyDocumentOperationsOptions): FolioDocumentOperationResult;
132
+ private applyDocumentOperationsInternal;
133
+ /** Undo the latest unchanged document-operation batch and its created comments. */
134
+ undoDocumentOperations(undoHandle: FolioDocumentOperationUndoHandle): FolioDocumentOperationUndoResult;
131
135
  /**
132
136
  * The body blocks with their stable ids, in document order — the same
133
137
  * `FolioAIBlock` shape {@link snapshot} builds, reused verbatim so the ids
@@ -44,6 +44,7 @@ import { EditorState } from "prosemirror-state";
44
44
  * across reviewers created within the same millisecond.
45
45
  */
46
46
  let commentIdCursor = Date.now();
47
+ let undoHandleCursor = Date.now();
47
48
  /**
48
49
  * Build the note-free comment thread the apply layer references by id.
49
50
  * Mirrors `commentsHelpers.createComment` (a pure object literal there) so a
@@ -162,6 +163,7 @@ var FolioDocxReviewer = class FolioDocxReviewer {
162
163
  originalBuffer;
163
164
  state;
164
165
  createdComments = [];
166
+ documentOperationUndoEntries = [];
165
167
  /**
166
168
  * Resolved-state overrides recorded by {@link resolveComment}, keyed by
167
169
  * comment id. Applied on read ({@link getComments}) and on write
@@ -210,11 +212,11 @@ var FolioDocxReviewer = class FolioDocxReviewer {
210
212
  * (including any comments) is retained for {@link toBuffer}.
211
213
  */
212
214
  applyOperations(operations, options = {}) {
213
- const { applied, skipped } = this.applyDocumentOperations({
215
+ const { applied, skipped } = this.applyDocumentOperationsInternal({
214
216
  version: 1,
215
217
  operations,
216
218
  mode: options.mode ?? "tracked-changes"
217
- }, { ...options.snapshot !== void 0 && { snapshot: options.snapshot } });
219
+ }, { ...options.snapshot !== void 0 && { snapshot: options.snapshot } }, false);
218
220
  return {
219
221
  applied,
220
222
  skipped
@@ -227,6 +229,11 @@ var FolioDocxReviewer = class FolioDocxReviewer {
227
229
  * edit semantics.
228
230
  */
229
231
  applyDocumentOperations(batch, options = {}) {
232
+ return this.applyDocumentOperationsInternal(batch, options, true);
233
+ }
234
+ applyDocumentOperationsInternal(batch, options, createUndoEntry) {
235
+ const beforeState = this.state;
236
+ const createdCommentsLengthBefore = this.createdComments.length;
230
237
  const view = {
231
238
  state: this.state,
232
239
  dispatch: (transaction) => {
@@ -242,11 +249,54 @@ var FolioDocxReviewer = class FolioDocxReviewer {
242
249
  const comment = createReviewerComment(text, this.author);
243
250
  this.createdComments.push(comment);
244
251
  return comment.id;
245
- }
252
+ },
253
+ ...createUndoEntry && { createUndoHandle: () => ({
254
+ type: "documentOperationUndo",
255
+ id: `headless-${String(undoHandleCursor++)}`
256
+ }) }
246
257
  });
247
258
  this.state = view.state;
259
+ if (result.undoHandle !== null) this.documentOperationUndoEntries.push({
260
+ undoHandle: result.undoHandle,
261
+ beforeState,
262
+ afterState: this.state,
263
+ createdCommentsLengthBefore,
264
+ createdCommentsLengthAfter: this.createdComments.length
265
+ });
248
266
  return result;
249
267
  }
268
+ /** Undo the latest unchanged document-operation batch and its created comments. */
269
+ undoDocumentOperations(undoHandle) {
270
+ const entryIndex = this.documentOperationUndoEntries.findIndex((entry) => entry.undoHandle.type === undoHandle.type && entry.undoHandle.id === undoHandle.id);
271
+ if (entryIndex === -1) return {
272
+ status: "rejected",
273
+ undoHandle,
274
+ reason: "unknownHandle"
275
+ };
276
+ if (entryIndex !== this.documentOperationUndoEntries.length - 1) return {
277
+ status: "rejected",
278
+ undoHandle,
279
+ reason: "notLatest"
280
+ };
281
+ const entry = this.documentOperationUndoEntries.at(-1);
282
+ if (!entry) return {
283
+ status: "rejected",
284
+ undoHandle,
285
+ reason: "unknownHandle"
286
+ };
287
+ if (this.state !== entry.afterState || this.createdComments.length !== entry.createdCommentsLengthAfter) return {
288
+ status: "rejected",
289
+ undoHandle,
290
+ reason: "documentChanged"
291
+ };
292
+ this.state = entry.beforeState;
293
+ this.createdComments.length = entry.createdCommentsLengthBefore;
294
+ this.documentOperationUndoEntries.pop();
295
+ return {
296
+ status: "undone",
297
+ undoHandle
298
+ };
299
+ }
250
300
  /**
251
301
  * The body blocks with their stable ids, in document order — the same
252
302
  * `FolioAIBlock` shape {@link snapshot} builds, reused verbatim so the ids
@@ -1,10 +1,10 @@
1
1
  import { FolioAIBlock, FolioAIBlockAnchor, FolioAIBlockKind, FolioAIBlockPreviewRun, FolioAIComment, FolioAIEditAppliedOperation, FolioAIEditApplyMode, FolioAIEditApplyResult, FolioAIEditOperation, FolioAIEditPrecondition, FolioAIEditReviewMeta, FolioAIEditSeverity, FolioAIEditSkipReason, FolioAIEditSkippedOperation, FolioAIEditSnapshot, FolioAIInlineFormatting, FolioAISignatureParty, FolioAITextRangeHandle } from "./types.js";
2
2
  import { FolioAIEditView, applyFolioAIEditOperations } from "./apply.js";
3
3
  import { buildAnnotatedBlockText } from "./clean-text.js";
4
- 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, FolioDocumentOperationStatus, FolioDocumentOperationType, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch } from "../document-operations.js";
4
+ 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, FolioDocumentOperationStatus, FolioDocumentOperationType, FolioDocumentOperationUndoFailureReason, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch } from "../document-operations.js";
5
5
  import { FolioCommentAnchor, FolioReviewChange, FolioReviewChangeKind, getCommentAnchorsFromDoc, getTrackedChangesFromDoc } from "./read.js";
6
6
  import { FolioDocumentStory, FolioDocumentStoryHandle } from "./headless.js";
7
7
  import { createFolioAIEditSnapshot, createFolioAITextRangeHandle, hashFolioAIBlockText, normalizeFolioAIBlockText } from "./snapshot.js";
8
8
  import { getFolioParaIdFromBlockId } from "../types/block-id.js";
9
9
  import { WordDiffSegment, diffWordSegments } from "./word-diff.js";
10
- export { type 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, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyResult, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAIEditView, type FolioAIInlineFormatting, type FolioAISignatureParty, type FolioAITextRangeHandle, type FolioCommentAnchor, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationStatus, type FolioDocumentOperationType, type FolioDocumentStory, type FolioDocumentStoryHandle, type FolioReviewChange, type FolioReviewChangeKind, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, type WordDiffSegment, applyFolioAIEditOperations, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, buildAnnotatedBlockText, createFolioAIEditSnapshot, createFolioAITextRangeHandle, diffWordSegments, getCommentAnchorsFromDoc, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getTrackedChangesFromDoc, hashFolioAIBlockText, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch };
10
+ export { type 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, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyResult, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAIEditView, type FolioAIInlineFormatting, type FolioAISignatureParty, type FolioAITextRangeHandle, type FolioCommentAnchor, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationStatus, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocumentStory, type FolioDocumentStoryHandle, type FolioReviewChange, type FolioReviewChangeKind, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, type WordDiffSegment, applyFolioAIEditOperations, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, buildAnnotatedBlockText, createFolioAIEditSnapshot, createFolioAITextRangeHandle, diffWordSegments, getCommentAnchorsFromDoc, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getTrackedChangesFromDoc, hashFolioAIBlockText, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch };
@@ -1,7 +1,7 @@
1
1
  import { FolioAIBlock, FolioAIBlockAnchor, FolioAIBlockKind, FolioAIBlockPreviewRun, FolioAIComment, FolioAIEditAppliedOperation, FolioAIEditApplyMode, FolioAIEditApplyResult, FolioAIEditOperation, FolioAIEditPrecondition, FolioAIEditReviewMeta, FolioAIEditSeverity, FolioAIEditSkipReason, FolioAIEditSkippedOperation, FolioAIEditSnapshot, FolioAISignatureParty } from "../ai-edits/types.js";
2
2
  import { applyFolioAIEditOperations } from "../ai-edits/apply.js";
3
3
  import { document_d_exports } from "../types/document.js";
4
- 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, FolioDocumentOperationStatus, FolioDocumentOperationType, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch } from "../document-operations.js";
4
+ 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, FolioDocumentOperationStatus, FolioDocumentOperationType, FolioDocumentOperationUndoFailureReason, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch } from "../document-operations.js";
5
5
  import { createFolioAIEditSnapshot, hashFolioAIBlockText, normalizeFolioAIBlockText } from "../ai-edits/snapshot.js";
6
6
  import { DeriveBlockIdInput, FolioBlockId, deriveBlockId, getFolioParaIdFromBlockId, isFolioBlockId, isSequentialFolioBlockId } from "../types/block-id.js";
7
7
  import { WordDiffSegment, diffWordSegments } from "../ai-edits/word-diff.js";
@@ -27,4 +27,4 @@ import { toMarkdown, toMarkdownResult } from "../markdown/index.js";
27
27
  import { EmbeddedFont, EmbeddedFontParts, extractEmbeddedFonts, getEmbeddedFontFaces } from "../fonts/embeddedFonts.js";
28
28
  import { getGoogleFontsEnabled, setGoogleFontsEnabled } from "../utils/fontResolver.js";
29
29
  type Document = document_d_exports.Document;
30
- 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 CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocxCompatibility, type EmbeddedFont, type EmbeddedFontParts, 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 FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyResult, 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 FolioDocumentOperationStatus, type FolioDocumentOperationType, type ImageMeta, type ImageRef, InvalidFolioDocumentOperationBatchError, type MarkdownOptions, type MarkdownResult, type PositionalText, type ResolvedAnchor, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, deriveBlockId, diffWordSegments, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
30
+ 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 CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocxCompatibility, type EmbeddedFont, type EmbeddedFontParts, 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 FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyResult, 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 FolioDocumentOperationStatus, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type ImageMeta, type ImageRef, InvalidFolioDocumentOperationBatchError, type MarkdownOptions, type MarkdownResult, type PositionalText, type ResolvedAnchor, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, deriveBlockId, diffWordSegments, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
@@ -1,6 +1,8 @@
1
1
  import "../layout-engine/types.js";
2
2
  import { renderPages } from "../layout-painter/renderPage.js";
3
3
  import { templatePreviewValuesKey } from "../prosemirror/plugins/templatePreviewValues.js";
4
+ import { getMargins, getPageSize, twipsToPixels } from "../paged-layout/sectionGeometry.js";
5
+ import { getColumns } from "../layout-bridge/sectionColumns.js";
4
6
  import { toFlowBlocks } from "../layout-bridge/convert/toFlowBlocks.js";
5
7
  import { recordLayoutComplete, recordLayoutError, recordLayoutPhase, recordLayoutStart } from "../layout-engine/layoutInstrumentation.js";
6
8
  import { buildBookmarkPageMap } from "../fields/bookmarkPages.js";
@@ -15,7 +17,6 @@ import { layoutDocument } from "../layout-engine/index.js";
15
17
  import { measureBlocks, measureSingleBlockWithoutFloatingZones } from "../layout-engine/measure/measureBlocks.js";
16
18
  import { tryBuildIncrementalMeasures } from "../paged-layout/incrementalMeasure.js";
17
19
  import { computePerBlockMeasureInputs } from "../paged-layout/sectionBlockWidths.js";
18
- import { getMargins, getPageSize, twipsToPixels } from "../paged-layout/sectionGeometry.js";
19
20
  import { getDocumentWatermark } from "../watermark/index.js";
20
21
  //#region src/controller/layoutPipeline.ts
21
22
  function runLayoutPipeline(deps, state, options = {}) {
@@ -98,10 +99,17 @@ function runLayoutPipeline(deps, state, options = {}) {
98
99
  margins
99
100
  };
100
101
  if (columns !== void 0) bodyLayoutConfig.columns = columns;
102
+ const finalSectionProperties = document?.package.document.sections?.at(-1)?.properties;
103
+ const finalLayoutConfig = finalSectionProperties ? {
104
+ pageSize: getPageSize(finalSectionProperties),
105
+ margins: getMargins(finalSectionProperties)
106
+ } : bodyLayoutConfig;
107
+ const finalColumns = getColumns(finalSectionProperties);
108
+ if (finalColumns !== void 0) finalLayoutConfig.columns = finalColumns;
101
109
  const blockMeasureInputs = computePerBlockMeasureInputs({
102
110
  blocks: newBlocks,
103
111
  bodyConfig: bodyLayoutConfig,
104
- finalConfig: bodyLayoutConfig
112
+ finalConfig: finalLayoutConfig
105
113
  });
106
114
  const blockWidths = blockMeasureInputs.widths;
107
115
  const previousArtifacts = session.artifacts;
@@ -144,10 +152,13 @@ function runLayoutPipeline(deps, state, options = {}) {
144
152
  top: headerBottom
145
153
  };
146
154
  }
147
- const finalSection = document?.package.document.sections?.at(-1);
148
- if (finalSection) {
149
- nextLayoutOpts.finalPageSize = getPageSize(finalSection.properties);
150
- nextLayoutOpts.finalMargins = getMargins(finalSection.properties);
155
+ if (finalSectionProperties) {
156
+ nextLayoutOpts.finalPageSize = finalLayoutConfig.pageSize;
157
+ nextLayoutOpts.finalMargins = finalLayoutConfig.margins;
158
+ nextLayoutOpts.finalColumns = finalLayoutConfig.columns ?? {
159
+ count: 1,
160
+ gap: 0
161
+ };
151
162
  }
152
163
  if (columns !== void 0) nextLayoutOpts.columns = columns;
153
164
  if (bodyBreakType !== void 0) nextLayoutOpts.bodyBreakType = bodyBreakType;
@@ -93,13 +93,28 @@ type FolioDocumentOperationReceipt = {
93
93
  operationIndex: number;
94
94
  affected: FolioDocumentOperationAffectedTarget[];
95
95
  };
96
+ /** Opaque handle for undoing one committed document-operation batch. */
97
+ type FolioDocumentOperationUndoHandle = {
98
+ type: "documentOperationUndo";
99
+ id: string;
100
+ };
101
+ type FolioDocumentOperationUndoFailureReason = "unknownHandle" | "notLatest" | "documentChanged";
102
+ type FolioDocumentOperationUndoResult = {
103
+ status: "undone";
104
+ undoHandle: FolioDocumentOperationUndoHandle;
105
+ } | {
106
+ status: "rejected";
107
+ undoHandle: FolioDocumentOperationUndoHandle;
108
+ reason: FolioDocumentOperationUndoFailureReason;
109
+ };
96
110
  type FolioDocumentOperationResult = {
97
111
  version: typeof FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION;
98
112
  status: FolioDocumentOperationStatus;
99
113
  applied: FolioAIEditAppliedOperation[];
100
114
  skipped: FolioAIEditSkippedOperation[];
101
115
  issues: FolioDocumentOperationIssue[]; /** Successful effects in input-operation order; skipped operations are omitted. */
102
- receipts: FolioDocumentOperationReceipt[];
116
+ receipts: FolioDocumentOperationReceipt[]; /** Present when the execution surface can undo this committed batch. */
117
+ undoHandle: FolioDocumentOperationUndoHandle | null;
103
118
  };
104
119
  declare const getFolioDocumentOperationIssues: (operations: readonly FolioDocumentOperation[], skipped: readonly FolioAIEditSkippedOperation[]) => FolioDocumentOperationIssue[];
105
120
  /** Build deterministic affected-target receipts from operations and their applied entries. */
@@ -110,13 +125,15 @@ type ApplyFolioDocumentOperationsOptions = {
110
125
  batch: FolioDocumentOperationBatch;
111
126
  author?: string;
112
127
  createCommentId?: (text: string) => number;
128
+ createUndoHandle?: () => FolioDocumentOperationUndoHandle;
113
129
  };
114
130
  declare const applyFolioDocumentOperations: ({
115
131
  view,
116
132
  snapshot,
117
133
  batch,
118
134
  author,
119
- createCommentId
135
+ createCommentId,
136
+ createUndoHandle
120
137
  }: ApplyFolioDocumentOperationsOptions) => FolioDocumentOperationResult;
121
138
  //#endregion
122
- export { 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, FolioDocumentOperationStatus, FolioDocumentOperationType, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch };
139
+ export { 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, FolioDocumentOperationStatus, FolioDocumentOperationType, FolioDocumentOperationUndoFailureReason, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch };
@@ -515,7 +515,7 @@ const getFolioDocumentOperationReceipts = (operations, applied) => {
515
515
  });
516
516
  return receipts;
517
517
  };
518
- const applyFolioDocumentOperations = ({ view, snapshot, batch, author, createCommentId }) => {
518
+ const applyFolioDocumentOperations = ({ view, snapshot, batch, author, createCommentId, createUndoHandle }) => {
519
519
  const parsedBatch = parseFolioDocumentOperationBatch(batch);
520
520
  const apply = ({ targetView, targetCreateCommentId = createCommentId, preview = false }) => {
521
521
  return (preview ? previewFolioAIEditOperations : applyFolioAIEditOperations)({
@@ -543,7 +543,8 @@ const applyFolioDocumentOperations = ({ view, snapshot, batch, author, createCom
543
543
  applied: [],
544
544
  skipped,
545
545
  issues: getFolioDocumentOperationIssues(parsedBatch.operations, skipped),
546
- receipts: []
546
+ receipts: [],
547
+ undoHandle: null
547
548
  };
548
549
  };
549
550
  if (parsedBatch.dryRun === true) {
@@ -555,7 +556,8 @@ const applyFolioDocumentOperations = ({ view, snapshot, batch, author, createCom
555
556
  applied: previewResult.applied.map(({ id }) => ({ id })),
556
557
  skipped: previewResult.skipped,
557
558
  issues: getFolioDocumentOperationIssues(parsedBatch.operations, previewResult.skipped),
558
- receipts: getFolioDocumentOperationReceipts(parsedBatch.operations, previewResult.applied)
559
+ receipts: getFolioDocumentOperationReceipts(parsedBatch.operations, previewResult.applied),
560
+ undoHandle: null
559
561
  };
560
562
  }
561
563
  if (parsedBatch.atomic === true) {
@@ -568,7 +570,8 @@ const applyFolioDocumentOperations = ({ view, snapshot, batch, author, createCom
568
570
  status: "committed",
569
571
  ...result,
570
572
  issues: getFolioDocumentOperationIssues(parsedBatch.operations, result.skipped),
571
- receipts: getFolioDocumentOperationReceipts(parsedBatch.operations, result.applied)
573
+ receipts: getFolioDocumentOperationReceipts(parsedBatch.operations, result.applied),
574
+ undoHandle: result.applied.length > 0 && createUndoHandle !== void 0 ? createUndoHandle() : null
572
575
  };
573
576
  };
574
577
  //#endregion
@@ -1,9 +1,9 @@
1
- import { elementToXml, findChild, findDeep, getChildElements, getLocalName, mergeXmlnsDeclarations } from "./xmlParser.js";
1
+ import { elementToXml, findChild, getChildElements, getLocalName, mergeXmlnsDeclarations } from "./xmlParser.js";
2
2
  import { parseBookmarkEnd, parseBookmarkStart } from "./bookmarkParser.js";
3
- import { getTextBoxContentElement, isTextBoxDrawing, parseTextBox, parseTextBoxContent } from "./textBoxParser.js";
4
3
  import { parseSdtProperties } from "./sdtProperties.js";
5
4
  import { parseParagraph } from "./paragraphParser.js";
6
5
  import { appendBookmarkMarkerToLastParagraphInBlocks, prependBookmarkMarkersToFirstParagraphInBlocks } from "./bookmarkPlacement.js";
6
+ import { enrichParagraphTextBoxes } from "./paragraphTextBoxEnrichment.js";
7
7
  import { parseTable } from "./tableParser.js";
8
8
  import { padDecimal } from "./numberingParser.js";
9
9
  import { convertBulletToUnicode } from "./bulletMarkers.js";
@@ -100,104 +100,6 @@ const computeListMarker = (paragraph, numbering, listCounters, abstractCounters)
100
100
  }
101
101
  listRendering.marker = computedMarker;
102
102
  };
103
- const enrichParagraphTextBoxes = (paragraph, paraXml, styles, theme, numbering, rels, media) => {
104
- const xmlChildren = getChildElements(paraXml);
105
- let parsedIndex = 0;
106
- let lastConsumedRun;
107
- for (const xmlChild of xmlChildren) {
108
- if (getLocalName(xmlChild.name ?? "") !== "r") {
109
- if (parsedIndex < paragraph.content.length && paragraph.content[parsedIndex]?.type !== "run") parsedIndex += 1;
110
- continue;
111
- }
112
- const { textBoxDrawings, hasNonTextBoxContent } = scanRunForTextBoxDrawings(xmlChild);
113
- const parsedContent = paragraph.content[parsedIndex];
114
- const parsedRun = parsedContent?.type === "run" ? parsedContent : void 0;
115
- const targetRun = parsedRun ?? (hasNonTextBoxContent ? lastConsumedRun : void 0);
116
- for (const runEl of textBoxDrawings) {
117
- const textBox = parseTextBox(runEl);
118
- if (!textBox) continue;
119
- const wsp = findDeep(runEl, "wps", "wsp");
120
- if (wsp) {
121
- const txbxContentEl = getTextBoxContentElement(wsp);
122
- if (txbxContentEl) textBox.content = parseTextBoxContent(txbxContentEl, parseParagraph, null, styles, theme, numbering, rels ?? void 0, media ?? void 0);
123
- }
124
- const shape = {
125
- type: "shape",
126
- shapeType: "textBox",
127
- size: textBox.size,
128
- ...textBox.position !== void 0 ? { position: textBox.position } : {},
129
- ...textBox.wrap !== void 0 ? { wrap: textBox.wrap } : {},
130
- ...textBox.fill !== void 0 ? { fill: textBox.fill } : {},
131
- ...textBox.outline !== void 0 ? { outline: textBox.outline } : {},
132
- textBody: {
133
- content: textBox.content,
134
- ...textBox.margins !== void 0 ? { margins: textBox.margins } : {}
135
- }
136
- };
137
- if (textBox.id) shape.id = textBox.id;
138
- const shapeContent = {
139
- type: "shape",
140
- shape
141
- };
142
- if (targetRun && hasNonTextBoxContent) targetRun.content.push(shapeContent);
143
- else {
144
- const newRun = {
145
- type: "run",
146
- content: [shapeContent]
147
- };
148
- paragraph.content.splice(parsedIndex, 0, newRun);
149
- lastConsumedRun = newRun;
150
- parsedIndex += 1;
151
- }
152
- }
153
- if (hasNonTextBoxContent && parsedRun) {
154
- lastConsumedRun = parsedRun;
155
- parsedIndex += 1;
156
- }
157
- }
158
- };
159
- const scanRunForTextBoxDrawings = (xmlRun) => {
160
- const textBoxDrawings = [];
161
- let hasNonTextBoxContent = false;
162
- const visitDrawing = (drawingEl) => {
163
- if (isTextBoxDrawing(drawingEl)) {
164
- textBoxDrawings.push(drawingEl);
165
- return;
166
- }
167
- hasNonTextBoxContent = true;
168
- };
169
- for (const el of getChildElements(xmlRun)) {
170
- const name = getLocalName(el.name ?? "");
171
- if (name === "rPr") continue;
172
- if (name === "drawing") {
173
- visitDrawing(el);
174
- continue;
175
- }
176
- if (name === "AlternateContent") {
177
- const branches = getChildElements(el);
178
- const choice = branches.find((branch) => getLocalName(branch.name ?? "") === "Choice");
179
- const fallback = branches.find((branch) => getLocalName(branch.name ?? "") === "Fallback");
180
- const tryBranch = (branch) => {
181
- if (!branch) return false;
182
- let found = false;
183
- for (const innerEl of getChildElements(branch)) if (getLocalName(innerEl.name ?? "") === "drawing") {
184
- visitDrawing(innerEl);
185
- found = true;
186
- }
187
- return found;
188
- };
189
- let foundInBranch = tryBranch(choice);
190
- if (!foundInBranch) foundInBranch = tryBranch(fallback);
191
- if (!foundInBranch) hasNonTextBoxContent = true;
192
- continue;
193
- }
194
- hasNonTextBoxContent = true;
195
- }
196
- return {
197
- textBoxDrawings,
198
- hasNonTextBoxContent
199
- };
200
- };
201
103
  const parseBlockContent = (parent, styles, theme, numbering, rels, media, options) => parseBlockContentWithState(parent, styles, theme, numbering, rels, media, {
202
104
  listCounters: /* @__PURE__ */ new Map(),
203
105
  abstractCounters: /* @__PURE__ */ new Map(),
@@ -0,0 +1,9 @@
1
+ import { document_d_exports } from "../types/document.js";
2
+ import { NumberingMap } from "./numberingParser.js";
3
+ import { StyleMap } from "./styleParser.js";
4
+ import { XmlElement } from "./xmlParser.js";
5
+
6
+ //#region src/docx/paragraphTextBoxEnrichment.d.ts
7
+ declare const enrichParagraphTextBoxes: (paragraph: document_d_exports.Paragraph, paraXml: XmlElement, styles: StyleMap | null, theme: document_d_exports.Theme | null, numbering: NumberingMap | null, rels: document_d_exports.RelationshipMap | null, media: Map<string, document_d_exports.MediaFile> | null) => void;
8
+ //#endregion
9
+ export { enrichParagraphTextBoxes };
@@ -0,0 +1,104 @@
1
+ import { findDeep, getChildElements, getLocalName } from "./xmlParser.js";
2
+ import { getTextBoxContentElement, isTextBoxDrawing, parseTextBox, parseTextBoxContent } from "./textBoxParser.js";
3
+ import { parseParagraph } from "./paragraphParser.js";
4
+ //#region src/docx/paragraphTextBoxEnrichment.ts
5
+ const enrichParagraphTextBoxes = (paragraph, paraXml, styles, theme, numbering, rels, media) => {
6
+ const xmlChildren = getChildElements(paraXml);
7
+ let parsedIndex = 0;
8
+ let lastConsumedRun;
9
+ for (const xmlChild of xmlChildren) {
10
+ if (getLocalName(xmlChild.name ?? "") !== "r") {
11
+ if (parsedIndex < paragraph.content.length && paragraph.content[parsedIndex]?.type !== "run") parsedIndex += 1;
12
+ continue;
13
+ }
14
+ const { textBoxDrawings, hasNonTextBoxContent } = scanRunForTextBoxDrawings(xmlChild);
15
+ const parsedContent = paragraph.content[parsedIndex];
16
+ const parsedRun = parsedContent?.type === "run" ? parsedContent : void 0;
17
+ const targetRun = parsedRun ?? (hasNonTextBoxContent ? lastConsumedRun : void 0);
18
+ for (const runEl of textBoxDrawings) {
19
+ const textBox = parseTextBox(runEl);
20
+ if (!textBox) continue;
21
+ const wsp = findDeep(runEl, "wps", "wsp");
22
+ if (wsp) {
23
+ const txbxContentEl = getTextBoxContentElement(wsp);
24
+ if (txbxContentEl) textBox.content = parseTextBoxContent(txbxContentEl, parseParagraph, null, styles, theme, numbering, rels ?? void 0, media ?? void 0);
25
+ }
26
+ const shape = {
27
+ type: "shape",
28
+ shapeType: "textBox",
29
+ size: textBox.size,
30
+ ...textBox.position !== void 0 ? { position: textBox.position } : {},
31
+ ...textBox.wrap !== void 0 ? { wrap: textBox.wrap } : {},
32
+ ...textBox.fill !== void 0 ? { fill: textBox.fill } : {},
33
+ ...textBox.outline !== void 0 ? { outline: textBox.outline } : {},
34
+ textBody: {
35
+ content: textBox.content,
36
+ ...textBox.margins !== void 0 ? { margins: textBox.margins } : {}
37
+ }
38
+ };
39
+ if (textBox.id) shape.id = textBox.id;
40
+ const shapeContent = {
41
+ type: "shape",
42
+ shape
43
+ };
44
+ if (targetRun && hasNonTextBoxContent) targetRun.content.push(shapeContent);
45
+ else {
46
+ const newRun = {
47
+ type: "run",
48
+ content: [shapeContent]
49
+ };
50
+ paragraph.content.splice(parsedIndex, 0, newRun);
51
+ lastConsumedRun = newRun;
52
+ parsedIndex += 1;
53
+ }
54
+ }
55
+ if (hasNonTextBoxContent && parsedRun) {
56
+ lastConsumedRun = parsedRun;
57
+ parsedIndex += 1;
58
+ }
59
+ }
60
+ };
61
+ const scanRunForTextBoxDrawings = (xmlRun) => {
62
+ const textBoxDrawings = [];
63
+ let hasNonTextBoxContent = false;
64
+ const visitDrawing = (drawingEl) => {
65
+ if (isTextBoxDrawing(drawingEl)) {
66
+ textBoxDrawings.push(drawingEl);
67
+ return;
68
+ }
69
+ hasNonTextBoxContent = true;
70
+ };
71
+ for (const el of getChildElements(xmlRun)) {
72
+ const name = getLocalName(el.name ?? "");
73
+ if (name === "rPr") continue;
74
+ if (name === "drawing") {
75
+ visitDrawing(el);
76
+ continue;
77
+ }
78
+ if (name === "AlternateContent") {
79
+ const branches = getChildElements(el);
80
+ const choice = branches.find((branch) => getLocalName(branch.name ?? "") === "Choice");
81
+ const fallback = branches.find((branch) => getLocalName(branch.name ?? "") === "Fallback");
82
+ const tryBranch = (branch) => {
83
+ if (!branch) return false;
84
+ let found = false;
85
+ for (const innerEl of getChildElements(branch)) if (getLocalName(innerEl.name ?? "") === "drawing") {
86
+ visitDrawing(innerEl);
87
+ found = true;
88
+ }
89
+ return found;
90
+ };
91
+ let foundInBranch = tryBranch(choice);
92
+ if (!foundInBranch) foundInBranch = tryBranch(fallback);
93
+ if (!foundInBranch) hasNonTextBoxContent = true;
94
+ continue;
95
+ }
96
+ hasNonTextBoxContent = true;
97
+ }
98
+ return {
99
+ textBoxDrawings,
100
+ hasNonTextBoxContent
101
+ };
102
+ };
103
+ //#endregion
104
+ export { enrichParagraphTextBoxes };
@@ -3,6 +3,7 @@ import { parseBookmarkEnd, parseBookmarkStart } from "./bookmarkParser.js";
3
3
  import { BorderStyleSchema, FloatingTableXSpecSchema, FloatingTableYSpecSchema, ShadingPatternSchema, TableCellTextDirectionSchema, ThemeColorSlotSchema, narrowEnum } from "./parserEnums.js";
4
4
  import { parseParagraph } from "./paragraphParser.js";
5
5
  import { appendBookmarkMarkerToLastParagraphInBlocks, appendBookmarkMarkerToLastParagraphInCells, prependBookmarkMarkersToFirstParagraphInBlocks, prependBookmarkMarkersToFirstParagraphInCell } from "./bookmarkPlacement.js";
6
+ import { enrichParagraphTextBoxes } from "./paragraphTextBoxEnrichment.js";
6
7
  //#region src/docx/tableParser.ts
7
8
  /**
8
9
  * Parse a table measurement (width, height, etc.)
@@ -489,6 +490,7 @@ function parseCellContent(tcElement, styles, theme, numbering, rels, media, opti
489
490
  const localName = getLocalName(child.name);
490
491
  if (localName === "p") {
491
492
  const para = parseParagraph(child, styles, theme, numbering, rels, media, options);
493
+ enrichParagraphTextBoxes(para, child, styles, theme, numbering, rels, media);
492
494
  prependPendingBookmarkMarkers(para, pendingBookmarkMarkers);
493
495
  content.push(para);
494
496
  } else if (localName === "tbl") {