@stll/folio-core 0.39.1 → 0.40.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.
@@ -1090,6 +1090,7 @@ const buildInsertedParagraphs = ({ item, schema, formattingFromStyle, mode, auth
1090
1090
  suggestionId
1091
1091
  } : {}
1092
1092
  };
1093
+ const formatsEveryParagraph = operation.formattingScope === "allParagraphs";
1093
1094
  const baseAttrs = operation.inheritFormatting === false ? {} : {
1094
1095
  ...stripBlockIdentityAttrs(item.blockNode.attrs),
1095
1096
  _propertyChanges: null,
@@ -1102,6 +1103,7 @@ const buildInsertedParagraphs = ({ item, schema, formattingFromStyle, mode, auth
1102
1103
  let nextRevisionId = revisionSeed;
1103
1104
  for (const [paragraphIndex, text] of insertTexts.entries()) {
1104
1105
  const isFirstParagraph = paragraphIndex === 0;
1106
+ const formatsParagraph = isFirstParagraph || formatsEveryParagraph;
1105
1107
  const marks = [];
1106
1108
  let paragraphRevisionId = null;
1107
1109
  if (producesTrackedChanges && insertionType) {
@@ -1127,11 +1129,11 @@ const buildInsertedParagraphs = ({ item, schema, formattingFromStyle, mode, auth
1127
1129
  text,
1128
1130
  marks
1129
1131
  }) : buildEmphasisInlineContent(schema, text, marks);
1130
- const attrs = isFirstParagraph ? { ...baseAttrs } : {};
1132
+ const attrs = formatsParagraph ? { ...baseAttrs } : {};
1131
1133
  if (isFirstParagraph && operation.pageBreakBefore === true) attrs["pageBreakBefore"] = true;
1132
1134
  const explicitNumbering = operation.numbering;
1133
1135
  const listLevel = operation.listLevel;
1134
- if (isFirstParagraph) {
1136
+ if (formatsParagraph) {
1135
1137
  if (explicitNumbering === null) {
1136
1138
  attrs["numPr"] = null;
1137
1139
  Object.assign(attrs, CLEARED_LIST_RENDERING_ATTRS);
@@ -1160,11 +1162,11 @@ const buildInsertedParagraphs = ({ item, schema, formattingFromStyle, mode, auth
1160
1162
  }
1161
1163
  }
1162
1164
  }
1163
- if (isFirstParagraph && operation.styleId !== void 0) {
1165
+ if (formatsParagraph && operation.styleId !== void 0) {
1164
1166
  attrs["styleId"] = operation.styleId;
1165
1167
  if (operation.inheritFormatting !== false && operation.styleId !== null) Object.assign(attrs, CLEARED_LIST_RENDERING_ATTRS);
1166
1168
  }
1167
- if (isFirstParagraph && (operation.styleId !== void 0 || operation.alignment !== void 0 || operation.spacing !== void 0 || operation.indentation !== void 0)) {
1169
+ if (formatsParagraph && (operation.styleId !== void 0 || operation.alignment !== void 0 || operation.spacing !== void 0 || operation.indentation !== void 0)) {
1168
1170
  const inheritedDirectAlignment = operation.inheritFormatting === false ? void 0 : directParagraphAlignment(expectParagraphAttrs(item.blockNode));
1169
1171
  const inheritedDirectSpacing = operation.inheritFormatting === false ? void 0 : directParagraphSpacing(expectParagraphAttrs(item.blockNode));
1170
1172
  const inheritedDirectIndentation = operation.inheritFormatting === false ? void 0 : directParagraphIndentation(expectParagraphAttrs(item.blockNode));
@@ -1,5 +1,5 @@
1
1
  import { FolioContentParagraphKind } from "../compare/content-types.js";
2
- import { FolioAIBlock, FolioAIBlockAnchor, FolioAIBlockKind, FolioAIBlockPreviewRun, FolioAIBlockStructuralBoundary, FolioAIBlockTableLocation, FolioAIComment, FolioAIEditAppliedOperation, FolioAIEditApplyMode, FolioAIEditApplyResult, FolioAIEditNormalization, FolioAIEditNormalizationCode, FolioAIEditOperation, FolioAIEditPrecondition, FolioAIEditReviewMeta, FolioAIEditSeverity, FolioAIEditSkipReason, FolioAIEditSkippedOperation, FolioAIEditSnapshot, FolioAIInlineBooleanProperty, FolioAIInlineFormatting, FolioAIInlineFormattingPatch, FolioAIParagraphSpacing, FolioAISignatureParty, FolioAITextRangeHandle, FolioDocumentNavigationTarget, FolioDocumentOutline, FolioDocumentOutlineEntry, FolioDocumentSection, FolioDocumentSectionHandle, FolioDocumentSectionReadResult } from "./types.js";
2
+ import { FolioAIBlock, FolioAIBlockAnchor, FolioAIBlockKind, FolioAIBlockPreviewRun, FolioAIBlockStructuralBoundary, FolioAIBlockTableLocation, FolioAIComment, FolioAIEditAppliedOperation, FolioAIEditApplyMode, FolioAIEditApplyResult, FolioAIEditNormalization, FolioAIEditNormalizationCode, FolioAIEditOperation, FolioAIEditPrecondition, FolioAIEditReviewMeta, FolioAIEditSeverity, FolioAIEditSkipReason, FolioAIEditSkippedOperation, FolioAIEditSnapshot, FolioAIInlineBooleanProperty, FolioAIInlineFormatting, FolioAIInlineFormattingPatch, FolioAIInsertFormattingScope, FolioAIParagraphSpacing, FolioAISignatureParty, FolioAITextRangeHandle, FolioDocumentNavigationTarget, FolioDocumentOutline, FolioDocumentOutlineEntry, FolioDocumentSection, FolioDocumentSectionHandle, FolioDocumentSectionReadResult } from "./types.js";
3
3
  import { WORD_DIFF_GRANULARITIES, WordDiffGranularity, WordDiffNormalization, WordDiffOptions, WordDiffSegment, diffWordSegments } from "./word-diff.js";
4
4
  import { FolioAIEditApplyOutcome, FolioAIEditView, FolioRevisionStamp, FolioWordDiffOptions, applyFolioAIEditOperations } from "./apply.js";
5
5
  import { DocPositionRange, clampRangeToDocSize, resolveFolioAIBlockRange, resolveFolioAITextRange, resolvePassageRange } from "./blockRange.js";
@@ -10,4 +10,4 @@ import { createFolioAIEditSnapshot, createFolioAITextRangeHandle, hashFolioAIBlo
10
10
  import { FOLIO_RESOLVED_REVIEWED_VIEWS, FOLIO_REVIEWED_VIEWS, FolioApplyDocumentOperationsToStoryOptions, FolioDocumentStory, FolioDocumentStoryHandle, FolioDocumentStoryNotFoundError, FolioEditableDocumentStoryHandle, FolioReadReviewedStoryOptions, FolioResolveReviewedStoryOptions, FolioResolvedReviewedView, FolioReviewedStory, FolioReviewedView, UnsupportedFolioReviewedViewError, isFolioResolvedReviewedView, isFolioReviewedView } from "./headless.js";
11
11
  import { getFolioDocumentOutline, readFolioDocumentSection } from "./scoped-reading.js";
12
12
  import { getFolioParaIdFromBlockId } from "../types/block-id.js";
13
- export { type ApplyFolioDocumentOperationsOptions, type DocPositionRange, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, FOLIO_RESOLVED_REVIEWED_VIEWS, FOLIO_REVIEWED_VIEWS, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIBlockStructuralBoundary, 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 FolioAIEditView, type FolioAIInlineBooleanProperty, type FolioAIInlineFormatting, type FolioAIInlineFormattingPatch, type FolioAIParagraphSpacing, type FolioAISignatureParty, type FolioAITextRangeHandle, type FolioApplyDocumentOperationsToStoryOptions, type FolioCommentAnchor, type FolioContentParagraphKind, type FolioDocumentNavigationTarget, 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 FolioDocumentOutline, type FolioDocumentOutlineEntry, type FolioDocumentSection, type FolioDocumentSectionHandle, type FolioDocumentSectionReadResult, type FolioDocumentStory, type FolioDocumentStoryHandle, FolioDocumentStoryNotFoundError, type FolioEditableDocumentStoryHandle, type FolioReadReviewedStoryOptions, type FolioResolveReviewedStoryOptions, type FolioResolvedReviewedView, type FolioReviewChange, type FolioReviewChangeKind, type FolioReviewedStory, type FolioReviewedView, type FolioRevisionStamp, type FolioWordDiffOptions, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, UnsupportedFolioReviewedViewError, WORD_DIFF_GRANULARITIES, type WordDiffGranularity, type WordDiffNormalization, type WordDiffOptions, type WordDiffSegment, applyFolioAIEditOperations, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, buildAnnotatedBlockText, clampRangeToDocSize, createFolioAIEditSnapshot, createFolioAITextRangeHandle, diffWordSegments, getCommentAnchorsFromDoc, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioDocumentOutline, getFolioParaIdFromBlockId, getTrackedChangesFromDoc, hashFolioAIBlockText, isFolioAIContentBlock, isFolioDocumentOperationModeSupported, isFolioResolvedReviewedView, isFolioReviewedView, isSupportedFolioDocumentOperationVersion, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, readFolioDocumentSection, resolveFolioAIBlockRange, resolveFolioAITextRange, resolvePassageRange };
13
+ export { type ApplyFolioDocumentOperationsOptions, type DocPositionRange, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, FOLIO_RESOLVED_REVIEWED_VIEWS, FOLIO_REVIEWED_VIEWS, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIBlockStructuralBoundary, 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 FolioAIEditView, type FolioAIInlineBooleanProperty, type FolioAIInlineFormatting, type FolioAIInlineFormattingPatch, type FolioAIInsertFormattingScope, type FolioAIParagraphSpacing, type FolioAISignatureParty, type FolioAITextRangeHandle, type FolioApplyDocumentOperationsToStoryOptions, type FolioCommentAnchor, type FolioContentParagraphKind, type FolioDocumentNavigationTarget, 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 FolioDocumentOutline, type FolioDocumentOutlineEntry, type FolioDocumentSection, type FolioDocumentSectionHandle, type FolioDocumentSectionReadResult, type FolioDocumentStory, type FolioDocumentStoryHandle, FolioDocumentStoryNotFoundError, type FolioEditableDocumentStoryHandle, type FolioReadReviewedStoryOptions, type FolioResolveReviewedStoryOptions, type FolioResolvedReviewedView, type FolioReviewChange, type FolioReviewChangeKind, type FolioReviewedStory, type FolioReviewedView, type FolioRevisionStamp, type FolioWordDiffOptions, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, UnsupportedFolioReviewedViewError, WORD_DIFF_GRANULARITIES, type WordDiffGranularity, type WordDiffNormalization, type WordDiffOptions, type WordDiffSegment, applyFolioAIEditOperations, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, buildAnnotatedBlockText, clampRangeToDocSize, createFolioAIEditSnapshot, createFolioAITextRangeHandle, diffWordSegments, getCommentAnchorsFromDoc, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioDocumentOutline, getFolioParaIdFromBlockId, getTrackedChangesFromDoc, hashFolioAIBlockText, isFolioAIContentBlock, isFolioDocumentOperationModeSupported, isFolioResolvedReviewedView, isFolioReviewedView, isSupportedFolioDocumentOperationVersion, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, readFolioDocumentSection, resolveFolioAIBlockRange, resolveFolioAITextRange, resolvePassageRange };
@@ -43,6 +43,8 @@ type FolioAIParagraphSpacing = FolioContentParagraphSpacing;
43
43
  /** The complete modeled attribute set of one direct `w:pPr/w:ind` child. */
44
44
  type FolioAIParagraphIndentation = FolioContentParagraphIndentation;
45
45
  type FolioAIListReference = FolioContentListReference;
46
+ /** Which paragraphs split from one insertion's `text` receive its paragraph formatting. */
47
+ type FolioAIInsertFormattingScope = "firstParagraph" | "allParagraphs";
46
48
  /**
47
49
  * The paragraph properties an operation may set. A subset of `w:pPrChange`'s
48
50
  * scope: properties a comparison can see in a block projection and an agent
@@ -212,11 +214,11 @@ type FolioAIEditOperation = FolioAIEditReviewMeta & {
212
214
  /**
213
215
  * The paragraph text to insert. With the default `lineBreakMode:
214
216
  * "paragraph"`, a line break splits `text` into consecutive
215
- * paragraphs at the same anchor: only the first paragraph gets
216
- * `styleId` / `alignment` / `inheritFormatting`, later ones use
217
- * body formatting. Blank lines are dropped and reported as a
218
- * `splitMultilineText` normalization. `"inline"` retains the
219
- * control inside one paragraph.
217
+ * paragraphs at the same anchor. `formattingScope` decides which of
218
+ * them receive this operation's paragraph formatting: by default only
219
+ * the first, later ones use body formatting. Blank lines are dropped
220
+ * and reported as a `splitMultilineText` normalization. `"inline"`
221
+ * retains the control inside one paragraph.
220
222
  *
221
223
  * `""` inserts a BLANK paragraph, and is a real edit: adding an empty
222
224
  * line is a change a reader sees, and a document that has one where
@@ -229,6 +231,17 @@ type FolioAIEditOperation = FolioAIEditReviewMeta & {
229
231
  * `"inline"` retains tabs and hard breaks inside this inserted block.
230
232
  */
231
233
  lineBreakMode?: "paragraph" | "inline";
234
+ /**
235
+ * Which paragraphs split from `text` receive the operation's
236
+ * paragraph formatting: the inherited anchor formatting plus
237
+ * `styleId`, `listLevel`, `numbering`, `alignment`, `spacing` and
238
+ * `indentation`. `"firstParagraph"` (the default) formats the first
239
+ * and leaves the rest as body paragraphs, for a heading followed by
240
+ * its body. `"allParagraphs"` formats every paragraph alike, for
241
+ * several list items in one operation. `pageBreakBefore` and
242
+ * `hardPageBreak` apply to the first paragraph in either scope.
243
+ */
244
+ formattingScope?: FolioAIInsertFormattingScope;
232
245
  inheritFormatting?: boolean;
233
246
  /**
234
247
  * Links this insertion to the deletion that carries the same
@@ -596,4 +609,4 @@ type FolioAIEditApplyResult = {
596
609
  normalizations?: FolioAIEditNormalization[];
597
610
  };
598
611
  //#endregion
599
- export { FolioAIBlock, FolioAIBlockAnchor, FolioAIBlockKind, FolioAIBlockParagraphProperties, FolioAIBlockPreviewRun, FolioAIBlockStructuralBoundary, FolioAIBlockTableLocation, FolioAIComment, FolioAIEditAppliedOperation, FolioAIEditApplyMode, FolioAIEditApplyResult, FolioAIEditNormalization, FolioAIEditNormalizationCode, FolioAIEditOperation, FolioAIEditPrecondition, FolioAIEditReviewMeta, FolioAIEditSeverity, FolioAIEditSkipReason, FolioAIEditSkippedOperation, FolioAIEditSnapshot, FolioAIInlineBooleanProperty, FolioAIInlineFormatting, FolioAIInlineFormattingPatch, FolioAIListReference, FolioAIParagraphIndentation, FolioAIParagraphSpacing, FolioAISignatureParty, FolioAITextRangeHandle, FolioDocumentNavigationTarget, FolioDocumentOutline, FolioDocumentOutlineEntry, FolioDocumentSection, FolioDocumentSectionHandle, FolioDocumentSectionReadResult };
612
+ export { FolioAIBlock, FolioAIBlockAnchor, FolioAIBlockKind, FolioAIBlockParagraphProperties, FolioAIBlockPreviewRun, FolioAIBlockStructuralBoundary, FolioAIBlockTableLocation, FolioAIComment, FolioAIEditAppliedOperation, FolioAIEditApplyMode, FolioAIEditApplyResult, FolioAIEditNormalization, FolioAIEditNormalizationCode, FolioAIEditOperation, FolioAIEditPrecondition, FolioAIEditReviewMeta, FolioAIEditSeverity, FolioAIEditSkipReason, FolioAIEditSkippedOperation, FolioAIEditSnapshot, FolioAIInlineBooleanProperty, FolioAIInlineFormatting, FolioAIInlineFormattingPatch, FolioAIInsertFormattingScope, FolioAIListReference, FolioAIParagraphIndentation, FolioAIParagraphSpacing, FolioAISignatureParty, FolioAITextRangeHandle, FolioDocumentNavigationTarget, FolioDocumentOutline, FolioDocumentOutlineEntry, FolioDocumentSection, FolioDocumentSectionHandle, FolioDocumentSectionReadResult };
@@ -95,27 +95,27 @@ type FolioDocumentOperationBatch = {
95
95
  * guessing, and so tool schemas can be derived from the contract.
96
96
  */
97
97
  declare const FOLIO_DOCUMENT_OPERATION_KEYS_BY_TYPE: Readonly<{
98
- readonly replaceInBlock: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "find", "replace", "comment"];
99
- readonly replaceRange: readonly ["id", "type", "range", "severity", "area", "precondition", "suggestionId", "replace", "comment"];
100
- readonly commentOnRange: readonly ["id", "type", "range", "severity", "area", "precondition", "comment"];
101
- readonly formatRange: readonly ["id", "type", "range", "severity", "area", "precondition", "suggestionId", "formatting"];
102
- readonly insertAfterBlock: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "text", "inheritFormatting", "alignment", "spacing", "indentation", "lineBreakMode", "listLevel", "numbering", "moveId", "pageBreakBefore", "hardPageBreak", "styleId", "comment"];
103
- readonly insertBeforeBlock: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "text", "inheritFormatting", "alignment", "spacing", "indentation", "lineBreakMode", "listLevel", "numbering", "moveId", "pageBreakBefore", "hardPageBreak", "styleId", "comment"];
104
- readonly replaceBlock: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "text", "preserveFormatting", "styleId", "comment"];
105
- readonly deleteBlock: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "moveId", "comment"];
106
- readonly splitBlock: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "offset", "separator", "firstParagraphProperties", "secondParagraphProperties"];
107
- readonly mergeBlockWithNext: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "separator", "mergedParagraphProperties"];
108
- readonly setBlockParagraphProperties: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "properties"];
109
- readonly insertTable: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "position", "rows"];
110
- readonly deleteTable: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId"];
111
- readonly commentOnBlock: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "quote", "comment"];
112
- readonly insertSignatureTable: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "position", "parties", "comment"];
113
- readonly insertTableRow: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "position", "cellTexts"];
114
- readonly deleteTableRow: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId"];
115
- readonly insertTableColumn: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "position", "cellTexts"];
116
- readonly deleteTableColumn: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId"];
117
- readonly mergeTableCells: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "endBlockId", "rowCount"];
118
- readonly splitTableCell: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId"];
98
+ readonly replaceInBlock: readonly string[];
99
+ readonly replaceRange: readonly string[];
100
+ readonly commentOnRange: readonly string[];
101
+ readonly formatRange: readonly string[];
102
+ readonly insertAfterBlock: readonly string[];
103
+ readonly insertBeforeBlock: readonly string[];
104
+ readonly replaceBlock: readonly string[];
105
+ readonly deleteBlock: readonly string[];
106
+ readonly splitBlock: readonly string[];
107
+ readonly mergeBlockWithNext: readonly string[];
108
+ readonly setBlockParagraphProperties: readonly string[];
109
+ readonly insertTable: readonly string[];
110
+ readonly deleteTable: readonly string[];
111
+ readonly commentOnBlock: readonly string[];
112
+ readonly insertSignatureTable: readonly string[];
113
+ readonly insertTableRow: readonly string[];
114
+ readonly deleteTableRow: readonly string[];
115
+ readonly insertTableColumn: readonly string[];
116
+ readonly deleteTableColumn: readonly string[];
117
+ readonly mergeTableCells: readonly string[];
118
+ readonly splitTableCell: readonly string[];
119
119
  }>;
120
120
  declare const parseFolioDocumentOperationBatch: (value: unknown) => FolioDocumentOperationBatch;
121
121
  /**
@@ -448,23 +448,145 @@ const readReviewMeta = (value, path) => {
448
448
  ...area !== void 0 && { area }
449
449
  };
450
450
  };
451
- const COMMON_OPERATION_KEYS = [
452
- "id",
453
- "type",
454
- "blockId",
455
- "severity",
456
- "area",
457
- "precondition",
458
- "suggestionId"
459
- ];
460
- const RANGE_OPERATION_KEYS = [
461
- "id",
462
- "type",
463
- "range",
464
- "severity",
465
- "area",
466
- "precondition"
467
- ];
451
+ const COMMON_OPERATION_KEY_DECISIONS = {
452
+ id: true,
453
+ type: true,
454
+ blockId: true,
455
+ severity: true,
456
+ area: true,
457
+ precondition: true,
458
+ suggestionId: true
459
+ };
460
+ const RANGE_OPERATION_KEY_DECISIONS = {
461
+ id: true,
462
+ type: true,
463
+ range: true,
464
+ severity: true,
465
+ area: true,
466
+ precondition: true
467
+ };
468
+ const OPERATION_KEY_DECISIONS = {
469
+ replaceInBlock: {
470
+ ...COMMON_OPERATION_KEY_DECISIONS,
471
+ find: true,
472
+ replace: true,
473
+ comment: true
474
+ },
475
+ replaceRange: {
476
+ ...RANGE_OPERATION_KEY_DECISIONS,
477
+ suggestionId: true,
478
+ replace: true,
479
+ comment: true
480
+ },
481
+ commentOnRange: {
482
+ ...RANGE_OPERATION_KEY_DECISIONS,
483
+ suggestionId: false,
484
+ comment: true
485
+ },
486
+ formatRange: {
487
+ ...RANGE_OPERATION_KEY_DECISIONS,
488
+ suggestionId: true,
489
+ formatting: true
490
+ },
491
+ insertAfterBlock: {
492
+ ...COMMON_OPERATION_KEY_DECISIONS,
493
+ text: true,
494
+ inheritFormatting: true,
495
+ alignment: true,
496
+ spacing: true,
497
+ indentation: true,
498
+ lineBreakMode: true,
499
+ formattingScope: true,
500
+ listLevel: true,
501
+ numbering: true,
502
+ moveId: true,
503
+ pageBreakBefore: true,
504
+ hardPageBreak: true,
505
+ styleId: true,
506
+ comment: true
507
+ },
508
+ insertBeforeBlock: {
509
+ ...COMMON_OPERATION_KEY_DECISIONS,
510
+ text: true,
511
+ inheritFormatting: true,
512
+ alignment: true,
513
+ spacing: true,
514
+ indentation: true,
515
+ lineBreakMode: true,
516
+ formattingScope: true,
517
+ listLevel: true,
518
+ numbering: true,
519
+ moveId: true,
520
+ pageBreakBefore: true,
521
+ hardPageBreak: true,
522
+ styleId: true,
523
+ comment: true
524
+ },
525
+ replaceBlock: {
526
+ ...COMMON_OPERATION_KEY_DECISIONS,
527
+ text: true,
528
+ preserveFormatting: true,
529
+ styleId: true,
530
+ comment: true
531
+ },
532
+ deleteBlock: {
533
+ ...COMMON_OPERATION_KEY_DECISIONS,
534
+ moveId: true,
535
+ comment: true
536
+ },
537
+ splitBlock: {
538
+ ...COMMON_OPERATION_KEY_DECISIONS,
539
+ offset: true,
540
+ separator: true,
541
+ firstParagraphProperties: true,
542
+ secondParagraphProperties: true
543
+ },
544
+ mergeBlockWithNext: {
545
+ ...COMMON_OPERATION_KEY_DECISIONS,
546
+ separator: true,
547
+ mergedParagraphProperties: true
548
+ },
549
+ setBlockParagraphProperties: {
550
+ ...COMMON_OPERATION_KEY_DECISIONS,
551
+ properties: true
552
+ },
553
+ insertTable: {
554
+ ...COMMON_OPERATION_KEY_DECISIONS,
555
+ position: true,
556
+ rows: true
557
+ },
558
+ deleteTable: COMMON_OPERATION_KEY_DECISIONS,
559
+ commentOnBlock: {
560
+ ...COMMON_OPERATION_KEY_DECISIONS,
561
+ quote: true,
562
+ comment: true
563
+ },
564
+ insertSignatureTable: {
565
+ ...COMMON_OPERATION_KEY_DECISIONS,
566
+ position: true,
567
+ parties: true,
568
+ comment: true
569
+ },
570
+ insertTableRow: {
571
+ ...COMMON_OPERATION_KEY_DECISIONS,
572
+ position: true,
573
+ cellTexts: true
574
+ },
575
+ deleteTableRow: COMMON_OPERATION_KEY_DECISIONS,
576
+ insertTableColumn: {
577
+ ...COMMON_OPERATION_KEY_DECISIONS,
578
+ position: true,
579
+ cellTexts: true
580
+ },
581
+ deleteTableColumn: COMMON_OPERATION_KEY_DECISIONS,
582
+ mergeTableCells: {
583
+ ...COMMON_OPERATION_KEY_DECISIONS,
584
+ endBlockId: true,
585
+ rowCount: true
586
+ },
587
+ splitTableCell: COMMON_OPERATION_KEY_DECISIONS
588
+ };
589
+ const acceptedKeys = (decisions) => Object.keys(decisions).filter((key) => decisions[key] === true);
468
590
  /**
469
591
  * Every property each operation type accepts on the wire; the parser
470
592
  * rejects any other key. Exported so a lenient front door (an LLM tool
@@ -472,116 +594,27 @@ const RANGE_OPERATION_KEYS = [
472
594
  * guessing, and so tool schemas can be derived from the contract.
473
595
  */
474
596
  const FOLIO_DOCUMENT_OPERATION_KEYS_BY_TYPE = Object.freeze({
475
- replaceInBlock: [
476
- ...COMMON_OPERATION_KEYS,
477
- "find",
478
- "replace",
479
- "comment"
480
- ],
481
- replaceRange: [
482
- ...RANGE_OPERATION_KEYS,
483
- "suggestionId",
484
- "replace",
485
- "comment"
486
- ],
487
- commentOnRange: [...RANGE_OPERATION_KEYS, "comment"],
488
- formatRange: [
489
- ...RANGE_OPERATION_KEYS,
490
- "suggestionId",
491
- "formatting"
492
- ],
493
- insertAfterBlock: [
494
- ...COMMON_OPERATION_KEYS,
495
- "text",
496
- "inheritFormatting",
497
- "alignment",
498
- "spacing",
499
- "indentation",
500
- "lineBreakMode",
501
- "listLevel",
502
- "numbering",
503
- "moveId",
504
- "pageBreakBefore",
505
- "hardPageBreak",
506
- "styleId",
507
- "comment"
508
- ],
509
- insertBeforeBlock: [
510
- ...COMMON_OPERATION_KEYS,
511
- "text",
512
- "inheritFormatting",
513
- "alignment",
514
- "spacing",
515
- "indentation",
516
- "lineBreakMode",
517
- "listLevel",
518
- "numbering",
519
- "moveId",
520
- "pageBreakBefore",
521
- "hardPageBreak",
522
- "styleId",
523
- "comment"
524
- ],
525
- replaceBlock: [
526
- ...COMMON_OPERATION_KEYS,
527
- "text",
528
- "preserveFormatting",
529
- "styleId",
530
- "comment"
531
- ],
532
- deleteBlock: [
533
- ...COMMON_OPERATION_KEYS,
534
- "moveId",
535
- "comment"
536
- ],
537
- splitBlock: [
538
- ...COMMON_OPERATION_KEYS,
539
- "offset",
540
- "separator",
541
- "firstParagraphProperties",
542
- "secondParagraphProperties"
543
- ],
544
- mergeBlockWithNext: [
545
- ...COMMON_OPERATION_KEYS,
546
- "separator",
547
- "mergedParagraphProperties"
548
- ],
549
- setBlockParagraphProperties: [...COMMON_OPERATION_KEYS, "properties"],
550
- insertTable: [
551
- ...COMMON_OPERATION_KEYS,
552
- "position",
553
- "rows"
554
- ],
555
- deleteTable: COMMON_OPERATION_KEYS,
556
- commentOnBlock: [
557
- ...COMMON_OPERATION_KEYS,
558
- "quote",
559
- "comment"
560
- ],
561
- insertSignatureTable: [
562
- ...COMMON_OPERATION_KEYS,
563
- "position",
564
- "parties",
565
- "comment"
566
- ],
567
- insertTableRow: [
568
- ...COMMON_OPERATION_KEYS,
569
- "position",
570
- "cellTexts"
571
- ],
572
- deleteTableRow: COMMON_OPERATION_KEYS,
573
- insertTableColumn: [
574
- ...COMMON_OPERATION_KEYS,
575
- "position",
576
- "cellTexts"
577
- ],
578
- deleteTableColumn: COMMON_OPERATION_KEYS,
579
- mergeTableCells: [
580
- ...COMMON_OPERATION_KEYS,
581
- "endBlockId",
582
- "rowCount"
583
- ],
584
- splitTableCell: COMMON_OPERATION_KEYS
597
+ replaceInBlock: acceptedKeys(OPERATION_KEY_DECISIONS.replaceInBlock),
598
+ replaceRange: acceptedKeys(OPERATION_KEY_DECISIONS.replaceRange),
599
+ commentOnRange: acceptedKeys(OPERATION_KEY_DECISIONS.commentOnRange),
600
+ formatRange: acceptedKeys(OPERATION_KEY_DECISIONS.formatRange),
601
+ insertAfterBlock: acceptedKeys(OPERATION_KEY_DECISIONS.insertAfterBlock),
602
+ insertBeforeBlock: acceptedKeys(OPERATION_KEY_DECISIONS.insertBeforeBlock),
603
+ replaceBlock: acceptedKeys(OPERATION_KEY_DECISIONS.replaceBlock),
604
+ deleteBlock: acceptedKeys(OPERATION_KEY_DECISIONS.deleteBlock),
605
+ splitBlock: acceptedKeys(OPERATION_KEY_DECISIONS.splitBlock),
606
+ mergeBlockWithNext: acceptedKeys(OPERATION_KEY_DECISIONS.mergeBlockWithNext),
607
+ setBlockParagraphProperties: acceptedKeys(OPERATION_KEY_DECISIONS.setBlockParagraphProperties),
608
+ insertTable: acceptedKeys(OPERATION_KEY_DECISIONS.insertTable),
609
+ deleteTable: acceptedKeys(OPERATION_KEY_DECISIONS.deleteTable),
610
+ commentOnBlock: acceptedKeys(OPERATION_KEY_DECISIONS.commentOnBlock),
611
+ insertSignatureTable: acceptedKeys(OPERATION_KEY_DECISIONS.insertSignatureTable),
612
+ insertTableRow: acceptedKeys(OPERATION_KEY_DECISIONS.insertTableRow),
613
+ deleteTableRow: acceptedKeys(OPERATION_KEY_DECISIONS.deleteTableRow),
614
+ insertTableColumn: acceptedKeys(OPERATION_KEY_DECISIONS.insertTableColumn),
615
+ deleteTableColumn: acceptedKeys(OPERATION_KEY_DECISIONS.deleteTableColumn),
616
+ mergeTableCells: acceptedKeys(OPERATION_KEY_DECISIONS.mergeTableCells),
617
+ splitTableCell: acceptedKeys(OPERATION_KEY_DECISIONS.splitTableCell)
585
618
  });
586
619
  const isFolioDocumentOperationType = (value) => Object.hasOwn(FOLIO_DOCUMENT_OPERATION_KEYS_BY_TYPE, value);
587
620
  const parseSignatureParties = (value, path) => {
@@ -762,6 +795,8 @@ const parseDocumentOperation = (value, index) => {
762
795
  });
763
796
  const lineBreakMode = value["lineBreakMode"];
764
797
  if (lineBreakMode !== void 0 && lineBreakMode !== "paragraph" && lineBreakMode !== "inline") return invalidBatch(`${path}.lineBreakMode`, "expected \"paragraph\" or \"inline\" when provided");
798
+ const formattingScope = value["formattingScope"];
799
+ if (formattingScope !== void 0 && formattingScope !== "firstParagraph" && formattingScope !== "allParagraphs") return invalidBatch(`${path}.formattingScope`, "expected \"firstParagraph\" or \"allParagraphs\" when provided");
765
800
  const text = readString(value, "text", path);
766
801
  if (hardPageBreak !== void 0 && text.length > 0) return invalidBatch(`${path}.text`, "expected empty text with hardPageBreak");
767
802
  if (hardPageBreak !== void 0 && pageBreakBefore !== void 0) return invalidBatch(`${path}.pageBreakBefore`, "cannot combine hardPageBreak with pageBreakBefore");
@@ -777,6 +812,7 @@ const parseDocumentOperation = (value, index) => {
777
812
  ...spacing !== void 0 && { spacing },
778
813
  ...indentation !== void 0 && { indentation },
779
814
  ...lineBreakMode !== void 0 && { lineBreakMode },
815
+ ...formattingScope !== void 0 && { formattingScope },
780
816
  ...listLevel !== void 0 && { listLevel },
781
817
  ...numbering !== void 0 && { numbering },
782
818
  ...moveId !== void 0 && { moveId },
@@ -107,7 +107,6 @@ const withoutOrphanBlockMarkers = (blocks, validCommentIds) => {
107
107
  const withoutOrphanBlockMarker = (block, validCommentIds) => {
108
108
  if (block.type === "paragraph") return withoutOrphanParagraphMarkers(block, validCommentIds);
109
109
  if (block.type === "table") return withoutOrphanTableMarkers(block, validCommentIds);
110
- if (!("content" in block) || !block.content) return block;
111
110
  const content = withoutOrphanBlockMarkers(block.content, validCommentIds);
112
111
  if (!content) return block;
113
112
  return {
@@ -1,20 +1,9 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
2
  //#region src/docx/headerFooterVerbatim.d.ts
3
- /**
4
- * Folio extension on {@link HeaderFooter}: original part XML captured at parse
5
- * time so unedited headers/footers re-emit byte-identically on save (VML OLE
6
- * wrappers, smart tags, and other constructs the model cannot fully represent).
7
- * Cleared on first edit.
8
- */
9
- type HeaderFooterWithVerbatim = document_d_exports.HeaderFooter & {
10
- verbatimXml?: string;
11
- /** Fingerprint of modeled fields at parse time; verbatim replay is safe only while it matches. */
12
- verbatimFingerprint?: string;
13
- };
14
3
  declare const getHeaderFooterVerbatimXml: (hf: document_d_exports.HeaderFooter) => string | undefined;
15
4
  declare const canReplayHeaderFooterVerbatim: (hf: document_d_exports.HeaderFooter) => boolean;
16
5
  declare const assignHeaderFooterVerbatimXml: (hf: document_d_exports.HeaderFooter, xml: string) => void;
17
6
  declare const refreshHeaderFooterVerbatimFingerprint: (hf: document_d_exports.HeaderFooter) => void;
18
7
  declare const clearHeaderFooterVerbatimXml: (hf: document_d_exports.HeaderFooter) => void;
19
8
  //#endregion
20
- export { HeaderFooterWithVerbatim, assignHeaderFooterVerbatimXml, canReplayHeaderFooterVerbatim, clearHeaderFooterVerbatimXml, getHeaderFooterVerbatimXml, refreshHeaderFooterVerbatimFingerprint };
9
+ export { assignHeaderFooterVerbatimXml, canReplayHeaderFooterVerbatim, clearHeaderFooterVerbatimXml, getHeaderFooterVerbatimXml, refreshHeaderFooterVerbatimFingerprint };
@@ -45,9 +45,7 @@ declare function createNumberingMap(definitions: document_d_exports.NumberingDef
45
45
  declare function computeListRendering(numPr: {
46
46
  numId?: number;
47
47
  ilvl?: number;
48
- }, numbering: NumberingMap): (document_d_exports.ListRendering & {
49
- levelStarts: number[];
50
- }) | null;
48
+ }, numbering: NumberingMap): document_d_exports.ListRendering | null;
51
49
  /**
52
50
  * Render list marker text by replacing placeholders with formatted numbers
53
51
  *
@@ -1,11 +1,7 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
2
  //#region src/docx/settingsParser.d.ts
3
- type FolioDocumentSettings = document_d_exports.DocumentSettings & {
4
- /** Swap left/right section margins on even physical pages. */
5
- mirrorMargins?: boolean;
6
- };
7
3
  /** OOXML default per §17.6.13 when `w:defaultTabStop` is absent. */
8
4
  declare const DEFAULT_TAB_STOP_TWIPS = 720;
9
- declare function parseSettings(xml: string | null): FolioDocumentSettings;
5
+ declare function parseSettings(xml: string | null): document_d_exports.DocumentSettings;
10
6
  //#endregion
11
- export { DEFAULT_TAB_STOP_TWIPS, FolioDocumentSettings, parseSettings };
7
+ export { DEFAULT_TAB_STOP_TWIPS, parseSettings };
@@ -105,13 +105,7 @@ const buildFlowOptions = (document, pageContentHeight) => {
105
105
  if (finalSectionDocumentGridLinePitchTwips !== void 0) options.finalSectionDocumentGridLinePitchTwips = finalSectionDocumentGridLinePitchTwips;
106
106
  return options;
107
107
  };
108
- /**
109
- * `w:mirrorMargins` is parsed into `FolioDocumentSettings` but the shared
110
- * `Document` model types `settings` as the narrower `DocumentSettings`, so the
111
- * flag is present at runtime and invisible to the type. The React paged editor
112
- * narrows the same way; both should stop once the model carries the field.
113
- */
114
- const readsMirrorMargins = (settings) => settings !== void 0 && "mirrorMargins" in settings && settings.mirrorMargins === true;
108
+ const readsMirrorMargins = (settings) => settings?.mirrorMargins === true;
115
109
  const buildBlockLookup = (blocks, measures) => new Map(blocks.flatMap((block, index) => {
116
110
  const measure = measures.at(index);
117
111
  return measure === void 0 ? [] : [[String(block.id), {
@@ -15,6 +15,7 @@ import { autospacingMatchesBase, hasAutospacingBaseSide } from "../autospacingBa
15
15
  import { expectBookmarkBoundaryAttrs } from "../bookmarkBoundaryAttrs.js";
16
16
  import { paragraphRejectAttrPatch, paragraphRejectOriginalFormatting, removeParagraphPropertyChanges } from "../commands/propertyChangeScope.js";
17
17
  import { applyRunFormattingOverrideAttrs, buildRunFormattingOverrideAttrs } from "../extensions/marks/RunFormattingOverrideExtension.js";
18
+ import { listRenderingFromAttrs as listRenderingFromAttrs$1 } from "../listRenderingAttrs.js";
18
19
  import { resolveNumberedRefFields } from "../numberedRefFields.js";
19
20
  import { directParagraphAlignment } from "../paragraphAlignment.js";
20
21
  import { directionToBidi } from "../paragraphDirection.js";
@@ -657,25 +658,10 @@ function listRenderingFromAttrs(attrs) {
657
658
  const numId = attrs.numPr?.numId;
658
659
  if (numId === void 0 || numId === 0) return;
659
660
  if (!(attrs.listMarker != null || attrs.listIsBullet || attrs.listNumFmt != null)) return;
660
- return {
661
- marker: attrs.listMarker ?? "",
662
- ...attrs.listMarkerTemplate != null && { markerTemplate: attrs.listMarkerTemplate },
663
- level: attrs.numPr?.ilvl ?? 0,
664
- numId,
665
- isBullet: attrs.listIsBullet ?? false,
666
- ...attrs.listIsLegal != null && { isLegal: attrs.listIsLegal },
667
- ...attrs.listNumFmt != null && { numFmt: attrs.listNumFmt },
668
- ...attrs.listMarkerHidden != null && { markerHidden: attrs.listMarkerHidden },
669
- ...attrs.listMarkerFormatting != null && { markerFormatting: attrs.listMarkerFormatting },
670
- ...attrs.listMarkerAlignment != null && { markerAlignment: attrs.listMarkerAlignment },
671
- ...attrs.listMarkerSuffix != null && { markerSuffix: attrs.listMarkerSuffix },
672
- ...attrs.listMarkerAllCaps != null && { markerAllCaps: attrs.listMarkerAllCaps },
673
- ...attrs.listImplicitChildLevelAdvances != null && { implicitChildLevelAdvances: attrs.listImplicitChildLevelAdvances },
674
- ...attrs.listMarkerSecondSlotOffsetTwips != null && { markerSecondSlotOffsetTwips: attrs.listMarkerSecondSlotOffsetTwips },
675
- ...attrs.listLevelNumFmts != null && { levelNumFmts: attrs.listLevelNumFmts },
676
- ...attrs.listAbstractNumId != null && { abstractNumId: attrs.listAbstractNumId },
677
- ...attrs.listStartOverride != null && { startOverride: attrs.listStartOverride }
678
- };
661
+ return listRenderingFromAttrs$1({
662
+ attrs,
663
+ numId
664
+ });
679
665
  }
680
666
  /**
681
667
  * Create a paragraph containing only a page break run (for DOCX serialization)
@@ -9,6 +9,7 @@ import { mergeTextFormatting } from "../../utils/textFormattingMerge.js";
9
9
  import { emuToPixels } from "../../utils/units.js";
10
10
  import { setAutospacingBaseValue } from "../autospacingBase.js";
11
11
  import { buildRunFormattingOverrideAttrs } from "../extensions/marks/RunFormattingOverrideExtension.js";
12
+ import { listRenderingAttrPatch } from "../listRenderingAttrs.js";
12
13
  import { stampNumberedRefFieldBaselines } from "../numberedRefFields.js";
13
14
  import { pageBreakRunParagraphProjectionDispositionForFeatures } from "../pageBreakRunProjection.js";
14
15
  import { directionFromBidi } from "../paragraphDirection.js";
@@ -422,25 +423,7 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
422
423
  if (tableOfContentsLevel !== void 0) attrs._tableOfContentsLevel = tableOfContentsLevel;
423
424
  if (formatting?.numPr) attrs.numPr = formatting.numPr;
424
425
  if (formatting?.numPrFromStyle) attrs.numPrFromStyle = formatting.numPrFromStyle;
425
- if (paragraph.listRendering?.numFmt) attrs.listNumFmt = paragraph.listRendering.numFmt;
426
- if (paragraph.listRendering?.isBullet) attrs.listIsBullet = paragraph.listRendering.isBullet;
427
- if (paragraph.listRendering?.isLegal) attrs.listIsLegal = paragraph.listRendering.isLegal;
428
- if (paragraph.listRendering?.marker) attrs.listMarker = paragraph.listRendering.marker;
429
- if (paragraph.listRendering?.markerTemplate) attrs.listMarkerTemplate = paragraph.listRendering.markerTemplate;
430
- if (paragraph.listRendering?.markerHidden) attrs.listMarkerHidden = paragraph.listRendering.markerHidden;
431
- if (paragraph.listRendering?.markerFormatting) attrs.listMarkerFormatting = paragraph.listRendering.markerFormatting;
432
- if (paragraph.listRendering?.markerAlignment) attrs.listMarkerAlignment = paragraph.listRendering.markerAlignment;
433
- if (paragraph.listRendering?.markerSuffix) attrs.listMarkerSuffix = paragraph.listRendering.markerSuffix;
434
- if (paragraph.listRendering?.markerAllCaps) attrs.listMarkerAllCaps = paragraph.listRendering.markerAllCaps;
435
- if (paragraph.listRendering?.implicitChildLevelAdvances !== void 0) attrs.listImplicitChildLevelAdvances = paragraph.listRendering.implicitChildLevelAdvances;
436
- if (paragraph.listRendering?.markerSecondSlotOffsetTwips !== void 0) attrs.listMarkerSecondSlotOffsetTwips = paragraph.listRendering.markerSecondSlotOffsetTwips;
437
- if (paragraph.listRendering?.levelNumFmts) attrs.listLevelNumFmts = paragraph.listRendering.levelNumFmts;
438
- if (paragraph.listRendering && "levelStarts" in paragraph.listRendering) {
439
- const { levelStarts } = paragraph.listRendering;
440
- if (Array.isArray(levelStarts) && levelStarts.every((value) => typeof value === "number")) attrs.listLevelStarts = levelStarts;
441
- }
442
- if (paragraph.listRendering?.abstractNumId !== void 0) attrs.listAbstractNumId = paragraph.listRendering.abstractNumId;
443
- if (paragraph.listRendering?.startOverride !== void 0) attrs.listStartOverride = paragraph.listRendering.startOverride;
426
+ if (paragraph.listRendering) Object.assign(attrs, listRenderingAttrPatch(paragraph.listRendering));
444
427
  if (formatting) attrs._originalFormatting = formatting;
445
428
  if (paragraph.propertyChanges && paragraph.propertyChanges.length > 0) attrs._propertyChanges = [...paragraph.propertyChanges];
446
429
  if (paragraph.pPrMark) attrs.pPrMark = paragraph.pPrMark;
@@ -1,6 +1,7 @@
1
1
  import { expectParagraphAttrs } from "../../attrs/index.js";
2
2
  import { PPR_CHANGE_SCOPED_ATTR_KEYS, hasSerializableParagraphPropertyChange } from "../../commands/propertyChangeScope.js";
3
- import { CLEARED_LIST_RENDERING_ATTRS, LIST_RENDERING_ATTR_KEYS } from "../../listMarker.js";
3
+ import { CLEARED_LIST_RENDERING_ATTRS } from "../../listMarker.js";
4
+ import { LIST_RENDERING_ATTR_KEYS } from "../../listRenderingAttrs.js";
4
5
  import { getDocumentNumbering } from "../../plugins/documentNumbering.js";
5
6
  import { SUGGESTION_META, makeRevisionInfo } from "../../plugins/suggestionMode.js";
6
7
  import { listLevelAttrPatch } from "../../styles/resolvedStyleAttrs.js";
@@ -1,5 +1,6 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
2
  import { ParagraphAttrs } from "./schema/nodes.js";
3
+ import { LIST_RENDERING_ATTR_KEYS } from "./listRenderingAttrs.js";
3
4
  //#region src/prosemirror/listMarker.d.ts
4
5
  type ListCounterState = {
5
6
  counters: Map<number, number[]>;
@@ -42,7 +43,6 @@ type ResolvedListTemplate = {
42
43
  components: readonly ResolvedListComponent[];
43
44
  };
44
45
  declare const MAX_LIST_LEVEL = 8;
45
- declare const LIST_RENDERING_ATTR_KEYS: readonly ["listIsBullet", "listIsLegal", "listNumFmt", "listMarker", "listMarkerTemplate", "listMarkerHidden", "listMarkerFormatting", "listMarkerAlignment", "listMarkerSuffix", "listMarkerAllCaps", "listImplicitChildLevelAdvances", "listMarkerSecondSlotOffsetTwips", "listLevelNumFmts", "listLevelStarts", "listAbstractNumId", "listStartOverride"];
46
46
  declare const CLEARED_LIST_RENDERING_ATTRS: Readonly<{
47
47
  listIsBullet: null;
48
48
  listIsLegal: null;
@@ -1,25 +1,8 @@
1
1
  import { convertBulletToUnicode } from "../docx/bulletMarkers.js";
2
2
  import { formatOoxmlCounter } from "../docx/ooxmlCounterFormatter.js";
3
+ import { LIST_RENDERING_ATTR_KEYS } from "./listRenderingAttrs.js";
3
4
  //#region src/prosemirror/listMarker.ts
4
5
  const MAX_LIST_LEVEL = 8;
5
- const LIST_RENDERING_ATTR_KEYS = [
6
- "listIsBullet",
7
- "listIsLegal",
8
- "listNumFmt",
9
- "listMarker",
10
- "listMarkerTemplate",
11
- "listMarkerHidden",
12
- "listMarkerFormatting",
13
- "listMarkerAlignment",
14
- "listMarkerSuffix",
15
- "listMarkerAllCaps",
16
- "listImplicitChildLevelAdvances",
17
- "listMarkerSecondSlotOffsetTwips",
18
- "listLevelNumFmts",
19
- "listLevelStarts",
20
- "listAbstractNumId",
21
- "listStartOverride"
22
- ];
23
6
  const CLEARED_LIST_RENDERING_ATTRS = Object.freeze({
24
7
  listIsBullet: null,
25
8
  listIsLegal: null,
@@ -0,0 +1,42 @@
1
+ import { document_d_exports } from "../types/document.js";
2
+ import { ParagraphAttrs } from "./schema/nodes.js";
3
+ //#region src/prosemirror/listRenderingAttrs.d.ts
4
+ /** `ListRendering` fields that have their own editor attr. */
5
+ type ListRenderingAttrField = Exclude<keyof document_d_exports.ListRendering, "level" | "numId">;
6
+ declare const LIST_RENDERING_ATTR_BY_FIELD: {
7
+ readonly marker: "listMarker";
8
+ readonly markerTemplate: "listMarkerTemplate";
9
+ readonly isBullet: "listIsBullet";
10
+ readonly isLegal: "listIsLegal";
11
+ readonly numFmt: "listNumFmt";
12
+ readonly markerHidden: "listMarkerHidden";
13
+ readonly markerFormatting: "listMarkerFormatting";
14
+ readonly markerAlignment: "listMarkerAlignment";
15
+ readonly markerAllCaps: "listMarkerAllCaps";
16
+ readonly markerSuffix: "listMarkerSuffix";
17
+ readonly levelNumFmts: "listLevelNumFmts";
18
+ readonly levelStarts: "listLevelStarts";
19
+ readonly abstractNumId: "listAbstractNumId";
20
+ readonly startOverride: "listStartOverride";
21
+ readonly implicitChildLevelAdvances: "listImplicitChildLevelAdvances";
22
+ readonly markerSecondSlotOffsetTwips: "listMarkerSecondSlotOffsetTwips";
23
+ };
24
+ type ListRenderingAttrKey = (typeof LIST_RENDERING_ATTR_BY_FIELD)[ListRenderingAttrField];
25
+ declare const LIST_RENDERING_ATTR_KEYS: readonly ListRenderingAttrKey[];
26
+ /**
27
+ * Editor attrs carrying `rendering`. A falsy marker, flag or format is left
28
+ * unset: the editor treats `null` and absent alike for those, and the parser
29
+ * never authors them as `false` or `""` deliberately.
30
+ */
31
+ declare const listRenderingAttrPatch: (rendering: document_d_exports.ListRendering) => Partial<ParagraphAttrs>;
32
+ type ListRenderingFromAttrsOptions = {
33
+ attrs: ParagraphAttrs;
34
+ numId: number;
35
+ };
36
+ /**
37
+ * Inverse of `listRenderingAttrPatch`. The caller decides whether the
38
+ * paragraph is a list item at all; this only reassembles the fields.
39
+ */
40
+ declare const listRenderingFromAttrs: ({ attrs, numId }: ListRenderingFromAttrsOptions) => document_d_exports.ListRendering;
41
+ //#endregion
42
+ export { LIST_RENDERING_ATTR_BY_FIELD, LIST_RENDERING_ATTR_KEYS, ListRenderingAttrField, ListRenderingAttrKey, listRenderingAttrPatch, listRenderingFromAttrs };
@@ -0,0 +1,80 @@
1
+ //#region src/prosemirror/listRenderingAttrs.ts
2
+ const LIST_RENDERING_ATTR_BY_FIELD = {
3
+ marker: "listMarker",
4
+ markerTemplate: "listMarkerTemplate",
5
+ isBullet: "listIsBullet",
6
+ isLegal: "listIsLegal",
7
+ numFmt: "listNumFmt",
8
+ markerHidden: "listMarkerHidden",
9
+ markerFormatting: "listMarkerFormatting",
10
+ markerAlignment: "listMarkerAlignment",
11
+ markerAllCaps: "listMarkerAllCaps",
12
+ markerSuffix: "listMarkerSuffix",
13
+ levelNumFmts: "listLevelNumFmts",
14
+ levelStarts: "listLevelStarts",
15
+ abstractNumId: "listAbstractNumId",
16
+ startOverride: "listStartOverride",
17
+ implicitChildLevelAdvances: "listImplicitChildLevelAdvances",
18
+ markerSecondSlotOffsetTwips: "listMarkerSecondSlotOffsetTwips"
19
+ };
20
+ const LIST_RENDERING_ATTR_KEYS = Object.values(LIST_RENDERING_ATTR_BY_FIELD);
21
+ const isDefinedEntry = ([, value]) => value !== void 0;
22
+ const definedAttrs = (patch) => Object.fromEntries(Object.entries(patch).filter(isDefinedEntry));
23
+ const definedFields = (fields) => Object.fromEntries(Object.entries(fields).filter(isDefinedEntry));
24
+ /**
25
+ * Editor attrs carrying `rendering`. A falsy marker, flag or format is left
26
+ * unset: the editor treats `null` and absent alike for those, and the parser
27
+ * never authors them as `false` or `""` deliberately.
28
+ */
29
+ const listRenderingAttrPatch = (rendering) => {
30
+ const patch = {
31
+ listMarker: rendering.marker || void 0,
32
+ listMarkerTemplate: rendering.markerTemplate || void 0,
33
+ listIsBullet: rendering.isBullet || void 0,
34
+ listIsLegal: rendering.isLegal || void 0,
35
+ listNumFmt: rendering.numFmt || void 0,
36
+ listMarkerHidden: rendering.markerHidden || void 0,
37
+ listMarkerFormatting: rendering.markerFormatting || void 0,
38
+ listMarkerAlignment: rendering.markerAlignment || void 0,
39
+ listMarkerAllCaps: rendering.markerAllCaps || void 0,
40
+ listMarkerSuffix: rendering.markerSuffix || void 0,
41
+ listLevelNumFmts: rendering.levelNumFmts || void 0,
42
+ listLevelStarts: rendering.levelStarts || void 0,
43
+ listAbstractNumId: rendering.abstractNumId,
44
+ listStartOverride: rendering.startOverride,
45
+ listImplicitChildLevelAdvances: rendering.implicitChildLevelAdvances,
46
+ listMarkerSecondSlotOffsetTwips: rendering.markerSecondSlotOffsetTwips
47
+ };
48
+ return definedAttrs(patch);
49
+ };
50
+ /**
51
+ * Inverse of `listRenderingAttrPatch`. The caller decides whether the
52
+ * paragraph is a list item at all; this only reassembles the fields.
53
+ */
54
+ const listRenderingFromAttrs = ({ attrs, numId }) => {
55
+ const optional = {
56
+ markerTemplate: attrs.listMarkerTemplate ?? void 0,
57
+ isLegal: attrs.listIsLegal ?? void 0,
58
+ numFmt: attrs.listNumFmt ?? void 0,
59
+ markerHidden: attrs.listMarkerHidden ?? void 0,
60
+ markerFormatting: attrs.listMarkerFormatting ?? void 0,
61
+ markerAlignment: attrs.listMarkerAlignment ?? void 0,
62
+ markerAllCaps: attrs.listMarkerAllCaps ?? void 0,
63
+ markerSuffix: attrs.listMarkerSuffix ?? void 0,
64
+ levelNumFmts: attrs.listLevelNumFmts ?? void 0,
65
+ levelStarts: attrs.listLevelStarts ?? void 0,
66
+ abstractNumId: attrs.listAbstractNumId ?? void 0,
67
+ startOverride: attrs.listStartOverride ?? void 0,
68
+ implicitChildLevelAdvances: attrs.listImplicitChildLevelAdvances ?? void 0,
69
+ markerSecondSlotOffsetTwips: attrs.listMarkerSecondSlotOffsetTwips ?? void 0
70
+ };
71
+ return {
72
+ marker: attrs.listMarker ?? "",
73
+ level: attrs.numPr?.ilvl ?? 0,
74
+ numId,
75
+ isBullet: attrs.listIsBullet ?? false,
76
+ ...definedFields(optional)
77
+ };
78
+ };
79
+ //#endregion
80
+ export { LIST_RENDERING_ATTR_BY_FIELD, LIST_RENDERING_ATTR_KEYS, listRenderingAttrPatch, listRenderingFromAttrs };
@@ -201,7 +201,7 @@ type RunFormattingOverrideAttrs = {
201
201
  position?: 0;
202
202
  rtl?: false;
203
203
  scale?: 100;
204
- shading?: ShadingProperties & {
204
+ shading?: Omit<ShadingProperties, "pattern"> & {
205
205
  pattern: "nil";
206
206
  };
207
207
  spacing?: 0;
@@ -2,6 +2,7 @@ import { computeListRendering, numberingLevelHasMarkerSlot } from "../../docx/nu
2
2
  import { tableOfContentsStyleLevel } from "../../utils/tableOfContentsStyle.js";
3
3
  import { setAutospacingBaseValue } from "../autospacingBase.js";
4
4
  import { CLEARED_LIST_RENDERING_ATTRS } from "../listMarker.js";
5
+ import { listRenderingAttrPatch } from "../listRenderingAttrs.js";
5
6
  //#region src/prosemirror/styles/resolvedStyleAttrs.ts
6
7
  /**
7
8
  * Shared helper for projecting a resolved paragraph style onto ProseMirror
@@ -103,20 +104,7 @@ function listAttrsFromNumbering(numPr, numbering) {
103
104
  return {
104
105
  ...CLEARED_LIST_RENDERING_ATTRS,
105
106
  numPr: targetNumPr,
106
- listNumFmt: rendering?.numFmt ?? null,
107
- listIsBullet: rendering?.isBullet ?? null,
108
- listIsLegal: rendering?.isLegal ?? null,
109
- listMarker: rendering?.marker ?? null,
110
- listMarkerTemplate: rendering?.markerTemplate ?? null,
111
- listMarkerHidden: rendering?.markerHidden ?? null,
112
- listMarkerFormatting: rendering?.markerFormatting ?? null,
113
- listMarkerAlignment: rendering?.markerAlignment ?? null,
114
- listMarkerSuffix: rendering?.markerSuffix ?? null,
115
- listMarkerAllCaps: rendering?.markerAllCaps ?? null,
116
- listLevelNumFmts: rendering?.levelNumFmts ?? null,
117
- listLevelStarts: rendering?.levelStarts ?? null,
118
- listAbstractNumId: rendering?.abstractNumId ?? null,
119
- listStartOverride: rendering?.startOverride ?? null
107
+ ...rendering && listRenderingAttrPatch(rendering)
120
108
  };
121
109
  }
122
110
  /** Recompute every level-dependent attr when a paragraph changes list level. */
@@ -85,7 +85,7 @@ function mergeDocumentContent(target, source) {
85
85
  function remapBlock(block, numIdRemap, abstractNumIdRemap) {
86
86
  if (block.type === "paragraph") return remapParagraph(block, numIdRemap, abstractNumIdRemap);
87
87
  if (block.type === "table") return remapTable(block, numIdRemap, abstractNumIdRemap);
88
- if ("content" in block && Array.isArray(block.content)) return {
88
+ if (block.type === "blockSdt" && Array.isArray(block.content)) return {
89
89
  ...block,
90
90
  content: block.content.map((child) => remapBlock(child, numIdRemap, abstractNumIdRemap))
91
91
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stll/folio-core",
3
- "version": "0.39.1",
3
+ "version": "0.40.0",
4
4
  "description": "Headless, framework-neutral core of folio: the OOXML (.docx) parser, document model, ProseMirror integration, and page-layout engine. No React.",
5
5
  "keywords": [
6
6
  "document-model",
@@ -121,7 +121,7 @@
121
121
  "perf": "bun scripts/profile-editor.ts"
122
122
  },
123
123
  "dependencies": {
124
- "@stll/docx-core": "^0.20.1",
124
+ "@stll/docx-core": "^0.20.2",
125
125
  "@stll/docx-utils": "^0.1.0",
126
126
  "@stll/template-conditions": ">=0.4.0 <1.0.0",
127
127
  "better-result": "3.0.1",