@stll/folio-core 0.32.2 → 0.33.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-edits/__fixtures__/paragraphs.d.ts +17 -0
- package/dist/ai-edits/__fixtures__/paragraphs.js +33 -0
- package/dist/ai-edits/apply.d.ts +49 -3
- package/dist/ai-edits/apply.js +652 -86
- package/dist/ai-edits/blockRange.d.ts +7 -3
- package/dist/ai-edits/blockRange.js +14 -6
- package/dist/ai-edits/headless.d.ts +39 -5
- package/dist/ai-edits/headless.js +76 -17
- package/dist/ai-edits/index.d.ts +6 -6
- package/dist/ai-edits/index.js +3 -3
- package/dist/ai-edits/read.d.ts +4 -0
- package/dist/ai-edits/read.js +30 -6
- package/dist/ai-edits/scoped-reading.js +4 -3
- package/dist/ai-edits/snapshot.d.ts +42 -2
- package/dist/ai-edits/snapshot.js +127 -62
- package/dist/ai-edits/table-row-column-mutations.d.ts +24 -1
- package/dist/ai-edits/table-row-column-mutations.js +98 -6
- package/dist/ai-edits/table-targets.d.ts +12 -3
- package/dist/ai-edits/table-targets.js +15 -5
- package/dist/ai-edits/types.d.ts +219 -15
- package/dist/ai-edits/word-diff.d.ts +54 -11
- package/dist/ai-edits/word-diff.js +221 -61
- package/dist/compare/__fixtures__/body-sequence.d.ts +56 -0
- package/dist/compare/__fixtures__/body-sequence.js +136 -0
- package/dist/compare/__fixtures__/nested-table.d.ts +16 -0
- package/dist/compare/__fixtures__/nested-table.js +50 -0
- package/dist/compare/__fixtures__/numbered-list.d.ts +34 -0
- package/dist/compare/__fixtures__/numbered-list.js +85 -0
- package/dist/compare/column-alignment.d.ts +27 -0
- package/dist/compare/column-alignment.js +162 -0
- package/dist/compare/compare.d.ts +107 -0
- package/dist/compare/compare.js +412 -0
- package/dist/compare/formatting.d.ts +29 -0
- package/dist/compare/formatting.js +84 -0
- package/dist/compare/plan.d.ts +22 -0
- package/dist/compare/plan.js +1141 -0
- package/dist/compare/reproducible-package.d.ts +21 -0
- package/dist/compare/reproducible-package.js +47 -0
- package/dist/compare/scenario.d.ts +77 -0
- package/dist/compare/scenario.js +263 -0
- package/dist/compare/types.d.ts +297 -0
- package/dist/compare/types.js +42 -0
- package/dist/compare/verification.d.ts +83 -0
- package/dist/compare/verification.js +189 -0
- package/dist/compat/eigenpal.d.ts +9 -6
- package/dist/compat/eigenpal.js +6 -3
- package/dist/controller/layoutPipeline.d.ts +13 -0
- package/dist/controller/layoutPipeline.js +15 -1
- package/dist/display-list/build/buildContext.d.ts +39 -0
- package/dist/display-list/build/buildContext.js +31 -0
- package/dist/display-list/build/buildDisplayList.d.ts +79 -0
- package/dist/display-list/build/buildDisplayList.js +283 -0
- package/dist/display-list/build/colors.d.ts +20 -0
- package/dist/display-list/build/colors.js +136 -0
- package/dist/display-list/build/floatingImages.d.ts +24 -0
- package/dist/display-list/build/floatingImages.js +41 -0
- package/dist/display-list/build/fontTable.d.ts +31 -0
- package/dist/display-list/build/fontTable.js +97 -0
- package/dist/display-list/build/furniture.d.ts +86 -0
- package/dist/display-list/build/furniture.js +98 -0
- package/dist/display-list/build/glyphs.d.ts +55 -0
- package/dist/display-list/build/glyphs.js +103 -0
- package/dist/display-list/build/headerFooterPrimitives.d.ts +17 -0
- package/dist/display-list/build/headerFooterPrimitives.js +40 -0
- package/dist/display-list/build/imagePrimitives.d.ts +35 -0
- package/dist/display-list/build/imagePrimitives.js +264 -0
- package/dist/display-list/build/pageBorderPrimitives.d.ts +23 -0
- package/dist/display-list/build/pageBorderPrimitives.js +111 -0
- package/dist/display-list/build/pageFurniture.d.ts +35 -0
- package/dist/display-list/build/pageFurniture.js +141 -0
- package/dist/display-list/build/paragraphPrimitives.d.ts +19 -0
- package/dist/display-list/build/paragraphPrimitives.js +819 -0
- package/dist/display-list/build/regions.d.ts +46 -0
- package/dist/display-list/build/regions.js +56 -0
- package/dist/display-list/build/storyPrimitives.d.ts +29 -0
- package/dist/display-list/build/storyPrimitives.js +279 -0
- package/dist/display-list/build/strokes.d.ts +19 -0
- package/dist/display-list/build/strokes.js +78 -0
- package/dist/display-list/build/tablePrimitives.d.ts +38 -0
- package/dist/display-list/build/tablePrimitives.js +409 -0
- package/dist/display-list/build/textBoxPrimitives.d.ts +14 -0
- package/dist/display-list/build/textBoxPrimitives.js +129 -0
- package/dist/display-list/build/textDecorations.d.ts +29 -0
- package/dist/display-list/build/textDecorations.js +29 -0
- package/dist/display-list/build/unsupported.d.ts +57 -0
- package/dist/display-list/build/unsupported.js +0 -0
- package/dist/display-list/build/watermarkPrimitives.d.ts +15 -0
- package/dist/display-list/build/watermarkPrimitives.js +128 -0
- package/dist/display-list/dom/renderDisplayListToDom.d.ts +26 -0
- package/dist/display-list/dom/renderDisplayListToDom.js +620 -0
- package/dist/display-list/editor/displayListPagePainter.d.ts +22 -0
- package/dist/display-list/editor/displayListPagePainter.js +63 -0
- package/dist/display-list/editor/pageRenderer.d.ts +24 -0
- package/dist/display-list/editor/pageRenderer.js +36 -0
- package/dist/display-list/primitives.d.ts +95 -0
- package/dist/display-list/primitives.js +127 -0
- package/dist/display-list/types.d.ts +472 -0
- package/dist/display-list/types.js +0 -0
- package/dist/document-operations.d.ts +39 -8
- package/dist/document-operations.js +169 -16
- package/dist/document-stories.d.ts +16 -0
- package/dist/document-stories.js +48 -4
- package/dist/docx/hyperlinkParser.d.ts +9 -1
- package/dist/docx/hyperlinkParser.js +19 -13
- package/dist/docx/packageParts.d.ts +35 -0
- package/dist/docx/packageParts.js +120 -0
- package/dist/docx/paraIdRangeNormalization.d.ts +40 -0
- package/dist/docx/paraIdRangeNormalization.js +64 -0
- package/dist/docx/paragraphParser.js +101 -26
- package/dist/docx/paragraphTraversal.js +1 -1
- package/dist/docx/renderedPageBreakNormalization.js +3 -1
- package/dist/docx/revisionIdNormalization.d.ts +27 -0
- package/dist/docx/revisionIdNormalization.js +121 -0
- package/dist/docx/rezip.d.ts +6 -0
- package/dist/docx/rezip.js +51 -19
- package/dist/docx/selectiveSave.js +2 -2
- package/dist/docx/serializer/commentSerializer.js +6 -1
- package/dist/docx/serializer/paragraphSerializer.js +73 -20
- package/dist/docx/serializer/runSerializer.js +11 -10
- package/dist/docx/serializer/tableSerializer.js +26 -10
- package/dist/docx/server/applyDocxXmlPatchProposal.js +1 -1
- package/dist/docx/server/createBilingualDocx.js +3 -2
- package/dist/docx/streamingXmlParser.d.ts +13 -1
- package/dist/docx/streamingXmlParser.js +49 -11
- package/dist/docx/unzip.d.ts +1 -2
- package/dist/docx/unzip.js +25 -6
- package/dist/docx/xmlParser.d.ts +3 -1
- package/dist/docx/xmlParser.js +33 -27
- package/dist/export-pdf.d.ts +43 -0
- package/dist/export-pdf.js +98 -0
- package/dist/fonts/headlessMeasure.d.ts +76 -0
- package/dist/fonts/headlessMeasure.js +0 -0
- package/dist/fonts/sfnt/parse.d.ts +51 -0
- package/dist/fonts/sfnt/parse.js +525 -0
- package/dist/fonts/sfnt/subset.d.ts +20 -0
- package/dist/fonts/sfnt/subset.js +350 -0
- package/dist/fonts/sfnt/tables.d.ts +88 -0
- package/dist/fonts/sfnt/tables.js +131 -0
- package/dist/fonts/sfnt/woff.d.ts +14 -0
- package/dist/fonts/sfnt/woff.js +163 -0
- package/dist/generated/text_shaper.js +324 -0
- package/dist/generated/text_shaper_bg.wasm +0 -0
- package/dist/headless-layout.d.ts +75 -0
- package/dist/headless-layout.js +350 -0
- package/dist/index.d.ts +9 -6
- package/dist/index.js +6 -3
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +2 -0
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +3 -1
- package/dist/layout-bridge/convert/toFlowBlocks.js +2 -0
- package/dist/layout-engine/measure/advanceComposition.d.ts +62 -0
- package/dist/layout-engine/measure/advanceComposition.js +148 -0
- package/dist/layout-engine/measure/cache.d.ts +2 -0
- package/dist/layout-engine/measure/measureContainer.js +13 -0
- package/dist/layout-engine/measure/measureParagraph.js +1 -2
- package/dist/layout-engine/measure/measureTypes.d.ts +12 -0
- package/dist/layout-engine/measure/tableInlinePlacement.d.ts +3 -2
- package/dist/layout-engine/measure/tableInlinePlacement.js +14 -1
- package/dist/layout-engine/tableIndentCompatibility.d.ts +5 -0
- package/dist/layout-engine/tableIndentCompatibility.js +15 -0
- package/dist/layout-engine/types.d.ts +8 -0
- package/dist/layout-painter/renderPage.d.ts +29 -1
- package/dist/layout-painter/renderPage.js +47 -19
- package/dist/layout-painter/renderParagraph.d.ts +21 -2
- package/dist/layout-painter/renderParagraph.js +1 -1
- package/dist/layout-painter/renderTable.js +37 -4
- package/dist/managers/editorShortcuts.d.ts +33 -1
- package/dist/managers/editorShortcuts.js +20 -1
- package/dist/markdown/renderRuns.js +7 -2
- package/dist/markdown/renderTable.js +5 -1
- package/dist/model.d.ts +3 -3
- package/dist/model.js +2 -2
- package/dist/pdf/contentStream.d.ts +73 -0
- package/dist/pdf/contentStream.js +143 -0
- package/dist/pdf/fonts.d.ts +96 -0
- package/dist/pdf/fonts.js +593 -0
- package/dist/pdf/images.d.ts +28 -0
- package/dist/pdf/images.js +439 -0
- package/dist/pdf/objects.d.ts +93 -0
- package/dist/pdf/objects.js +237 -0
- package/dist/pdf/pageSpace.d.ts +43 -0
- package/dist/pdf/pageSpace.js +57 -0
- package/dist/pdf/paint.d.ts +32 -0
- package/dist/pdf/paint.js +442 -0
- package/dist/pdf/writePdf.d.ts +56 -0
- package/dist/pdf/writePdf.js +345 -0
- package/dist/prosemirror/commands/comments.js +96 -6
- package/dist/prosemirror/conversion/fromProseDoc.js +41 -7
- package/dist/prosemirror/conversion/toProseDoc.js +41 -4
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +15 -2
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +35 -6
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +2 -2
- package/dist/prosemirror/extensions/features/pasteCleanup.js +4 -3
- package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.d.ts +3 -1
- package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +5 -3
- package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.d.ts +7 -1
- package/dist/prosemirror/extensions/nodes/RenderedPageBreakExtension.js +9 -3
- package/dist/prosemirror/extensions/nodes/TableExtension.js +56 -39
- package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.d.ts +3 -1
- package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.js +5 -3
- package/dist/prosemirror/plugins/suggestionMode.js +1 -0
- package/dist/prosemirror/revisionCarriers.js +19 -2
- package/dist/prosemirror/utils/extractTrackedChanges.d.ts +2 -2
- package/dist/prosemirror/utils/extractTrackedChanges.js +59 -23
- package/dist/prosemirror/validation.js +55 -27
- package/dist/prosemirror/zeroWidthAnchors.d.ts +10 -0
- package/dist/prosemirror/zeroWidthAnchors.js +23 -0
- package/dist/redline.js +12 -79
- package/dist/server.d.ts +3 -3
- package/dist/server.js +2 -2
- package/dist/shaping/placeRun.d.ts +51 -0
- package/dist/shaping/placeRun.js +84 -0
- package/dist/shaping/shaper.d.ts +92 -0
- package/dist/shaping/shaper.js +102 -0
- package/dist/types/block-id.d.ts +18 -2
- package/dist/types/block-id.js +49 -5
- package/dist/types/content.d.ts +2 -2
- package/dist/utils/clipboard.js +4 -3
- package/dist/utils/fontResolver.js +183 -0
- package/dist/utils/htmlComments.d.ts +17 -0
- package/dist/utils/htmlComments.js +22 -0
- package/dist/utils/scriptSegments.d.ts +12 -1
- package/dist/utils/scriptSegments.js +17 -1
- package/dist/version-comparison.d.ts +1 -1
- package/package.json +7 -3
|
@@ -50,9 +50,13 @@ declare const resolvePassageRange: ({ blockId, text, doc, snapshot }: ResolvePas
|
|
|
50
50
|
* server's `seq-NNNN`: the direct anchor lookup misses, and a
|
|
51
51
|
* paraId-based live lookup can't match either (no node carries a
|
|
52
52
|
* `seq-` paraId). The seq number is the block's 1-based position in
|
|
53
|
-
* the
|
|
54
|
-
* `createFolioAIEditSnapshot` share
|
|
55
|
-
*
|
|
53
|
+
* the non-empty-block walk the server extractor and
|
|
54
|
+
* `createFolioAIEditSnapshot` share.
|
|
55
|
+
*
|
|
56
|
+
* That walk is not the snapshot's `blocks` array: `blocks` also holds
|
|
57
|
+
* the document's blank paragraphs, which the seq sequence does not
|
|
58
|
+
* count. So the position is counted here over the blocks that carry
|
|
59
|
+
* text, which is what the number means.
|
|
56
60
|
*/
|
|
57
61
|
declare const resolveSequentialBlockAnchor: (blockId: string, snapshot: FolioAIEditSnapshot) => FolioAIBlockAnchor | undefined;
|
|
58
62
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { findParagraphByParaId } from "../prosemirror/utils/findParagraphByParaId.js";
|
|
2
2
|
import { getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex } from "../types/block-id.js";
|
|
3
3
|
import { buildCleanBlockText } from "./clean-text.js";
|
|
4
|
-
import { createFolioAIEditSnapshot, hashFolioAIBlockText } from "./snapshot.js";
|
|
4
|
+
import { createFolioAIEditSnapshot, hashFolioAIBlockText, isFolioAIContentBlock } from "./snapshot.js";
|
|
5
5
|
//#region src/ai-edits/blockRange.ts
|
|
6
6
|
const resolveFolioAIBlockRange = ({ blockId, doc, snapshot }) => {
|
|
7
7
|
const paraId = getFolioParaIdFromBlockId(blockId);
|
|
@@ -113,15 +113,23 @@ const matchPassage = (haystack, needleSource) => {
|
|
|
113
113
|
* server's `seq-NNNN`: the direct anchor lookup misses, and a
|
|
114
114
|
* paraId-based live lookup can't match either (no node carries a
|
|
115
115
|
* `seq-` paraId). The seq number is the block's 1-based position in
|
|
116
|
-
* the
|
|
117
|
-
* `createFolioAIEditSnapshot` share
|
|
118
|
-
*
|
|
116
|
+
* the non-empty-block walk the server extractor and
|
|
117
|
+
* `createFolioAIEditSnapshot` share.
|
|
118
|
+
*
|
|
119
|
+
* That walk is not the snapshot's `blocks` array: `blocks` also holds
|
|
120
|
+
* the document's blank paragraphs, which the seq sequence does not
|
|
121
|
+
* count. So the position is counted here over the blocks that carry
|
|
122
|
+
* text, which is what the number means.
|
|
119
123
|
*/
|
|
120
124
|
const resolveSequentialBlockAnchor = (blockId, snapshot) => {
|
|
121
125
|
const index = getSequentialFolioBlockIdIndex(blockId);
|
|
122
126
|
if (index === null) return;
|
|
123
|
-
|
|
124
|
-
|
|
127
|
+
let remaining = index;
|
|
128
|
+
for (const block of snapshot.blocks) {
|
|
129
|
+
if (!isFolioAIContentBlock(block)) continue;
|
|
130
|
+
remaining -= 1;
|
|
131
|
+
if (remaining === 0) return snapshot.anchors[block.id];
|
|
132
|
+
}
|
|
125
133
|
};
|
|
126
134
|
/**
|
|
127
135
|
* Clamp a `{from, to}` pair so both endpoints fit inside a document of
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FolioAIBlock, FolioAIEditApplyMode, FolioAIEditApplyResult, FolioAIEditOperation, FolioAIEditSnapshot } from "./types.js";
|
|
2
|
+
import { FolioRevisionStamp, FolioWordDiffOptions } from "./apply.js";
|
|
2
3
|
import { document_d_exports } from "../types/document.js";
|
|
3
4
|
import { FolioDocumentOperationBatch, FolioDocumentOperationResult, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult } from "../document-operations.js";
|
|
4
5
|
import { FolioReviewChange, FolioReviewChangeKind } from "./read.js";
|
|
@@ -20,6 +21,10 @@ type FolioApplyOperationsOptions = {
|
|
|
20
21
|
* `snapshot()` -> build ops -> `applyOperations()` on the same reviewer.
|
|
21
22
|
*/
|
|
22
23
|
snapshot?: FolioAIEditSnapshot;
|
|
24
|
+
/** Omit to stamp revisions from the wall clock and the shared id cursor. */
|
|
25
|
+
revisionStamp?: FolioRevisionStamp;
|
|
26
|
+
/** Token size a replacement's redline is cut at. Word-level by default. */
|
|
27
|
+
wordDiff?: FolioWordDiffOptions;
|
|
23
28
|
};
|
|
24
29
|
/** Options for {@link FolioDocxReviewer.applyDocumentOperations}. */
|
|
25
30
|
type FolioApplyDocumentOperationsOptions = Omit<FolioApplyOperationsOptions, "mode">;
|
|
@@ -52,6 +57,17 @@ type FolioDocumentStoryHandle = {
|
|
|
52
57
|
noteId: number;
|
|
53
58
|
};
|
|
54
59
|
type FolioEditableDocumentStoryHandle = FolioDocumentStoryHandle;
|
|
60
|
+
/**
|
|
61
|
+
* One numbering level as a reader meets it: which list, which depth, and the
|
|
62
|
+
* format and template that produce the label.
|
|
63
|
+
*/
|
|
64
|
+
type FolioNumberingLevel = {
|
|
65
|
+
numId: number;
|
|
66
|
+
level: number;
|
|
67
|
+
format: string;
|
|
68
|
+
levelText: string;
|
|
69
|
+
start?: number;
|
|
70
|
+
};
|
|
55
71
|
type FolioDocumentStory = {
|
|
56
72
|
handle: FolioDocumentStoryHandle;
|
|
57
73
|
text: string;
|
|
@@ -169,6 +185,18 @@ declare class FolioDocxReviewer {
|
|
|
169
185
|
* the anchor map the apply layer resolves operations against.
|
|
170
186
|
*/
|
|
171
187
|
snapshot(): FolioAIEditSnapshot;
|
|
188
|
+
/**
|
|
189
|
+
* The package's numbering, flattened to what a reader sees: one entry per
|
|
190
|
+
* numbering instance and level, with the format and level text that produce
|
|
191
|
+
* its labels.
|
|
192
|
+
*
|
|
193
|
+
* Labels are rendered from these definitions rather than stored on the
|
|
194
|
+
* paragraphs, so nothing in a block projection changes when a list is
|
|
195
|
+
* renumbered — which is right for an insertion that renumbers the items
|
|
196
|
+
* below it, and wrong for a list whose FORMAT changed. Sorted so two
|
|
197
|
+
* packages can be compared entry by entry.
|
|
198
|
+
*/
|
|
199
|
+
readNumberingDefinitions(): FolioNumberingLevel[];
|
|
172
200
|
/** Return parsed package metadata without exposing the mutable document model. */
|
|
173
201
|
getDocumentProperties(): Readonly<NonNullable<document_d_exports.Document["package"]["properties"]>> | null;
|
|
174
202
|
/** Snapshot one editable story into stable, operation-ready blocks. */
|
|
@@ -191,7 +219,7 @@ declare class FolioDocxReviewer {
|
|
|
191
219
|
*/
|
|
192
220
|
applyDocumentOperations(batch: FolioDocumentOperationBatch, options?: FolioApplyDocumentOperationsOptions): FolioDocumentOperationResult;
|
|
193
221
|
/** Apply a versioned operation batch to one editable document story. */
|
|
194
|
-
applyDocumentOperationsToStory({ story, batch, snapshot }: FolioApplyDocumentOperationsToStoryOptions): FolioDocumentOperationResult;
|
|
222
|
+
applyDocumentOperationsToStory({ story, batch, snapshot, revisionStamp, wordDiff }: FolioApplyDocumentOperationsToStoryOptions): FolioDocumentOperationResult;
|
|
195
223
|
private applyDocumentOperationsInternal;
|
|
196
224
|
/** Undo the latest unchanged document-operation batch and its created comments. */
|
|
197
225
|
undoDocumentOperations(undoHandle: FolioDocumentOperationUndoHandle): FolioDocumentOperationUndoResult;
|
|
@@ -276,12 +304,17 @@ declare class FolioDocxReviewer {
|
|
|
276
304
|
*/
|
|
277
305
|
rejectChange(target: FolioReviewChange | number): boolean;
|
|
278
306
|
/**
|
|
279
|
-
* Accept every tracked change in the
|
|
280
|
-
* present before the sweep.
|
|
307
|
+
* Accept every tracked change in the package. Returns the number of changes
|
|
308
|
+
* present before the sweep.
|
|
309
|
+
*
|
|
310
|
+
* Every story, not just the body: a revision in a header or a footnote is
|
|
311
|
+
* one a reviewer meant to resolve, and leaving it behind means an accepted
|
|
312
|
+
* document still carries a redline nobody can see from the body.
|
|
281
313
|
*/
|
|
282
314
|
acceptAll(): number;
|
|
283
|
-
/** Reject every tracked change in the
|
|
315
|
+
/** Reject every tracked change in the package. See {@link acceptAll}. */
|
|
284
316
|
rejectAll(): number;
|
|
317
|
+
private resolveEveryStory;
|
|
285
318
|
/** The current document model with edits merged back in. */
|
|
286
319
|
toDocument(): document_d_exports.Document;
|
|
287
320
|
/**
|
|
@@ -320,6 +353,7 @@ declare class FolioDocxReviewer {
|
|
|
320
353
|
* resulting state for {@link toBuffer}.
|
|
321
354
|
*/
|
|
322
355
|
private runCommand;
|
|
356
|
+
private runStoryCommand;
|
|
323
357
|
}
|
|
324
358
|
/** Options for {@link applyFolioAIEditsToBuffer}. */
|
|
325
359
|
type ApplyFolioAIEditsToBufferOptions = {
|
|
@@ -348,4 +382,4 @@ type ApplyFolioAIEditsToBufferResult = FolioAIEditApplyResult & {
|
|
|
348
382
|
*/
|
|
349
383
|
declare const applyFolioAIEditsToBuffer: (buffer: ArrayBuffer, operations: FolioAIEditOperation[], options?: ApplyFolioAIEditsToBufferOptions) => Promise<ApplyFolioAIEditsToBufferResult>;
|
|
350
384
|
//#endregion
|
|
351
|
-
export { ApplyFolioAIEditsToBufferOptions, ApplyFolioAIEditsToBufferResult, FOLIO_RESOLVED_REVIEWED_VIEWS, FOLIO_REVIEWED_VIEWS, FolioApplyDocumentOperationsOptions, FolioApplyDocumentOperationsToStoryOptions, FolioApplyOperationsOptions, FolioDocumentStory, FolioDocumentStoryHandle, FolioDocumentStoryNotFoundError, FolioDocxReviewer, FolioDocxReviewerOptions, FolioEditableDocumentStoryHandle, FolioGetContentAsTextOptions, FolioReadReviewedStoryOptions, FolioResolveReviewedStoryOptions, FolioResolvedReviewedView, type FolioReviewChange, FolioReviewChangeFilter, type FolioReviewChangeKind, FolioReviewComment, FolioReviewCommentFilter, FolioReviewCommentReply, FolioReviewReplyInput, FolioReviewedStory, FolioReviewedView, UnsupportedFolioReviewedViewError, applyFolioAIEditsToBuffer, isFolioResolvedReviewedView, isFolioReviewedView };
|
|
385
|
+
export { ApplyFolioAIEditsToBufferOptions, ApplyFolioAIEditsToBufferResult, FOLIO_RESOLVED_REVIEWED_VIEWS, FOLIO_REVIEWED_VIEWS, FolioApplyDocumentOperationsOptions, FolioApplyDocumentOperationsToStoryOptions, FolioApplyOperationsOptions, FolioDocumentStory, FolioDocumentStoryHandle, FolioDocumentStoryNotFoundError, FolioDocxReviewer, FolioDocxReviewerOptions, FolioEditableDocumentStoryHandle, FolioGetContentAsTextOptions, FolioNumberingLevel, FolioReadReviewedStoryOptions, FolioResolveReviewedStoryOptions, FolioResolvedReviewedView, type FolioReviewChange, FolioReviewChangeFilter, type FolioReviewChangeKind, FolioReviewComment, FolioReviewCommentFilter, FolioReviewCommentReply, FolioReviewReplyInput, FolioReviewedStory, FolioReviewedView, type FolioRevisionStamp, UnsupportedFolioReviewedViewError, applyFolioAIEditsToBuffer, isFolioResolvedReviewedView, isFolioReviewedView };
|
|
@@ -14,7 +14,7 @@ import { schema, singletonManager } from "../prosemirror/schema/index.js";
|
|
|
14
14
|
import { deterministicHexId } from "../utils/hexId.js";
|
|
15
15
|
import { buildAnnotatedBlockText } from "./clean-text.js";
|
|
16
16
|
import { getCommentAnchorsFromDoc, getTrackedChangesFromDoc } from "./read.js";
|
|
17
|
-
import { createFolioAIEditSnapshot, normalizeFolioAIBlockText } from "./snapshot.js";
|
|
17
|
+
import { createFolioAIEditSnapshot, isFolioAIContentBlock, normalizeFolioAIBlockText } from "./snapshot.js";
|
|
18
18
|
import { TaggedError } from "better-result";
|
|
19
19
|
import { Fragment } from "prosemirror-model";
|
|
20
20
|
import { EditorState } from "prosemirror-state";
|
|
@@ -154,12 +154,19 @@ const resolveReviewedState = (state, view) => {
|
|
|
154
154
|
};
|
|
155
155
|
const formatStoryStateForLLM = (state, annotated) => {
|
|
156
156
|
const snapshot = createFolioAIEditSnapshot(state.doc);
|
|
157
|
-
|
|
157
|
+
const blocks = snapshot.blocks.filter(isFolioAIContentBlock);
|
|
158
|
+
if (!annotated) return blocks.map(formatBlockForLLM).join("\n");
|
|
159
|
+
const nodeByStart = /* @__PURE__ */ new Map();
|
|
160
|
+
state.doc.descendants((node, pos) => {
|
|
161
|
+
if (!node.isTextblock) return true;
|
|
162
|
+
nodeByStart.set(pos, node);
|
|
163
|
+
return false;
|
|
164
|
+
});
|
|
158
165
|
const startById = /* @__PURE__ */ new Map();
|
|
159
166
|
for (const anchor of Object.values(snapshot.anchors)) startById.set(anchor.id, anchor.from);
|
|
160
|
-
return
|
|
167
|
+
return blocks.map((block) => {
|
|
161
168
|
const from = startById.get(block.id);
|
|
162
|
-
const node = from === void 0 ?
|
|
169
|
+
const node = from === void 0 ? void 0 : nodeByStart.get(from);
|
|
163
170
|
const text = node ? buildAnnotatedBlockText(node) : block.text;
|
|
164
171
|
return formatBlockLine(block, text);
|
|
165
172
|
}).join("\n");
|
|
@@ -260,6 +267,38 @@ var FolioDocxReviewer = class FolioDocxReviewer {
|
|
|
260
267
|
snapshot() {
|
|
261
268
|
return createFolioAIEditSnapshot(this.state.doc);
|
|
262
269
|
}
|
|
270
|
+
/**
|
|
271
|
+
* The package's numbering, flattened to what a reader sees: one entry per
|
|
272
|
+
* numbering instance and level, with the format and level text that produce
|
|
273
|
+
* its labels.
|
|
274
|
+
*
|
|
275
|
+
* Labels are rendered from these definitions rather than stored on the
|
|
276
|
+
* paragraphs, so nothing in a block projection changes when a list is
|
|
277
|
+
* renumbered — which is right for an insertion that renumbers the items
|
|
278
|
+
* below it, and wrong for a list whose FORMAT changed. Sorted so two
|
|
279
|
+
* packages can be compared entry by entry.
|
|
280
|
+
*/
|
|
281
|
+
readNumberingDefinitions() {
|
|
282
|
+
const numbering = this.baseDocument.package.numbering;
|
|
283
|
+
if (!numbering) return [];
|
|
284
|
+
const levelsByAbstractId = new Map(numbering.abstractNums.map((abstractNum) => [abstractNum.abstractNumId, abstractNum.levels]));
|
|
285
|
+
const levels = [];
|
|
286
|
+
for (const instance of numbering.nums) {
|
|
287
|
+
const overrides = new Map((instance.levelOverrides ?? []).map((override) => [override.ilvl, override]));
|
|
288
|
+
for (const level of levelsByAbstractId.get(instance.abstractNumId) ?? []) {
|
|
289
|
+
const override = overrides.get(level.ilvl);
|
|
290
|
+
const resolved = override?.lvl ?? level;
|
|
291
|
+
levels.push({
|
|
292
|
+
numId: instance.numId,
|
|
293
|
+
level: resolved.ilvl,
|
|
294
|
+
format: resolved.numFmt,
|
|
295
|
+
levelText: resolved.lvlText,
|
|
296
|
+
...(override?.startOverride ?? resolved.start) !== void 0 ? { start: override?.startOverride ?? resolved.start } : {}
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return levels.toSorted((left, right) => left.numId - right.numId || left.level - right.level);
|
|
301
|
+
}
|
|
263
302
|
/** Return parsed package metadata without exposing the mutable document model. */
|
|
264
303
|
getDocumentProperties() {
|
|
265
304
|
const properties = this.baseDocument.package.properties;
|
|
@@ -325,6 +364,7 @@ var FolioDocxReviewer = class FolioDocxReviewer {
|
|
|
325
364
|
mode: options.mode ?? "tracked-changes"
|
|
326
365
|
},
|
|
327
366
|
...options.snapshot !== void 0 && { snapshot: options.snapshot },
|
|
367
|
+
...options.revisionStamp !== void 0 && { revisionStamp: options.revisionStamp },
|
|
328
368
|
createUndoEntry: false
|
|
329
369
|
});
|
|
330
370
|
return {
|
|
@@ -343,19 +383,22 @@ var FolioDocxReviewer = class FolioDocxReviewer {
|
|
|
343
383
|
story: MAIN_STORY,
|
|
344
384
|
batch,
|
|
345
385
|
...options.snapshot !== void 0 && { snapshot: options.snapshot },
|
|
386
|
+
...options.revisionStamp !== void 0 && { revisionStamp: options.revisionStamp },
|
|
346
387
|
createUndoEntry: true
|
|
347
388
|
});
|
|
348
389
|
}
|
|
349
390
|
/** Apply a versioned operation batch to one editable document story. */
|
|
350
|
-
applyDocumentOperationsToStory({ story, batch, snapshot }) {
|
|
391
|
+
applyDocumentOperationsToStory({ story, batch, snapshot, revisionStamp, wordDiff }) {
|
|
351
392
|
return this.applyDocumentOperationsInternal({
|
|
352
393
|
story,
|
|
353
394
|
batch,
|
|
354
395
|
...snapshot !== void 0 && { snapshot },
|
|
396
|
+
...revisionStamp !== void 0 && { revisionStamp },
|
|
397
|
+
...wordDiff !== void 0 && { wordDiff },
|
|
355
398
|
createUndoEntry: true
|
|
356
399
|
});
|
|
357
400
|
}
|
|
358
|
-
applyDocumentOperationsInternal({ story, batch, snapshot, createUndoEntry }) {
|
|
401
|
+
applyDocumentOperationsInternal({ story, batch, snapshot, revisionStamp, wordDiff, createUndoEntry }) {
|
|
359
402
|
const beforeState = this.requireEditableStoryState(story);
|
|
360
403
|
const createdCommentsLengthBefore = this.createdComments.length;
|
|
361
404
|
const view = {
|
|
@@ -370,6 +413,8 @@ var FolioDocxReviewer = class FolioDocxReviewer {
|
|
|
370
413
|
batch,
|
|
371
414
|
story: story.type === "main" ? "main" : story,
|
|
372
415
|
author: this.author,
|
|
416
|
+
...revisionStamp !== void 0 && { revisionStamp },
|
|
417
|
+
...wordDiff !== void 0 && { wordDiff },
|
|
373
418
|
createCommentId: (text) => {
|
|
374
419
|
const comment = createReviewerComment(this.nextCommentId(), text, this.author);
|
|
375
420
|
this.createdComments.push(comment);
|
|
@@ -658,18 +703,28 @@ var FolioDocxReviewer = class FolioDocxReviewer {
|
|
|
658
703
|
return this.runCommand(rejectAIEditRevision(revisionIdOf(target)));
|
|
659
704
|
}
|
|
660
705
|
/**
|
|
661
|
-
* Accept every tracked change in the
|
|
662
|
-
* present before the sweep.
|
|
706
|
+
* Accept every tracked change in the package. Returns the number of changes
|
|
707
|
+
* present before the sweep.
|
|
708
|
+
*
|
|
709
|
+
* Every story, not just the body: a revision in a header or a footnote is
|
|
710
|
+
* one a reviewer meant to resolve, and leaving it behind means an accepted
|
|
711
|
+
* document still carries a redline nobody can see from the body.
|
|
663
712
|
*/
|
|
664
713
|
acceptAll() {
|
|
665
|
-
|
|
666
|
-
this.runCommand(acceptAllChanges());
|
|
667
|
-
return count;
|
|
714
|
+
return this.resolveEveryStory(acceptAllChanges());
|
|
668
715
|
}
|
|
669
|
-
/** Reject every tracked change in the
|
|
716
|
+
/** Reject every tracked change in the package. See {@link acceptAll}. */
|
|
670
717
|
rejectAll() {
|
|
671
|
-
|
|
672
|
-
|
|
718
|
+
return this.resolveEveryStory(rejectAllChanges());
|
|
719
|
+
}
|
|
720
|
+
resolveEveryStory(command) {
|
|
721
|
+
let count = 0;
|
|
722
|
+
for (const { handle } of this.listStories()) {
|
|
723
|
+
const state = this.getEditableStoryState(handle);
|
|
724
|
+
if (!state) continue;
|
|
725
|
+
count += getTrackedChangesFromDoc(state.doc).length;
|
|
726
|
+
this.runStoryCommand(command, handle);
|
|
727
|
+
}
|
|
673
728
|
return count;
|
|
674
729
|
}
|
|
675
730
|
/** The current document model with edits merged back in. */
|
|
@@ -898,15 +953,19 @@ var FolioDocxReviewer = class FolioDocxReviewer {
|
|
|
898
953
|
* resulting state for {@link toBuffer}.
|
|
899
954
|
*/
|
|
900
955
|
runCommand(command) {
|
|
901
|
-
this.
|
|
956
|
+
return this.runStoryCommand(command, MAIN_STORY);
|
|
957
|
+
}
|
|
958
|
+
runStoryCommand(command, story) {
|
|
959
|
+
const state = this.getEditableStoryState(story);
|
|
960
|
+
if (!state) return false;
|
|
902
961
|
const view = {
|
|
903
|
-
state
|
|
962
|
+
state,
|
|
904
963
|
dispatch: (transaction) => {
|
|
905
964
|
view.state = view.state.apply(transaction);
|
|
906
965
|
}
|
|
907
966
|
};
|
|
908
967
|
const handled = command(view.state, view.dispatch);
|
|
909
|
-
this.
|
|
968
|
+
this.setEditableStoryState(story, view.state);
|
|
910
969
|
return handled;
|
|
911
970
|
}
|
|
912
971
|
};
|
package/dist/ai-edits/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { FolioAIBlock, FolioAIBlockAnchor, FolioAIBlockKind, FolioAIBlockPreviewRun, FolioAIComment, FolioAIEditAppliedOperation, FolioAIEditApplyMode, FolioAIEditApplyResult, FolioAIEditNormalization, FolioAIEditNormalizationCode, FolioAIEditOperation, FolioAIEditPrecondition, FolioAIEditReviewMeta, FolioAIEditSeverity, FolioAIEditSkipReason, FolioAIEditSkippedOperation, FolioAIEditSnapshot, FolioAIInlineFormatting, FolioAISignatureParty, FolioAITextRangeHandle, FolioDocumentNavigationTarget, FolioDocumentOutline, FolioDocumentOutlineEntry, FolioDocumentSection, FolioDocumentSectionHandle, FolioDocumentSectionReadResult } from "./types.js";
|
|
2
|
-
import {
|
|
1
|
+
import { FolioAIBlock, FolioAIBlockAnchor, FolioAIBlockKind, FolioAIBlockPreviewRun, FolioAIBlockTableLocation, FolioAIComment, FolioAIEditAppliedOperation, FolioAIEditApplyMode, FolioAIEditApplyResult, FolioAIEditNormalization, FolioAIEditNormalizationCode, FolioAIEditOperation, FolioAIEditPrecondition, FolioAIEditReviewMeta, FolioAIEditSeverity, FolioAIEditSkipReason, FolioAIEditSkippedOperation, FolioAIEditSnapshot, FolioAIInlineFormatting, FolioAISignatureParty, FolioAITextRangeHandle, FolioDocumentNavigationTarget, FolioDocumentOutline, FolioDocumentOutlineEntry, FolioDocumentSection, FolioDocumentSectionHandle, FolioDocumentSectionReadResult } from "./types.js";
|
|
2
|
+
import { WORD_DIFF_GRANULARITIES, WordDiffGranularity, WordDiffNormalization, WordDiffOptions, WordDiffSegment, diffWordSegments } from "./word-diff.js";
|
|
3
|
+
import { FolioAIEditApplyOutcome, FolioAIEditView, FolioRevisionStamp, FolioWordDiffOptions, applyFolioAIEditOperations } from "./apply.js";
|
|
3
4
|
import { DocPositionRange, clampRangeToDocSize, resolveFolioAIBlockRange, resolveFolioAITextRange, resolvePassageRange } from "./blockRange.js";
|
|
4
5
|
import { buildAnnotatedBlockText } from "./clean-text.js";
|
|
5
|
-
import { ApplyFolioDocumentOperationsOptions, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FolioDocumentOperation, FolioDocumentOperationAffectedTarget, FolioDocumentOperationBatch, FolioDocumentOperationCapabilities, FolioDocumentOperationIssue, FolioDocumentOperationMode, FolioDocumentOperationPrecondition, FolioDocumentOperationReceipt, FolioDocumentOperationRecovery, FolioDocumentOperationResult, FolioDocumentOperationStatus, FolioDocumentOperationStory, FolioDocumentOperationType, FolioDocumentOperationUndoFailureReason, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch } from "../document-operations.js";
|
|
6
|
+
import { ApplyFolioDocumentOperationsOptions, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FolioDocumentOperation, FolioDocumentOperationAffectedTarget, FolioDocumentOperationBatch, FolioDocumentOperationCapabilities, FolioDocumentOperationIssue, FolioDocumentOperationMode, FolioDocumentOperationPrecondition, FolioDocumentOperationReceipt, FolioDocumentOperationRecovery, FolioDocumentOperationResult, FolioDocumentOperationResultBase, FolioDocumentOperationStatus, FolioDocumentOperationStory, FolioDocumentOperationType, FolioDocumentOperationUndoFailureReason, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch } from "../document-operations.js";
|
|
6
7
|
import { FolioCommentAnchor, FolioReviewChange, FolioReviewChangeKind, getCommentAnchorsFromDoc, getTrackedChangesFromDoc } from "./read.js";
|
|
7
8
|
import { FOLIO_RESOLVED_REVIEWED_VIEWS, FOLIO_REVIEWED_VIEWS, FolioApplyDocumentOperationsToStoryOptions, FolioDocumentStory, FolioDocumentStoryHandle, FolioDocumentStoryNotFoundError, FolioEditableDocumentStoryHandle, FolioReadReviewedStoryOptions, FolioResolveReviewedStoryOptions, FolioResolvedReviewedView, FolioReviewedStory, FolioReviewedView, UnsupportedFolioReviewedViewError, isFolioResolvedReviewedView, isFolioReviewedView } from "./headless.js";
|
|
8
|
-
import { createFolioAIEditSnapshot, createFolioAITextRangeHandle, hashFolioAIBlockText, normalizeFolioAIBlockText } from "./snapshot.js";
|
|
9
|
+
import { createFolioAIEditSnapshot, createFolioAITextRangeHandle, hashFolioAIBlockText, isFolioAIContentBlock, normalizeFolioAIBlockText } from "./snapshot.js";
|
|
9
10
|
import { getFolioDocumentOutline, readFolioDocumentSection } from "./scoped-reading.js";
|
|
10
11
|
import { getFolioParaIdFromBlockId } from "../types/block-id.js";
|
|
11
|
-
|
|
12
|
-
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_RESOLVED_REVIEWED_VIEWS, FOLIO_REVIEWED_VIEWS, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyResult, type FolioAIEditNormalization, type FolioAIEditNormalizationCode, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAIEditView, type FolioAIInlineFormatting, type FolioAISignatureParty, type FolioAITextRangeHandle, type FolioApplyDocumentOperationsToStoryOptions, type FolioCommentAnchor, type FolioDocumentNavigationTarget, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, 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, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, UnsupportedFolioReviewedViewError, type WordDiffSegment, applyFolioAIEditOperations, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, buildAnnotatedBlockText, clampRangeToDocSize, createFolioAIEditSnapshot, createFolioAITextRangeHandle, diffWordSegments, getCommentAnchorsFromDoc, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioDocumentOutline, getFolioParaIdFromBlockId, getTrackedChangesFromDoc, hashFolioAIBlockText, isFolioDocumentOperationModeSupported, isFolioResolvedReviewedView, isFolioReviewedView, isSupportedFolioDocumentOperationVersion, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, readFolioDocumentSection, resolveFolioAIBlockRange, resolveFolioAITextRange, resolvePassageRange };
|
|
12
|
+
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_RESOLVED_REVIEWED_VIEWS, FOLIO_REVIEWED_VIEWS, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIBlockTableLocation, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyOutcome, type FolioAIEditApplyResult, type FolioAIEditNormalization, type FolioAIEditNormalizationCode, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAIEditView, type FolioAIInlineFormatting, type FolioAISignatureParty, type FolioAITextRangeHandle, type FolioApplyDocumentOperationsToStoryOptions, type FolioCommentAnchor, 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 };
|
package/dist/ai-edits/index.js
CHANGED
|
@@ -6,6 +6,6 @@ import { buildAnnotatedBlockText } from "./clean-text.js";
|
|
|
6
6
|
import { FOLIO_RESOLVED_REVIEWED_VIEWS, FOLIO_REVIEWED_VIEWS, FolioDocumentStoryNotFoundError, UnsupportedFolioReviewedViewError, isFolioResolvedReviewedView, isFolioReviewedView } from "./headless.js";
|
|
7
7
|
import { getCommentAnchorsFromDoc, getTrackedChangesFromDoc } from "./read.js";
|
|
8
8
|
import { getFolioDocumentOutline, readFolioDocumentSection } from "./scoped-reading.js";
|
|
9
|
-
import { createFolioAIEditSnapshot, createFolioAITextRangeHandle, hashFolioAIBlockText, normalizeFolioAIBlockText } from "./snapshot.js";
|
|
10
|
-
import { diffWordSegments } from "./word-diff.js";
|
|
11
|
-
export { 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_RESOLVED_REVIEWED_VIEWS, FOLIO_REVIEWED_VIEWS, FolioDocumentStoryNotFoundError, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, UnsupportedFolioReviewedViewError, applyFolioAIEditOperations, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, buildAnnotatedBlockText, clampRangeToDocSize, createFolioAIEditSnapshot, createFolioAITextRangeHandle, diffWordSegments, getCommentAnchorsFromDoc, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioDocumentOutline, getFolioParaIdFromBlockId, getTrackedChangesFromDoc, hashFolioAIBlockText, isFolioDocumentOperationModeSupported, isFolioResolvedReviewedView, isFolioReviewedView, isSupportedFolioDocumentOperationVersion, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, readFolioDocumentSection, resolveFolioAIBlockRange, resolveFolioAITextRange, resolvePassageRange };
|
|
9
|
+
import { createFolioAIEditSnapshot, createFolioAITextRangeHandle, hashFolioAIBlockText, isFolioAIContentBlock, normalizeFolioAIBlockText } from "./snapshot.js";
|
|
10
|
+
import { WORD_DIFF_GRANULARITIES, diffWordSegments } from "./word-diff.js";
|
|
11
|
+
export { 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_RESOLVED_REVIEWED_VIEWS, FOLIO_REVIEWED_VIEWS, FolioDocumentStoryNotFoundError, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, UnsupportedFolioReviewedViewError, WORD_DIFF_GRANULARITIES, 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 };
|
package/dist/ai-edits/read.d.ts
CHANGED
|
@@ -60,6 +60,10 @@ type FolioCommentAnchor = {
|
|
|
60
60
|
* The tracked changes present in the body, read from inline marks and
|
|
61
61
|
* structural node attributes. Runs of one inline revision within a block fold
|
|
62
62
|
* into a single entry.
|
|
63
|
+
*
|
|
64
|
+
* A tracked row insertion or deletion marks the row AND every run in its
|
|
65
|
+
* cells, the way Word writes it. Both halves are one change, so the run marks
|
|
66
|
+
* fold into the row's entry rather than reporting a second time.
|
|
63
67
|
*/
|
|
64
68
|
declare const getTrackedChangesFromDoc: (doc: Node) => FolioReviewChange[];
|
|
65
69
|
/**
|
package/dist/ai-edits/read.js
CHANGED
|
@@ -44,9 +44,20 @@ const firstBlockIdWithin = ({ node, nodePos, blockStarts }) => {
|
|
|
44
44
|
return blockId;
|
|
45
45
|
};
|
|
46
46
|
/**
|
|
47
|
+
* Whether a run's revision inside a marked row is that row's own. Folio writes
|
|
48
|
+
* both halves under one revision id; Word mints a fresh `w:id` per element, so
|
|
49
|
+
* an author + timestamp match counts too. A third party's edit inside the row
|
|
50
|
+
* matches neither and keeps its own entry.
|
|
51
|
+
*/
|
|
52
|
+
const belongsToRowRevision = (scope, revision) => revision.id === scope.change.id || revision.author === scope.change.author && revision.date === scope.change.date;
|
|
53
|
+
/**
|
|
47
54
|
* The tracked changes present in the body, read from inline marks and
|
|
48
55
|
* structural node attributes. Runs of one inline revision within a block fold
|
|
49
56
|
* into a single entry.
|
|
57
|
+
*
|
|
58
|
+
* A tracked row insertion or deletion marks the row AND every run in its
|
|
59
|
+
* cells, the way Word writes it. Both halves are one change, so the run marks
|
|
60
|
+
* fold into the row's entry rather than reporting a second time.
|
|
50
61
|
*/
|
|
51
62
|
const getTrackedChangesFromDoc = (doc) => {
|
|
52
63
|
const insertionType = doc.type.schema.marks["insertion"];
|
|
@@ -54,8 +65,10 @@ const getTrackedChangesFromDoc = (doc) => {
|
|
|
54
65
|
const blockStarts = blockStartIdsFromDoc(doc);
|
|
55
66
|
const grouped = /* @__PURE__ */ new Map();
|
|
56
67
|
const structuralChangeCellPositions = /* @__PURE__ */ new Map();
|
|
68
|
+
const rowRevisionScopes = [];
|
|
57
69
|
let currentBlockId = null;
|
|
58
70
|
doc.descendants((node, pos) => {
|
|
71
|
+
while (pos >= (rowRevisionScopes.at(-1)?.end ?? Number.POSITIVE_INFINITY)) rowRevisionScopes.pop();
|
|
59
72
|
const nodeRevisionCarriers = getFolioNodeRevisionCarriers(node, pos);
|
|
60
73
|
if (nodeRevisionCarriers.length > 0) {
|
|
61
74
|
const blockId = node.isTextblock ? blockStarts.get(pos) ?? null : firstBlockIdWithin({
|
|
@@ -80,7 +93,7 @@ const getTrackedChangesFromDoc = (doc) => {
|
|
|
80
93
|
const revisionId = marker.revisionId;
|
|
81
94
|
const author = "author" in marker ? marker.author : void 0;
|
|
82
95
|
const date = "date" in marker ? marker.date : void 0;
|
|
83
|
-
|
|
96
|
+
const change = {
|
|
84
97
|
id: revisionId,
|
|
85
98
|
type: kind,
|
|
86
99
|
author: typeof author === "string" ? author : "",
|
|
@@ -91,6 +104,12 @@ const getTrackedChangesFromDoc = (doc) => {
|
|
|
91
104
|
nodePos: pos,
|
|
92
105
|
blockStarts
|
|
93
106
|
})
|
|
107
|
+
};
|
|
108
|
+
grouped.set(`row:${kind}:${revisionId}:${String(pos)}`, change);
|
|
109
|
+
rowRevisionScopes.push({
|
|
110
|
+
end: pos + node.nodeSize,
|
|
111
|
+
kind: kind === "rowInserted" ? "insertion" : "deletion",
|
|
112
|
+
change
|
|
94
113
|
});
|
|
95
114
|
}
|
|
96
115
|
if (node.type.name === "tableCell" || node.type.name === "tableHeader") {
|
|
@@ -182,19 +201,24 @@ const getTrackedChangesFromDoc = (doc) => {
|
|
|
182
201
|
else if (mark.type === deletionType) kind = "deletion";
|
|
183
202
|
else continue;
|
|
184
203
|
const revisionId = mark.attrs["revisionId"];
|
|
204
|
+
const author = mark.attrs["author"];
|
|
205
|
+
const date = mark.attrs["date"];
|
|
206
|
+
const revision = {
|
|
207
|
+
id: revisionId,
|
|
208
|
+
author: typeof author === "string" ? author : "",
|
|
209
|
+
date: typeof date === "string" ? date : null
|
|
210
|
+
};
|
|
211
|
+
const rowScope = rowRevisionScopes.at(-1);
|
|
212
|
+
if (rowScope?.kind === kind && belongsToRowRevision(rowScope, revision)) continue;
|
|
185
213
|
const key = `${currentBlockId ?? ""}:${kind}:${revisionId}`;
|
|
186
214
|
const existing = grouped.get(key);
|
|
187
215
|
if (existing) {
|
|
188
216
|
existing.text += text;
|
|
189
217
|
continue;
|
|
190
218
|
}
|
|
191
|
-
const author = mark.attrs["author"];
|
|
192
|
-
const date = mark.attrs["date"];
|
|
193
219
|
grouped.set(key, {
|
|
194
|
-
|
|
220
|
+
...revision,
|
|
195
221
|
type: kind,
|
|
196
|
-
author: typeof author === "string" ? author : "",
|
|
197
|
-
date: typeof date === "string" ? date : null,
|
|
198
222
|
text,
|
|
199
223
|
blockId: currentBlockId
|
|
200
224
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isFolioAIContentBlock } from "./snapshot.js";
|
|
1
2
|
//#region src/ai-edits/scoped-reading.ts
|
|
2
3
|
const toSectionHandle = (snapshot, headingBlockId, headingLevel) => {
|
|
3
4
|
const headingTextHash = snapshot.anchors[headingBlockId]?.textHash;
|
|
@@ -15,7 +16,7 @@ const getFolioDocumentOutline = (snapshot) => {
|
|
|
15
16
|
const sections = [];
|
|
16
17
|
const parentStack = [];
|
|
17
18
|
for (const block of snapshot.blocks) {
|
|
18
|
-
if (block.headingLevel === void 0) continue;
|
|
19
|
+
if (block.headingLevel === void 0 || !isFolioAIContentBlock(block)) continue;
|
|
19
20
|
const handle = toSectionHandle(snapshot, block.id, block.headingLevel);
|
|
20
21
|
if (handle === null) continue;
|
|
21
22
|
while ((parentStack.at(-1)?.level ?? 0) >= block.headingLevel) parentStack.pop();
|
|
@@ -42,7 +43,7 @@ const readFolioDocumentSection = (snapshot, handle) => {
|
|
|
42
43
|
let endIndex = snapshot.blocks.length;
|
|
43
44
|
for (let index = startIndex + 1; index < snapshot.blocks.length; index++) {
|
|
44
45
|
const block = snapshot.blocks.at(index);
|
|
45
|
-
if (block
|
|
46
|
+
if (block !== void 0 && block.headingLevel !== void 0 && block.headingLevel <= heading.level && isFolioAIContentBlock(block)) {
|
|
46
47
|
endIndex = index;
|
|
47
48
|
break;
|
|
48
49
|
}
|
|
@@ -52,7 +53,7 @@ const readFolioDocumentSection = (snapshot, handle) => {
|
|
|
52
53
|
section: {
|
|
53
54
|
handle,
|
|
54
55
|
heading,
|
|
55
|
-
blocks: snapshot.blocks.slice(startIndex, endIndex)
|
|
56
|
+
blocks: snapshot.blocks.slice(startIndex, endIndex).filter(isFolioAIContentBlock)
|
|
56
57
|
}
|
|
57
58
|
};
|
|
58
59
|
};
|
|
@@ -1,7 +1,39 @@
|
|
|
1
|
-
import { FolioAIEditSnapshot, FolioAITextRangeHandle } from "./types.js";
|
|
1
|
+
import { FolioAIBlock, FolioAIEditSnapshot, FolioAITextRangeHandle } from "./types.js";
|
|
2
2
|
import { Node } from "prosemirror-model";
|
|
3
3
|
//#region src/ai-edits/snapshot.d.ts
|
|
4
4
|
declare const normalizeFolioAIBlockText: (text: string) => string;
|
|
5
|
+
/**
|
|
6
|
+
* Whether a block carries text a reader would see.
|
|
7
|
+
*
|
|
8
|
+
* The snapshot holds every paragraph, blank ones included: an empty cell is
|
|
9
|
+
* part of a table's shape, an empty row is a row, and a comparison that cannot
|
|
10
|
+
* address them cannot describe what changed around them. A reading surface
|
|
11
|
+
* wants the opposite — a model shown a document should see its content, not a
|
|
12
|
+
* line per blank paragraph.
|
|
13
|
+
*
|
|
14
|
+
* So the two needs are split here rather than in the walk: the snapshot is
|
|
15
|
+
* complete, and every surface that reads it for a person or a model states
|
|
16
|
+
* that it wants content by calling this. One helper, so "what counts as
|
|
17
|
+
* content" has a single answer; five inline emptiness checks would drift.
|
|
18
|
+
*/
|
|
19
|
+
declare const isFolioAIContentBlock: ({ text }: Pick<FolioAIBlock, "text">) => boolean;
|
|
20
|
+
/**
|
|
21
|
+
* The block that content appended to the end of a story hangs from: the last
|
|
22
|
+
* paragraph at body level.
|
|
23
|
+
*
|
|
24
|
+
* Not simply the last block. A story's last block is often inside a table, and
|
|
25
|
+
* a paragraph cannot be appended after one: the insertion escapes to the
|
|
26
|
+
* table's boundary, where the block it was anchored to is not adjacent to it
|
|
27
|
+
* and its paragraph mark ends a different container's paragraph. Neither
|
|
28
|
+
* container-edge rule then applies and the addition cannot be rejected
|
|
29
|
+
* cleanly.
|
|
30
|
+
*
|
|
31
|
+
* A body always ends with a paragraph — a table may not be the last child of a
|
|
32
|
+
* body or a cell, so a package that ends in a table carries a trailing, often
|
|
33
|
+
* empty, paragraph after it — so this is only `null` for a story with no
|
|
34
|
+
* body-level paragraph at all, which is a malformed document.
|
|
35
|
+
*/
|
|
36
|
+
declare const trailingBodyBlockId: ({ blocks }: FolioAIEditSnapshot) => string | null;
|
|
5
37
|
declare const hashFolioAIBlockText: (text: string) => string;
|
|
6
38
|
type CreateFolioAITextRangeHandleOptions = {
|
|
7
39
|
blockId: string;
|
|
@@ -10,6 +42,14 @@ type CreateFolioAITextRangeHandleOptions = {
|
|
|
10
42
|
endOffset: number;
|
|
11
43
|
};
|
|
12
44
|
declare const createFolioAITextRangeHandle: ({ blockId, text, startOffset, endOffset }: CreateFolioAITextRangeHandleOptions) => FolioAITextRangeHandle | null;
|
|
45
|
+
/**
|
|
46
|
+
* True for a `tableRow` marked `hidden` (OOXML `w:trPr/w:hidden` — Word never
|
|
47
|
+
* renders the row). Nothing inside such a row may surface its text to the
|
|
48
|
+
* AI/agent snapshot: an attacker DOCX could otherwise smuggle prompt-injection
|
|
49
|
+
* instructions into a row that no human ever sees. The walk skips the row's
|
|
50
|
+
* whole subtree, so a table nested inside a hidden row is hidden with it.
|
|
51
|
+
*/
|
|
52
|
+
declare const isHiddenTableRow: (node: Node) => boolean;
|
|
13
53
|
declare const createFolioAIEditSnapshot: (doc: Node) => FolioAIEditSnapshot;
|
|
14
54
|
//#endregion
|
|
15
|
-
export { createFolioAIEditSnapshot, createFolioAITextRangeHandle, hashFolioAIBlockText, normalizeFolioAIBlockText };
|
|
55
|
+
export { createFolioAIEditSnapshot, createFolioAITextRangeHandle, hashFolioAIBlockText, isFolioAIContentBlock, isHiddenTableRow, normalizeFolioAIBlockText, trailingBodyBlockId };
|