@stll/folio-core 0.56.0 → 0.57.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.
- package/dist/ai-edits/apply.js +45 -14
- package/dist/ai-edits/batch-claims.d.ts +3 -1
- package/dist/ai-edits/batch-claims.js +25 -1
- package/dist/ai-edits/table-row-column-mutations.js +17 -3
- package/dist/ai-suggestions/apply.js +20 -1
- package/dist/compare/inline-atoms.js +40 -16
- package/dist/compare/inline-provenance.js +12 -5
- package/dist/compat/eigenpal.d.ts +2 -1
- package/dist/compat/eigenpal.js +2 -1
- package/dist/controller/canonicalClipboard.js +7 -1
- package/dist/controller/canonicalComments.d.ts +41 -0
- package/dist/controller/canonicalComments.js +152 -0
- package/dist/controller/canonicalComposition.d.ts +4 -0
- package/dist/controller/canonicalComposition.js +43 -11
- package/dist/controller/canonicalInlineProjection.d.ts +6 -1
- package/dist/controller/canonicalInlineProjection.js +86 -3
- package/dist/controller/canonicalInput.js +10 -1
- package/dist/controller/canonicalInputTimer.d.ts +10 -1
- package/dist/controller/canonicalInputTimer.js +24 -1
- package/dist/controller/canonicalPublicOperations.d.ts +2 -2
- package/dist/controller/canonicalPublicOperations.js +107 -15
- package/dist/controller/canonicalSelection.d.ts +18 -0
- package/dist/controller/canonicalSelection.js +32 -0
- package/dist/controller/canonicalSession.d.ts +3 -0
- package/dist/controller/canonicalSession.js +58 -24
- package/dist/controller/canonicalStoryEditor.d.ts +2 -0
- package/dist/controller/canonicalStoryEditor.js +20 -0
- package/dist/controller/folioEditor.js +13 -0
- package/dist/controller/headerFooterEditorManager.d.ts +1 -1
- package/dist/controller/headerFooterEditorManager.js +25 -11
- package/dist/controller/hiddenEditorApi.d.ts +13 -2
- package/dist/controller/hiddenEditorApi.js +4 -0
- package/dist/controller/hiddenEditorManager.d.ts +3 -1
- package/dist/controller/hiddenEditorManager.js +166 -13
- package/dist/controller/noteEditorManager.d.ts +1 -1
- package/dist/controller/noteEditorManager.js +28 -13
- package/dist/docx/builtInStyles.js +13 -6
- package/dist/docx/containerChildren.gen.d.ts +3 -1
- package/dist/docx/containerChildren.gen.js +33 -1
- package/dist/docx/fieldParser.js +14 -2
- package/dist/docx/hyperlinkParser.d.ts +1 -1
- package/dist/docx/hyperlinkParser.js +20 -1
- package/dist/docx/inlineWrapperContent.d.ts +4 -4
- package/dist/docx/inlineWrapperContent.js +4 -4
- package/dist/docx/linkedSdtPreservation.d.ts +10 -0
- package/dist/docx/linkedSdtPreservation.js +37 -0
- package/dist/docx/paragraphParser.js +88 -67
- package/dist/docx/paragraphPropertySource.d.ts +22 -1
- package/dist/docx/paragraphPropertySource.js +107 -1
- package/dist/docx/preservedRunContent.js +2 -1
- package/dist/docx/relsParser.js +26 -2
- package/dist/docx/rezip.js +9 -6
- package/dist/docx/selectiveSave.js +10 -8
- package/dist/docx/serializer/commentSerializer.d.ts +4 -1
- package/dist/docx/serializer/commentSerializer.js +7 -3
- package/dist/docx/serializer/paragraphSerializer.js +207 -94
- package/dist/docx/server/materializeYjsDocx.js +14 -6
- package/dist/docx/server/migrateYjsAttrSchema.js +17 -5
- package/dist/i18n/messages/ar.gen.js +4 -0
- package/dist/i18n/messages/catalogs.gen.d.ts +68 -0
- package/dist/i18n/messages/catalogs.gen.js +68 -0
- package/dist/i18n/messages/cs.gen.js +4 -0
- package/dist/i18n/messages/de.gen.js +4 -0
- package/dist/i18n/messages/en.gen.js +4 -0
- package/dist/i18n/messages/es.gen.js +4 -0
- package/dist/i18n/messages/et.gen.js +4 -0
- package/dist/i18n/messages/fr.gen.js +4 -0
- package/dist/i18n/messages/he.gen.js +4 -0
- package/dist/i18n/messages/hi.gen.js +4 -0
- package/dist/i18n/messages/hu.gen.js +4 -0
- package/dist/i18n/messages/lt.gen.js +4 -0
- package/dist/i18n/messages/lv.gen.js +4 -0
- package/dist/i18n/messages/messages.gen.d.ts +4 -0
- package/dist/i18n/messages/pl.gen.js +4 -0
- package/dist/i18n/messages/pt-BR.gen.js +4 -0
- package/dist/i18n/messages/sk.gen.js +4 -0
- package/dist/i18n/messages/tr.gen.js +4 -0
- package/dist/i18n/messages/zh-CN.gen.js +4 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/internal/revisionResolutionInline.js +25 -3
- package/dist/markdown/renderRuns.js +1 -11
- package/dist/panel-layout.d.ts +11 -9
- package/dist/panel-layout.js +13 -9
- package/dist/prosemirror/addTrackedDeletionMark.d.ts +18 -0
- package/dist/prosemirror/addTrackedDeletionMark.js +87 -0
- package/dist/prosemirror/attrs/index.js +5 -0
- package/dist/prosemirror/commands/comments.js +60 -35
- package/dist/prosemirror/commands/propertyChangeScope.js +3 -6
- package/dist/prosemirror/commands/resolveParagraphProperties.js +22 -13
- package/dist/prosemirror/commentOps.js +15 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +22 -3
- package/dist/prosemirror/conversion/toProseDoc.js +119 -18
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +22 -5
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +74 -25
- package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +11 -0
- package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +22 -14
- package/dist/prosemirror/extensions/marks/markUtils.js +8 -7
- package/dist/prosemirror/extensions/marks/noteReferenceDeletion.js +5 -2
- package/dist/prosemirror/fieldRepresentation.d.ts +8 -0
- package/dist/prosemirror/fieldRepresentation.js +18 -0
- package/dist/prosemirror/hyperlinkRemoval.d.ts +13 -1
- package/dist/prosemirror/hyperlinkRemoval.js +28 -9
- package/dist/prosemirror/listNumbering.js +11 -5
- package/dist/prosemirror/noteReferenceOccurrenceId.d.ts +5 -0
- package/dist/prosemirror/noteReferenceOccurrenceId.js +5 -0
- package/dist/prosemirror/noteReferenceOccurrences.d.ts +21 -0
- package/dist/prosemirror/noteReferenceOccurrences.js +185 -0
- package/dist/prosemirror/noteReferenceReview.js +14 -1
- package/dist/prosemirror/plugins/documentStyles.d.ts +4 -1
- package/dist/prosemirror/plugins/documentStyles.js +17 -10
- package/dist/prosemirror/plugins/suggestionMode.js +47 -49
- package/dist/prosemirror/preservedXmlReview.d.ts +6 -0
- package/dist/prosemirror/preservedXmlReview.js +35 -0
- package/dist/prosemirror/runFormattingFromMarks.js +2 -2
- package/dist/prosemirror/runFormattingReconciliation.js +5 -4
- package/dist/prosemirror/runPropertyChangeResolution.d.ts +8 -1
- package/dist/prosemirror/runPropertyChangeResolution.js +24 -2
- package/dist/prosemirror/runStyleFormatting.d.ts +3 -1
- package/dist/prosemirror/runStyleFormatting.js +3 -1
- package/dist/prosemirror/schema/marks.d.ts +1 -0
- package/dist/prosemirror/schema/nodes.d.ts +2 -0
- package/dist/prosemirror/styles/paragraphStyleCascade.js +4 -1
- package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +15 -15
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +69 -28
- package/dist/prosemirror/textInput.d.ts +5 -1
- package/dist/prosemirror/textInput.js +3 -3
- package/dist/prosemirror/trackedRevisionPath.d.ts +5 -1
- package/dist/prosemirror/trackedRevisionPath.js +39 -1
- package/dist/prosemirror/validation.js +3 -5
- package/dist/prosemirror/yjsDocumentMetadata.d.ts +9 -3
- package/dist/prosemirror/yjsDocumentMetadata.js +37 -8
- package/dist/types/canonicalCapabilities.d.ts +6 -20
- package/dist/types/canonicalCapabilities.js +6 -20
- package/dist/types/canonicalComments.d.ts +51 -0
- package/dist/types/canonicalComments.js +0 -0
- package/dist/types/canonicalSections.d.ts +12 -0
- package/dist/types/canonicalSections.js +0 -0
- package/dist/utils/headingCollector.js +45 -4
- package/dist/utils/outlineDepth.d.ts +9 -0
- package/dist/utils/outlineDepth.js +9 -0
- package/package.json +2 -2
package/dist/ai-edits/apply.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { paragraphNumberingReference, paragraphNumberingReferenceId } from "../docx/numberingReference.js";
|
|
2
2
|
import { formattingEquals } from "../docx/runConsolidator.js";
|
|
3
3
|
import { isStyleSourcedParagraphNumbering } from "../internal/paragraphFormattingSerialization.js";
|
|
4
|
+
import { addTrackedDeletionMark } from "../prosemirror/addTrackedDeletionMark.js";
|
|
4
5
|
import { deleteTextBoxesAnchoredAt, droppedTextBoxAnchorIds, endOfParagraphWithItsTextBoxes, gatherTextBoxesAfterParagraph, textBoxAnchorIdOf, textBoxAnchorIdsBetween } from "../prosemirror/anchoredTextBoxes.js";
|
|
5
6
|
import { expectParagraphAttrs, expectRunPropertyChangeMarkAttrs, expectTableRowAttrs } from "../prosemirror/attrs/index.js";
|
|
6
7
|
import { hasSerializableParagraphPropertyChange, paragraphPropertiesSnapshot } from "../prosemirror/commands/propertyChangeScope.js";
|
|
@@ -34,7 +35,7 @@ import { removeRowsWithoutCellsAfterBatch } from "../prosemirror/tableGridMutati
|
|
|
34
35
|
import { isZeroWidthAnchor } from "../prosemirror/zeroWidthAnchors.js";
|
|
35
36
|
import { getFolioParaIdFromBlockId } from "../types/block-id.js";
|
|
36
37
|
import { CANONICAL_GAP } from "../types/canonicalCapabilities.js";
|
|
37
|
-
import { BatchClaims } from "./batch-claims.js";
|
|
38
|
+
import { BatchClaims, compareBatchTieOrder } from "./batch-claims.js";
|
|
38
39
|
import { stripBlockIdentityAttrs } from "./block-identity.js";
|
|
39
40
|
import { describeCharacterSplit } from "./character-boundaries.js";
|
|
40
41
|
import { buildCleanBlockText, resolveCleanTextRange } from "./clean-text.js";
|
|
@@ -2417,7 +2418,7 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations: reques
|
|
|
2417
2418
|
if (leftCellShape.tablePosition !== rightCellShape.tablePosition) return rightCellShape.tablePosition - leftCellShape.tablePosition;
|
|
2418
2419
|
if (leftCellShape.rectangle.bottom !== rightCellShape.rectangle.bottom) return rightCellShape.rectangle.bottom - leftCellShape.rectangle.bottom;
|
|
2419
2420
|
if (leftCellShape.rectangle.right !== rightCellShape.rectangle.right) return rightCellShape.rectangle.right - leftCellShape.rectangle.right;
|
|
2420
|
-
return
|
|
2421
|
+
return compareBatchTieOrder(left.originalIndex, right.originalIndex);
|
|
2421
2422
|
}
|
|
2422
2423
|
const leftColumn = left.tableColumnInsertion ?? left.tableColumnDeletion;
|
|
2423
2424
|
const rightColumn = right.tableColumnInsertion ?? right.tableColumnDeletion;
|
|
@@ -2428,10 +2429,10 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations: reques
|
|
|
2428
2429
|
if (leftColumn.columnIndex !== rightColumn.columnIndex) return rightColumn.columnIndex - leftColumn.columnIndex;
|
|
2429
2430
|
const leftIsInsertion = left.tableColumnInsertion !== void 0;
|
|
2430
2431
|
if (leftIsInsertion !== (right.tableColumnInsertion !== void 0)) return leftIsInsertion ? -1 : 1;
|
|
2431
|
-
return
|
|
2432
|
+
return compareBatchTieOrder(left.originalIndex, right.originalIndex);
|
|
2432
2433
|
}
|
|
2433
2434
|
if (left.from !== right.from) return right.from - left.from;
|
|
2434
|
-
return
|
|
2435
|
+
return compareBatchTieOrder(left.originalIndex, right.originalIndex);
|
|
2435
2436
|
});
|
|
2436
2437
|
for (let executionIndex = 0; executionIndex < executionOrder.length; executionIndex++) {
|
|
2437
2438
|
const item = executionOrder[executionIndex];
|
|
@@ -3186,9 +3187,21 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations: reques
|
|
|
3186
3187
|
...isPairedMove(item.operation.moveId) && { moveKind: "moveFrom" },
|
|
3187
3188
|
...trackedRevisionExtras
|
|
3188
3189
|
});
|
|
3189
|
-
|
|
3190
|
+
addTrackedDeletionMark({
|
|
3191
|
+
insertionPolicy: "preserve-pending",
|
|
3192
|
+
tr,
|
|
3193
|
+
from: item.from,
|
|
3194
|
+
to: item.to,
|
|
3195
|
+
mark: deletionMark
|
|
3196
|
+
});
|
|
3190
3197
|
const atomRanges = undeletedContentAtomRanges(tr, item.blockFrom);
|
|
3191
|
-
for (const { from, to } of atomRanges)
|
|
3198
|
+
for (const { from, to } of atomRanges) addTrackedDeletionMark({
|
|
3199
|
+
insertionPolicy: "preserve-pending",
|
|
3200
|
+
tr,
|
|
3201
|
+
from,
|
|
3202
|
+
to,
|
|
3203
|
+
mark: deletionMark
|
|
3204
|
+
});
|
|
3192
3205
|
for (const anchorId of textBoxAnchorIdsBetween(tr.doc, tr.mapping.map(item.blockFrom), tr.mapping.map(item.blockTo))) deletedTextBoxAnchorIds.add(anchorId);
|
|
3193
3206
|
encloseWholeControls({
|
|
3194
3207
|
tr,
|
|
@@ -3481,12 +3494,18 @@ const applyFolioAIEditOperationsInternal = ({ view, snapshot, operations: reques
|
|
|
3481
3494
|
appliedRevisionIds = [revisionIdMark];
|
|
3482
3495
|
if (item.to > item.from && deletionType) {
|
|
3483
3496
|
const revisionIdSeparator = operationRevisionSeed++;
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3497
|
+
addTrackedDeletionMark({
|
|
3498
|
+
insertionPolicy: "preserve-pending",
|
|
3499
|
+
tr,
|
|
3500
|
+
from: item.from,
|
|
3501
|
+
to: item.to,
|
|
3502
|
+
mark: deletionType.create({
|
|
3503
|
+
revisionId: revisionIdSeparator,
|
|
3504
|
+
author,
|
|
3505
|
+
date,
|
|
3506
|
+
...trackedRevisionExtras
|
|
3507
|
+
})
|
|
3508
|
+
});
|
|
3490
3509
|
appliedRevisionIds.push(revisionIdSeparator);
|
|
3491
3510
|
}
|
|
3492
3511
|
tr = tr.split(item.from);
|
|
@@ -3982,7 +4001,13 @@ const applyTextReplacement = ({ tr, item, mode, author, date, revisionIdDelete,
|
|
|
3982
4001
|
if (commentMark) nextTr = nextTr.addMark(inserted.start, inserted.end, commentMark);
|
|
3983
4002
|
}
|
|
3984
4003
|
if (item.to > item.from && deletionType) {
|
|
3985
|
-
|
|
4004
|
+
addTrackedDeletionMark({
|
|
4005
|
+
insertionPolicy: "preserve-pending",
|
|
4006
|
+
tr: nextTr,
|
|
4007
|
+
from: item.from,
|
|
4008
|
+
to: item.to,
|
|
4009
|
+
mark: deletionType.create(delAttrs)
|
|
4010
|
+
});
|
|
3986
4011
|
if (commentMark && replacement.length === 0) nextTr = nextTr.addMark(item.from, item.to, commentMark);
|
|
3987
4012
|
}
|
|
3988
4013
|
return nextTr;
|
|
@@ -4474,7 +4499,13 @@ const applyMinimalTrackedReplacement = ({ tr, item, noteReferences, replacement,
|
|
|
4474
4499
|
removedFrom = first.from;
|
|
4475
4500
|
marks = addCarriedMarks(inheritedReplacementMarks(doc, styleSource.from, styleSource.to), surveyReplacedAnnotations(doc, first.from, last.to).carried);
|
|
4476
4501
|
for (const piece of change.pieces) {
|
|
4477
|
-
|
|
4502
|
+
addTrackedDeletionMark({
|
|
4503
|
+
insertionPolicy: "preserve-pending",
|
|
4504
|
+
tr: nextTr,
|
|
4505
|
+
from: piece.from,
|
|
4506
|
+
to: piece.to,
|
|
4507
|
+
mark: deletion
|
|
4508
|
+
});
|
|
4478
4509
|
if (commentMark) nextTr = nextTr.addMark(piece.from, piece.to, commentMark);
|
|
4479
4510
|
}
|
|
4480
4511
|
}
|
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
* Positions are the ones the batch resolved against. A block is keyed by the
|
|
22
22
|
* position before its node.
|
|
23
23
|
*/
|
|
24
|
+
/** Equal snapshot coordinates execute in reverse input order. */
|
|
25
|
+
declare const compareBatchTieOrder: (leftIndex: number, rightIndex: number) => number;
|
|
24
26
|
type PositionRange = {
|
|
25
27
|
from: number;
|
|
26
28
|
to: number;
|
|
@@ -142,4 +144,4 @@ declare class BatchClaims {
|
|
|
142
144
|
add(operationId: string, claim: BatchClaim): void;
|
|
143
145
|
}
|
|
144
146
|
//#endregion
|
|
145
|
-
export { BatchClaim, BatchClaims };
|
|
147
|
+
export { BatchClaim, BatchClaims, compareBatchTieOrder };
|
|
@@ -1,4 +1,28 @@
|
|
|
1
1
|
//#region src/ai-edits/batch-claims.ts
|
|
2
|
+
/**
|
|
3
|
+
* Which operations of one batch may not share their targets.
|
|
4
|
+
*
|
|
5
|
+
* A batch resolves every operation against the document as it was read and
|
|
6
|
+
* applies them from the end of the document backwards, so an operation never
|
|
7
|
+
* moves the positions an earlier-placed one resolved to. That holds only while
|
|
8
|
+
* the operations' targets are disjoint. Two operations on the same stretch of
|
|
9
|
+
* text, or an operation inside a paragraph another one deletes, rewrites,
|
|
10
|
+
* splits or merges away, are applied against coordinates the first one has
|
|
11
|
+
* already invalidated — and the second then edits whatever now sits there,
|
|
12
|
+
* which can be a paragraph neither operation named.
|
|
13
|
+
*
|
|
14
|
+
* Each operation therefore states what it claims before anything is applied,
|
|
15
|
+
* and the later of two operations whose claims conflict is refused
|
|
16
|
+
* (`overlappingOperation`). The caller re-reads the document after the batch
|
|
17
|
+
* and sends the refused operation again against the result. What remains
|
|
18
|
+
* applies exactly as the same operations applied one at a time, from the end
|
|
19
|
+
* of the document backwards, would.
|
|
20
|
+
*
|
|
21
|
+
* Positions are the ones the batch resolved against. A block is keyed by the
|
|
22
|
+
* position before its node.
|
|
23
|
+
*/
|
|
24
|
+
/** Equal snapshot coordinates execute in reverse input order. */
|
|
25
|
+
const compareBatchTieOrder = (leftIndex, rightIndex) => rightIndex - leftIndex;
|
|
2
26
|
const blockRolesOf = (claim) => {
|
|
3
27
|
switch (claim.type) {
|
|
4
28
|
case "text":
|
|
@@ -272,4 +296,4 @@ var BatchClaims = class {
|
|
|
272
296
|
}
|
|
273
297
|
};
|
|
274
298
|
//#endregion
|
|
275
|
-
export { BatchClaims };
|
|
299
|
+
export { BatchClaims, compareBatchTieOrder };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { addTrackedDeletionMark } from "../prosemirror/addTrackedDeletionMark.js";
|
|
1
2
|
import { markStructuralChange } from "../prosemirror/extensions/features/ParagraphChangeTrackerExtension.js";
|
|
2
3
|
import { markRowsEmptiedInBatch, reconcileTableGridAfterColumnInsertion, reconcileTableGridAfterColumnRemoval, removeRowsWithoutCells, removeTableRow } from "../prosemirror/tableGridMutation.js";
|
|
3
4
|
import { stripBlockIdentityAttrs } from "./block-identity.js";
|
|
@@ -130,7 +131,7 @@ const markTableRowContent = ({ tr, rowPosition, kind, revision }) => {
|
|
|
130
131
|
if (!node.isInline) return true;
|
|
131
132
|
if (node.marks.some(isTrackedChangeMark)) {
|
|
132
133
|
wholeRowMarkable = false;
|
|
133
|
-
if (kind === "insertion"
|
|
134
|
+
if (kind === "insertion") return false;
|
|
134
135
|
}
|
|
135
136
|
const from = contentFrom + offset;
|
|
136
137
|
markable.push({
|
|
@@ -140,10 +141,23 @@ const markTableRowContent = ({ tr, rowPosition, kind, revision }) => {
|
|
|
140
141
|
return false;
|
|
141
142
|
});
|
|
142
143
|
if (wholeRowMarkable) {
|
|
143
|
-
|
|
144
|
+
if (kind === "deletion") addTrackedDeletionMark({
|
|
145
|
+
insertionPolicy: "preserve-pending",
|
|
146
|
+
tr,
|
|
147
|
+
from: contentFrom,
|
|
148
|
+
to: rowPosition + row.nodeSize - 1,
|
|
149
|
+
mark
|
|
150
|
+
});
|
|
151
|
+
else tr.addMark(contentFrom, rowPosition + row.nodeSize - 1, mark);
|
|
144
152
|
return;
|
|
145
153
|
}
|
|
146
|
-
for (const range of markable)
|
|
154
|
+
for (const range of markable) if (kind === "deletion") addTrackedDeletionMark({
|
|
155
|
+
insertionPolicy: "preserve-pending",
|
|
156
|
+
tr,
|
|
157
|
+
...range,
|
|
158
|
+
mark
|
|
159
|
+
});
|
|
160
|
+
else tr.addMark(range.from, range.to, mark);
|
|
147
161
|
};
|
|
148
162
|
const isTrackedChangeMark = (mark) => mark.type.name === "insertion" || mark.type.name === "deletion";
|
|
149
163
|
const isRowSpanningCell = (node) => {
|
|
@@ -1,6 +1,19 @@
|
|
|
1
|
+
import { addTrackedDeletionMark } from "../prosemirror/addTrackedDeletionMark.js";
|
|
1
2
|
import { mintRevisionId, seedRevisionIdsFromDoc } from "../prosemirror/plugins/revisionIds.js";
|
|
2
3
|
import { resolveSuggestionAnchor } from "./conflict.js";
|
|
3
4
|
//#region src/ai-suggestions/apply.ts
|
|
5
|
+
/**
|
|
6
|
+
* Apply AI suggestions to the document.
|
|
7
|
+
*
|
|
8
|
+
* Two modes:
|
|
9
|
+
* - "direct": replace text in place.
|
|
10
|
+
* - "tracked-changes": insertion + deletion marks, attributed to the
|
|
11
|
+
* configured author. Reuses the editor's existing tracked-change
|
|
12
|
+
* schema and resolution commands.
|
|
13
|
+
*
|
|
14
|
+
* Apply is always preceded by anchor resolution; stale suggestions are
|
|
15
|
+
* skipped and reported back to the caller.
|
|
16
|
+
*/
|
|
4
17
|
function applySuggestions(options) {
|
|
5
18
|
const { view, suggestions, mode, author } = options;
|
|
6
19
|
const applied = [];
|
|
@@ -51,7 +64,13 @@ function applySuggestions(options) {
|
|
|
51
64
|
tr.insertText(suggestion.suggestedText, to, to);
|
|
52
65
|
tr.addMark(to, to + suggestion.suggestedText.length, insertionType.create(attrs));
|
|
53
66
|
}
|
|
54
|
-
if (to > from)
|
|
67
|
+
if (to > from) addTrackedDeletionMark({
|
|
68
|
+
insertionPolicy: "preserve-pending",
|
|
69
|
+
tr,
|
|
70
|
+
from,
|
|
71
|
+
to,
|
|
72
|
+
mark: deletionType.create(attrs)
|
|
73
|
+
});
|
|
55
74
|
applied.push(suggestion.id);
|
|
56
75
|
}
|
|
57
76
|
}
|
|
@@ -2,7 +2,9 @@ import { buildCleanBlockText } from "../ai-edits/clean-text.js";
|
|
|
2
2
|
import { noteReferenceOf } from "../ai-edits/note-references.js";
|
|
3
3
|
import { collectNoteReferenceLabels, sourceDocumentOf } from "../ai-edits/snapshot.js";
|
|
4
4
|
import { drawingXmlWithoutIdentity } from "../docx/drawingIdNormalization.js";
|
|
5
|
+
import { addTrackedDeletionMark } from "../prosemirror/addTrackedDeletionMark.js";
|
|
5
6
|
import { resolveAllChangesInHeadlessStateWithMapping } from "../prosemirror/commands/comments.js";
|
|
7
|
+
import { mintNoteReferenceOccurrenceId } from "../prosemirror/noteReferenceOccurrences.js";
|
|
6
8
|
import { runFormattingInlineAtomResultText } from "../prosemirror/runFormattingInlineCarriers.js";
|
|
7
9
|
import { canonicalJson } from "../utils/canonicalJson.js";
|
|
8
10
|
import { prepareTargetInlineAtom } from "./inline-atom-resources.js";
|
|
@@ -618,11 +620,17 @@ const matchInlineAtoms = ({ state, targetSnapshot, revisionStamp, originalRevisi
|
|
|
618
620
|
const to = transaction.mapping.map(action.to, -1);
|
|
619
621
|
if (from >= to) return { status: "unalignable" };
|
|
620
622
|
if (action.textDisposition === "inserted") transaction.delete(from, to);
|
|
621
|
-
else
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
623
|
+
else addTrackedDeletionMark({
|
|
624
|
+
insertionPolicy: "preserve-pending",
|
|
625
|
+
tr: transaction,
|
|
626
|
+
from,
|
|
627
|
+
to,
|
|
628
|
+
mark: deletionType.create({
|
|
629
|
+
revisionId: nextRevisionId++,
|
|
630
|
+
author,
|
|
631
|
+
date: revisionStamp.date
|
|
632
|
+
})
|
|
633
|
+
});
|
|
626
634
|
const at = transaction.mapping.map(action.from, -1);
|
|
627
635
|
transaction.insert(at, action.node.mark(insertionType.create({
|
|
628
636
|
revisionId: nextRevisionId++,
|
|
@@ -638,7 +646,11 @@ const matchInlineAtoms = ({ state, targetSnapshot, revisionStamp, originalRevisi
|
|
|
638
646
|
const written = transaction.doc.nodeAt(from);
|
|
639
647
|
const noteMark = action.node.marks.find(({ type }) => type.name === "footnoteRef");
|
|
640
648
|
if (from >= to || !written?.isText || !noteMark) return { status: "unalignable" };
|
|
641
|
-
|
|
649
|
+
const restoredNoteMark = noteMark.type.create({
|
|
650
|
+
...noteMark.attrs,
|
|
651
|
+
occurrenceId: mintNoteReferenceOccurrenceId()
|
|
652
|
+
});
|
|
653
|
+
transaction.replaceWith(from, to, state.schema.text(action.node.text ?? "", restoredNoteMark.addToSet(written.marks)));
|
|
642
654
|
if (action.targetBlockId) changedTargetBlockIds.add(action.targetBlockId);
|
|
643
655
|
continue;
|
|
644
656
|
}
|
|
@@ -648,11 +660,17 @@ const matchInlineAtoms = ({ state, targetSnapshot, revisionStamp, originalRevisi
|
|
|
648
660
|
const node = transaction.doc.nodeAt(from);
|
|
649
661
|
if (!node || node.nodeSize !== to - from || node.type.name !== "field") return { status: "unalignable" };
|
|
650
662
|
if (action.atomDisposition === "inserted") transaction.delete(from, to);
|
|
651
|
-
else
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
663
|
+
else addTrackedDeletionMark({
|
|
664
|
+
insertionPolicy: "preserve-pending",
|
|
665
|
+
tr: transaction,
|
|
666
|
+
from,
|
|
667
|
+
to,
|
|
668
|
+
mark: deletionType.create({
|
|
669
|
+
revisionId: nextRevisionId++,
|
|
670
|
+
author,
|
|
671
|
+
date: revisionStamp.date
|
|
672
|
+
})
|
|
673
|
+
});
|
|
656
674
|
const at = transaction.mapping.map(action.from, -1);
|
|
657
675
|
transaction.insert(at, state.schema.text(action.text, insertionType.create({
|
|
658
676
|
revisionId: nextRevisionId++,
|
|
@@ -675,11 +693,17 @@ const matchInlineAtoms = ({ state, targetSnapshot, revisionStamp, originalRevisi
|
|
|
675
693
|
continue;
|
|
676
694
|
}
|
|
677
695
|
if (node.marks.some(({ type }) => type === deletionType)) return { status: "unalignable" };
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
696
|
+
addTrackedDeletionMark({
|
|
697
|
+
insertionPolicy: "preserve-pending",
|
|
698
|
+
tr: transaction,
|
|
699
|
+
from,
|
|
700
|
+
to,
|
|
701
|
+
mark: deletionType.create({
|
|
702
|
+
revisionId: nextRevisionId++,
|
|
703
|
+
author,
|
|
704
|
+
date: revisionStamp.date
|
|
705
|
+
})
|
|
706
|
+
});
|
|
683
707
|
if (action.targetBlockId) changedTargetBlockIds.add(action.targetBlockId);
|
|
684
708
|
}
|
|
685
709
|
return {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { sourceDocumentOf, styleResolverOf } from "../ai-edits/snapshot.js";
|
|
2
|
+
import { addTrackedDeletionMark } from "../prosemirror/addTrackedDeletionMark.js";
|
|
2
3
|
import { expectHyperlinkMarkAttrs, expectRunPropertyChangeMarkAttrs, expectTableCellAttrs } from "../prosemirror/attrs/index.js";
|
|
3
4
|
import { getDocumentStyleResolver } from "../prosemirror/plugins/documentStyleState.js";
|
|
4
5
|
import { applyMarksToRunFormattingRepresentation, expandRunFormattingCarrier, runFormattingCarrierReviewText } from "../prosemirror/runFormattingInlineCarriers.js";
|
|
@@ -252,11 +253,17 @@ const matchInlineProvenance = ({ state, targetSnapshot, revisionStamp, originalR
|
|
|
252
253
|
date: revisionStamp.date
|
|
253
254
|
}).addToSet(marks);
|
|
254
255
|
const text = state.doc.textBetween(change.live.from, change.live.to);
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
256
|
+
addTrackedDeletionMark({
|
|
257
|
+
insertionPolicy: "preserve-pending",
|
|
258
|
+
tr: transaction,
|
|
259
|
+
from: change.live.from,
|
|
260
|
+
to: change.live.to,
|
|
261
|
+
mark: deletionType.create({
|
|
262
|
+
revisionId: nextRevisionId++,
|
|
263
|
+
author,
|
|
264
|
+
date: revisionStamp.date
|
|
265
|
+
})
|
|
266
|
+
});
|
|
260
267
|
transaction.insert(change.live.to, state.schema.text(text, marks));
|
|
261
268
|
changedTargetBlockIds.add(change.targetBlockId);
|
|
262
269
|
continue;
|
|
@@ -17,6 +17,7 @@ import { MAX_COMPARE_OPERATIONS, compareDocx } from "../compare/compare.js";
|
|
|
17
17
|
import { DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DocumentPreset, DocumentStyleSet } from "../style-sets/types.js";
|
|
18
18
|
import { CreateEmptyDocumentOptions, createEmptyDocument } from "../utils/createDocument.js";
|
|
19
19
|
import { mergeDocumentContent } from "../utils/mergeDocumentContent.js";
|
|
20
|
+
import { DEFAULT_OUTLINE_DEPTH, OutlineDepth, filterHeadingsByDepth } from "../utils/outlineDepth.js";
|
|
20
21
|
import { DocumentStyleCatalog, DocumentStyleCatalogEntry, ExtractDocumentStyleSetOptions, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, inspectDocumentStyles, inspectDocumentStylesFromDocx } from "../style-sets/extract.js";
|
|
21
22
|
import { STELLA_STYLE_SET_NAME, createStellaStyleDocumentPreset, createStellaStyleSet } from "../style-sets/stellaStyle.js";
|
|
22
23
|
import { DocumentPropertiesOptions, createDocx } from "../docx/rezip.js";
|
|
@@ -41,4 +42,4 @@ import { FOLIO_YJS_ATTR_SCHEMA_VERSION, FolioYjsAttrSchemaVersion, FolioYjsAttrS
|
|
|
41
42
|
import { DOCX_CONFORMANCE_CLASSES } from "../index.js";
|
|
42
43
|
type Document = document_d_exports.Document;
|
|
43
44
|
type DocxConformanceClass = document_d_exports.DocxConformanceClass;
|
|
44
|
-
export { type AIBarStatus, type AIChatMode, type AICitation, type AICitationRange, type AICitationSource, type AIGenerateInput, type AISuggestion, type AISuggestionApplyMode, type AISuggestionPreset, type AISuggestionSeverity, type AISuggestionStatus, type AcceptAutocompleteResult, type AnonymizationMatch, type AnonymizationTerm, type ApplyFolioDocumentOperationsOptions, type ApplyResult, type AutocompleteSuggestionPluginOptions, type AutocompleteSuggestionState, type AutocompleteSuggestionStatus, type AutocompleteTriggerCheck, type AutocompleteTriggerOptions, type AutocompleteTriggerSkipReason, type BlockRect, COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, type CompareChange, type CompareChangeLocation, type CompareCompatibility, type CompareContentOptions, CompareDocxApplyError, type CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, type CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, type CompareFolioRequirement, type CompareResult, type CompareRevisionFormat, type CompareUnsupportedPart, type CompareUnsupportedReason, type CompareVerification, type CompareVerificationCause, type CompareVerificationFailure, type CompareVerificationInvariant, type CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, DRAWING_SAFETY_CLASSES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocumentPreset, type DocumentPropertiesOptions, type DocumentStyleCatalog, type DocumentStyleCatalogEntry, type DocumentStyleSet, type DocxCompatibility, type DocxCompatibilityContext, type DocxCompatibilityIssue, type DocxCompatibilityLocation, type DocxCompatibilityPart, type DocxConformanceClass, type DocxDrawingClassification, type DrawingSafetyClass, type EmbeddedFont, type EmbeddedFontParts, type ExtractDocumentStyleSetOptions, FOLIO_CONTENT_COMPARISON_LIMITS, 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_YJS_ATTR_SCHEMA_VERSION, type FinalParagraphMarkRevision, 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 FolioAIInlineBooleanProperty, type FolioAIInlineFormatting, type FolioAIInlineFormattingPatch, type FolioAIParagraphSpacing, type FolioAISignatureParty, type FolioBlockId, type FolioContentBlock, type FolioContentBlockProperty, type FolioContentComparison, type FolioContentComparisonError, type FolioContentComparisonEvent, type FolioContentComparisonLimit, FolioContentComparisonLimitError, type FolioContentContainerPathEntry, type FolioContentFormatRange, type FolioContentFormattingChange, type FolioContentIdStability, type FolioContentInlineBooleanProperty, type FolioContentInlineComparisonResult, type FolioContentInlineFormatting, type FolioContentInlineFormattingPatch, FolioContentInlinePresentationProjectionError, type FolioContentLineSpacingRule, type FolioContentParagraphAlignment, type FolioContentParagraphFormattingPatch, type FolioContentParagraphKind, type FolioContentParagraphSpacing, type FolioContentRun, type FolioContentSnapshot, type FolioContentStructuralChange, type FolioContentTableLocation, type FolioContentTextSegment, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationResultBase, type FolioDocumentOperationStatus, type FolioDocumentOperationStory, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocxCompatibilityHost, type FolioDocxCompatibilityProfile, type FolioRevisionStamp, type FolioWordDiffOptions, type FolioYjsAttrSchemaVersion, FolioYjsAttrSchemaVersionError, type ImageMeta, type ImageRef, type InspectDocxCompatibilityOptions, InvalidCompareDocxOptionsError, InvalidFolioContentComparisonError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, type MarkdownOptions, type MarkdownResult, type PositionalText, type ResolvedAnchor, STELLA_STYLE_SET_NAME, type TemplatePreviewHiddenRange, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, type WordDiffGranularity, type WordDiffNormalization, type WordDiffOptions, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareContent, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
|
|
45
|
+
export { type AIBarStatus, type AIChatMode, type AICitation, type AICitationRange, type AICitationSource, type AIGenerateInput, type AISuggestion, type AISuggestionApplyMode, type AISuggestionPreset, type AISuggestionSeverity, type AISuggestionStatus, type AcceptAutocompleteResult, type AnonymizationMatch, type AnonymizationTerm, type ApplyFolioDocumentOperationsOptions, type ApplyResult, type AutocompleteSuggestionPluginOptions, type AutocompleteSuggestionState, type AutocompleteSuggestionStatus, type AutocompleteTriggerCheck, type AutocompleteTriggerOptions, type AutocompleteTriggerSkipReason, type BlockRect, COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, type CompareChange, type CompareChangeLocation, type CompareCompatibility, type CompareContentOptions, CompareDocxApplyError, type CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, type CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, type CompareFolioRequirement, type CompareResult, type CompareRevisionFormat, type CompareUnsupportedPart, type CompareUnsupportedReason, type CompareVerification, type CompareVerificationCause, type CompareVerificationFailure, type CompareVerificationInvariant, type CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DEFAULT_OUTLINE_DEPTH, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, DRAWING_SAFETY_CLASSES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocumentPreset, type DocumentPropertiesOptions, type DocumentStyleCatalog, type DocumentStyleCatalogEntry, type DocumentStyleSet, type DocxCompatibility, type DocxCompatibilityContext, type DocxCompatibilityIssue, type DocxCompatibilityLocation, type DocxCompatibilityPart, type DocxConformanceClass, type DocxDrawingClassification, type DrawingSafetyClass, type EmbeddedFont, type EmbeddedFontParts, type ExtractDocumentStyleSetOptions, FOLIO_CONTENT_COMPARISON_LIMITS, 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_YJS_ATTR_SCHEMA_VERSION, type FinalParagraphMarkRevision, 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 FolioAIInlineBooleanProperty, type FolioAIInlineFormatting, type FolioAIInlineFormattingPatch, type FolioAIParagraphSpacing, type FolioAISignatureParty, type FolioBlockId, type FolioContentBlock, type FolioContentBlockProperty, type FolioContentComparison, type FolioContentComparisonError, type FolioContentComparisonEvent, type FolioContentComparisonLimit, FolioContentComparisonLimitError, type FolioContentContainerPathEntry, type FolioContentFormatRange, type FolioContentFormattingChange, type FolioContentIdStability, type FolioContentInlineBooleanProperty, type FolioContentInlineComparisonResult, type FolioContentInlineFormatting, type FolioContentInlineFormattingPatch, FolioContentInlinePresentationProjectionError, type FolioContentLineSpacingRule, type FolioContentParagraphAlignment, type FolioContentParagraphFormattingPatch, type FolioContentParagraphKind, type FolioContentParagraphSpacing, type FolioContentRun, type FolioContentSnapshot, type FolioContentStructuralChange, type FolioContentTableLocation, type FolioContentTextSegment, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationResultBase, type FolioDocumentOperationStatus, type FolioDocumentOperationStory, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocxCompatibilityHost, type FolioDocxCompatibilityProfile, type FolioRevisionStamp, type FolioWordDiffOptions, type FolioYjsAttrSchemaVersion, FolioYjsAttrSchemaVersionError, type ImageMeta, type ImageRef, type InspectDocxCompatibilityOptions, InvalidCompareDocxOptionsError, InvalidFolioContentComparisonError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, type MarkdownOptions, type MarkdownResult, type OutlineDepth, type PositionalText, type ResolvedAnchor, STELLA_STYLE_SET_NAME, type TemplatePreviewHiddenRange, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, type WordDiffGranularity, type WordDiffNormalization, type WordDiffOptions, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareContent, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, filterHeadingsByDepth, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
|
package/dist/compat/eigenpal.js
CHANGED
|
@@ -34,4 +34,5 @@ import { currentFolioBlockId, deriveBlockId, getFolioParaIdFromBlockId, isFolioB
|
|
|
34
34
|
import { createEmptyDocument } from "../utils/createDocument.js";
|
|
35
35
|
import { getGoogleFontsEnabled, setEmbeddedFontFamilyMap, setGoogleFontsEnabled } from "../utils/fontResolver.js";
|
|
36
36
|
import { mergeDocumentContent } from "../utils/mergeDocumentContent.js";
|
|
37
|
-
|
|
37
|
+
import { DEFAULT_OUTLINE_DEPTH, filterHeadingsByDepth } from "../utils/outlineDepth.js";
|
|
38
|
+
export { COMPARE_REVISION_FORMATS, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, CompareDocxApplyError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DEFAULT_OUTLINE_DEPTH, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, DRAWING_SAFETY_CLASSES, FOLIO_CONTENT_COMPARISON_LIMITS, 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_YJS_ATTR_SCHEMA_VERSION, FolioContentComparisonLimitError, FolioContentInlinePresentationProjectionError, FolioYjsAttrSchemaVersionError, InvalidCompareDocxOptionsError, InvalidFolioContentComparisonError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, STELLA_STYLE_SET_NAME, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareContent, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, filterHeadingsByDepth, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createNumberingIdAllocator } from "../docx/numberingIds.js";
|
|
2
|
+
import { copyParagraphIndentationProjection } from "../docx/paragraphPropertySource.js";
|
|
2
3
|
import { visitInlineContentSlots, visitParagraphRuns } from "../docx/paragraphTraversal.js";
|
|
3
4
|
import { captureVerbatimXml } from "../docx/verbatimCapture.js";
|
|
4
5
|
import { OFFICE_RELATIONSHIP_NAMESPACE_URIS, OOXML_NAMESPACE_SCOPE, findAttributeByNamespaceUri, getLocalName, parseXml } from "../docx/xmlParser.js";
|
|
@@ -203,7 +204,12 @@ const prepareCanonicalPaste = ({ session, state, slice, plain = false, moveTarge
|
|
|
203
204
|
const paragraphs = [];
|
|
204
205
|
for (const block of converted.value) {
|
|
205
206
|
if (block.type !== "paragraph") return refuse("The clipboard contains an unsupported block.");
|
|
206
|
-
|
|
207
|
+
const paragraph = structuredClone(block);
|
|
208
|
+
copyParagraphIndentationProjection({
|
|
209
|
+
target: paragraph,
|
|
210
|
+
source: block
|
|
211
|
+
});
|
|
212
|
+
paragraphs.push(paragraph);
|
|
207
213
|
}
|
|
208
214
|
if (moveTarget === void 0 && (plain || sourceDocument === void 0)) flattenClipboardStyleReferences(paragraphs);
|
|
209
215
|
const from = session.projection.addressAt(pasteTarget ?? moveSource?.from ?? state.selection.from);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { CANONICAL_GAP } from "../types/canonicalCapabilities.js";
|
|
3
|
+
import { Comment } from "../types/content.js";
|
|
4
|
+
import { CreateCommentOp, DocumentOp } from "@stll/docx-core/ops";
|
|
5
|
+
//#region src/controller/canonicalComments.d.ts
|
|
6
|
+
declare const CanonicalCommentError_base: import("better-result").TaggedErrorClass<"CanonicalCommentError">;
|
|
7
|
+
declare class CanonicalCommentError extends CanonicalCommentError_base<{
|
|
8
|
+
message: string;
|
|
9
|
+
gap: typeof CANONICAL_GAP.comments;
|
|
10
|
+
}> {}
|
|
11
|
+
type CanonicalCommentCommand = {
|
|
12
|
+
type: "create";
|
|
13
|
+
comment: CreateCommentOp["comment"];
|
|
14
|
+
anchor: CreateCommentOp["anchor"];
|
|
15
|
+
} | {
|
|
16
|
+
type: "update";
|
|
17
|
+
id: number;
|
|
18
|
+
content: Comment["content"];
|
|
19
|
+
} | {
|
|
20
|
+
type: "resolve";
|
|
21
|
+
id: number;
|
|
22
|
+
status: "open" | "resolved";
|
|
23
|
+
} | {
|
|
24
|
+
type: "delete";
|
|
25
|
+
id: number;
|
|
26
|
+
} | {
|
|
27
|
+
type: "replace";
|
|
28
|
+
comments: readonly Comment[];
|
|
29
|
+
};
|
|
30
|
+
type CompileCanonicalCommentsOptions = {
|
|
31
|
+
document: document_d_exports.Document;
|
|
32
|
+
command: CanonicalCommentCommand;
|
|
33
|
+
};
|
|
34
|
+
declare const compileCanonicalComments: ({ document, command }: CompileCanonicalCommentsOptions) => import("better-result").Err<never, CanonicalCommentError> | import("better-result").Ok<{
|
|
35
|
+
ops: DocumentOp[];
|
|
36
|
+
document: document_d_exports.Document;
|
|
37
|
+
commentId: number | undefined;
|
|
38
|
+
}, never>;
|
|
39
|
+
declare const canonicalCommentBody: (document: document_d_exports.Document, text: string) => Comment["content"];
|
|
40
|
+
//#endregion
|
|
41
|
+
export { CanonicalCommentCommand, CanonicalCommentError, canonicalCommentBody, compileCanonicalComments };
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { CANONICAL_GAP } from "../types/canonicalCapabilities.js";
|
|
2
|
+
import { canonicalJson } from "../utils/canonicalJson.js";
|
|
3
|
+
import { Result, TaggedError } from "better-result";
|
|
4
|
+
import { DOCUMENT_OP_TYPES, allocateCommentAnchorIds, applyDocumentOps, packageParagraphIds } from "@stll/docx-core/ops";
|
|
5
|
+
//#region src/controller/canonicalComments.ts
|
|
6
|
+
/** The one semantic compiler for canonical sidebar, controlled and public comments. */
|
|
7
|
+
var CanonicalCommentError = class extends TaggedError("CanonicalCommentError") {};
|
|
8
|
+
const refuse = (message) => Result.err(new CanonicalCommentError({
|
|
9
|
+
message,
|
|
10
|
+
gap: CANONICAL_GAP.comments
|
|
11
|
+
}));
|
|
12
|
+
const compileCanonicalComments = ({ document, command }) => {
|
|
13
|
+
const current = document.package.document.comments ?? [];
|
|
14
|
+
const byId = new Map(current.map((comment) => [comment.id, comment]));
|
|
15
|
+
const ops = [];
|
|
16
|
+
let commentId;
|
|
17
|
+
switch (command.type) {
|
|
18
|
+
case "create":
|
|
19
|
+
ops.push({
|
|
20
|
+
type: DOCUMENT_OP_TYPES.CREATE_COMMENT,
|
|
21
|
+
comment: command.comment,
|
|
22
|
+
anchor: command.anchor
|
|
23
|
+
});
|
|
24
|
+
commentId = command.comment.id;
|
|
25
|
+
break;
|
|
26
|
+
case "update":
|
|
27
|
+
ops.push({
|
|
28
|
+
type: DOCUMENT_OP_TYPES.UPDATE_COMMENT_CONTENT,
|
|
29
|
+
id: command.id,
|
|
30
|
+
content: command.content
|
|
31
|
+
});
|
|
32
|
+
break;
|
|
33
|
+
case "resolve":
|
|
34
|
+
ops.push({
|
|
35
|
+
type: DOCUMENT_OP_TYPES.SET_COMMENT_RESOLUTION,
|
|
36
|
+
id: command.id,
|
|
37
|
+
status: command.status
|
|
38
|
+
});
|
|
39
|
+
break;
|
|
40
|
+
case "delete": {
|
|
41
|
+
const comment = byId.get(command.id);
|
|
42
|
+
if (!comment) return refuse("The comment no longer exists.");
|
|
43
|
+
ops.push({
|
|
44
|
+
type: DOCUMENT_OP_TYPES.DELETE_COMMENT,
|
|
45
|
+
id: command.id,
|
|
46
|
+
scope: comment.parentId !== void 0 && byId.has(comment.parentId) ? "reply" : "thread"
|
|
47
|
+
});
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
case "replace": {
|
|
51
|
+
const nextById = new Map(command.comments.map((comment) => [comment.id, comment]));
|
|
52
|
+
if (nextById.size !== command.comments.length) return refuse("Comment ids must be unique.");
|
|
53
|
+
for (const comment of current) {
|
|
54
|
+
if (nextById.has(comment.id) && comment.parentId !== void 0 && byId.has(comment.parentId) && !nextById.has(comment.parentId)) return refuse("A retained reply requires its parent thread.");
|
|
55
|
+
if (nextById.has(comment.id)) continue;
|
|
56
|
+
if (comment.parentId !== void 0 && !nextById.has(comment.parentId) && byId.has(comment.parentId)) continue;
|
|
57
|
+
ops.push({
|
|
58
|
+
type: DOCUMENT_OP_TYPES.DELETE_COMMENT,
|
|
59
|
+
id: comment.id,
|
|
60
|
+
scope: comment.parentId !== void 0 && byId.has(comment.parentId) ? "reply" : "thread"
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
const pending = command.comments.filter((comment) => !byId.has(comment.id));
|
|
64
|
+
const available = new Set(current.filter((comment) => nextById.has(comment.id)).map((comment) => comment.id));
|
|
65
|
+
while (pending.length > 0) {
|
|
66
|
+
const index = pending.findIndex((comment) => comment.parentId !== void 0 && available.has(comment.parentId));
|
|
67
|
+
if (index < 0) return refuse("New controlled comments require an existing anchored parent without cycles.");
|
|
68
|
+
const next = pending.splice(index, 1).at(0);
|
|
69
|
+
if (next === void 0 || next.parentId === void 0) return refuse("The controlled reply is missing its parent.");
|
|
70
|
+
const { parentId, ...comment } = next;
|
|
71
|
+
ops.push({
|
|
72
|
+
type: DOCUMENT_OP_TYPES.CREATE_COMMENT,
|
|
73
|
+
comment,
|
|
74
|
+
anchor: {
|
|
75
|
+
kind: "reply",
|
|
76
|
+
parentId
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
available.add(next.id);
|
|
80
|
+
}
|
|
81
|
+
for (const next of command.comments) {
|
|
82
|
+
const previous = byId.get(next.id);
|
|
83
|
+
if (!previous) continue;
|
|
84
|
+
const { content: priorContent, done: priorDone, author: priorAuthor, initials: priorInitials, date: priorDate, ...priorMetadata } = previous;
|
|
85
|
+
const { content: nextContent, done: nextDone, author: nextAuthor, initials: nextInitials, date: nextDate, ...nextMetadata } = next;
|
|
86
|
+
if (canonicalJson(priorMetadata) !== canonicalJson(nextMetadata)) return refuse("Controlled comment identity and opaque metadata cannot be replaced.");
|
|
87
|
+
const patch = {
|
|
88
|
+
...priorAuthor === nextAuthor ? {} : { author: nextAuthor },
|
|
89
|
+
...priorInitials === nextInitials ? {} : { initials: Object.hasOwn(next, "initials") ? nextInitials : null },
|
|
90
|
+
...priorDate === nextDate ? {} : { date: Object.hasOwn(next, "date") ? nextDate : null }
|
|
91
|
+
};
|
|
92
|
+
if (canonicalJson(priorContent) !== canonicalJson(nextContent) || Object.keys(patch).length > 0) ops.push({
|
|
93
|
+
type: DOCUMENT_OP_TYPES.UPDATE_COMMENT_CONTENT,
|
|
94
|
+
id: next.id,
|
|
95
|
+
content: nextContent,
|
|
96
|
+
patch
|
|
97
|
+
});
|
|
98
|
+
if (priorDone !== nextDone) {
|
|
99
|
+
if (nextDone === void 0) return refuse("Resolution changes must name an open or resolved state.");
|
|
100
|
+
ops.push({
|
|
101
|
+
type: DOCUMENT_OP_TYPES.SET_COMMENT_RESOLUTION,
|
|
102
|
+
id: next.id,
|
|
103
|
+
status: nextDone ? "resolved" : "open"
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
default: return command;
|
|
110
|
+
}
|
|
111
|
+
const compiled = [];
|
|
112
|
+
let draft = document;
|
|
113
|
+
for (const op of ops) {
|
|
114
|
+
const materialized = (() => {
|
|
115
|
+
if (op.type !== DOCUMENT_OP_TYPES.CREATE_COMMENT) return Result.ok(op);
|
|
116
|
+
const allocation = allocateCommentAnchorIds(draft, op);
|
|
117
|
+
if (allocation.isErr()) return Result.err(allocation.error);
|
|
118
|
+
return Result.ok({
|
|
119
|
+
...op,
|
|
120
|
+
newIds: allocation.value
|
|
121
|
+
});
|
|
122
|
+
})();
|
|
123
|
+
if (materialized.isErr()) return refuse(materialized.error.message);
|
|
124
|
+
const applied = applyDocumentOps(draft, [materialized.value]);
|
|
125
|
+
if (applied.isErr()) return refuse(applied.error.message);
|
|
126
|
+
compiled.push(materialized.value);
|
|
127
|
+
draft = applied.value.document;
|
|
128
|
+
}
|
|
129
|
+
return Result.ok({
|
|
130
|
+
ops: compiled,
|
|
131
|
+
document: draft,
|
|
132
|
+
commentId
|
|
133
|
+
});
|
|
134
|
+
};
|
|
135
|
+
const canonicalCommentBody = (document, text) => {
|
|
136
|
+
const occupied = new Set(packageParagraphIds(document.package).map((id) => id.toUpperCase()));
|
|
137
|
+
let id = 1;
|
|
138
|
+
while (occupied.has(id.toString(16).padStart(8, "0").toUpperCase())) id += 1;
|
|
139
|
+
return [{
|
|
140
|
+
type: "paragraph",
|
|
141
|
+
paraId: id.toString(16).padStart(8, "0").toUpperCase(),
|
|
142
|
+
content: [{
|
|
143
|
+
type: "run",
|
|
144
|
+
content: [{
|
|
145
|
+
type: "text",
|
|
146
|
+
text
|
|
147
|
+
}]
|
|
148
|
+
}]
|
|
149
|
+
}];
|
|
150
|
+
};
|
|
151
|
+
//#endregion
|
|
152
|
+
export { CanonicalCommentError, canonicalCommentBody, compileCanonicalComments };
|