@stll/folio-core 0.8.0 → 0.9.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/README.md +39 -0
- package/dist/ai-edits/apply.js +18 -4
- package/dist/ai-edits/headless.d.ts +31 -4
- package/dist/ai-edits/headless.js +148 -35
- package/dist/ai-edits/index.d.ts +3 -3
- package/dist/ai-edits/index.js +2 -1
- package/dist/ai-edits/snapshot.js +40 -3
- package/dist/ai-edits/types.d.ts +2 -1
- package/dist/compat/eigenpal.d.ts +6 -4
- package/dist/compat/eigenpal.js +5 -3
- package/dist/controller/latestRequestGate.d.ts +13 -0
- package/dist/controller/latestRequestGate.js +16 -0
- package/dist/controller/layoutPipeline.js +12 -1
- package/dist/document-operations.d.ts +10 -3
- package/dist/document-operations.js +29 -14
- package/dist/docx/blockContentParser.js +2 -2
- package/dist/docx/commentParser.js +1 -1
- package/dist/docx/compatibility.d.ts +3 -7
- package/dist/docx/compatibility.js +0 -11
- package/dist/docx/encryption/agileDecryption.js +1 -1
- package/dist/docx/encryption/encryptionInfo.js +1 -1
- package/dist/docx/encryption/openEncryptedDocx.js +1 -1
- package/dist/docx/fontTableParser.d.ts +6 -0
- package/dist/docx/fontTableParser.js +72 -0
- package/dist/docx/groupDrawingParser.js +7 -2
- package/dist/docx/headerFooterParser.js +1 -1
- package/dist/docx/normalizeBaseDirection.js +1 -1
- package/dist/docx/numberingParser.js +1 -0
- package/dist/docx/paragraphParser.js +12 -1
- package/dist/docx/parser.d.ts +1 -1
- package/dist/docx/parser.js +12 -9
- package/dist/docx/rezip.js +70 -5
- package/dist/docx/runConsolidator.js +4 -0
- package/dist/docx/runParser.js +19 -1
- package/dist/docx/selectiveSave.js +3 -3
- package/dist/docx/serializer/fontTableSerializer.d.ts +6 -0
- package/dist/docx/serializer/fontTableSerializer.js +26 -0
- package/dist/docx/serializer/headerFooterSerializer.js +1 -1
- package/dist/docx/serializer/paragraphSerializer.js +4 -0
- package/dist/docx/serializer/runSerializer.js +7 -0
- package/dist/docx/serializer/settingsSerializer.d.ts +6 -0
- package/dist/docx/serializer/settingsSerializer.js +16 -0
- package/dist/docx/serializer/stylesSerializer.d.ts +6 -0
- package/dist/docx/serializer/stylesSerializer.js +56 -0
- package/dist/docx/serializer/tableSerializer.js +25 -26
- package/dist/docx/serializer/themeSerializer.d.ts +6 -0
- package/dist/docx/serializer/themeSerializer.js +36 -0
- package/dist/docx/settingsParser.js +46 -0
- package/dist/docx/styleParser.js +26 -1
- package/dist/docx/tableParser.js +11 -1
- package/dist/docx/vmlImageParser.js +1 -0
- package/dist/i18n/messages/catalogs.gen.d.ts +5916 -5916
- package/dist/i18n/messages/catalogs.gen.js +5910 -5910
- package/dist/index.d.ts +6 -4
- package/dist/index.js +5 -3
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +3 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +3 -1
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +3 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +6 -1
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +14 -2
- package/dist/layout-bridge/convert/toFlowBlocks.js +51 -14
- package/dist/layout-bridge/engine/measuring/index.d.ts +2 -1
- package/dist/layout-bridge/engine/measuring/index.js +2 -1
- package/dist/layout-engine/index.js +36 -28
- package/dist/layout-engine/measure/cache.js +11 -3
- package/dist/layout-engine/measure/font-metrics.worker.js +1 -0
- package/dist/layout-engine/measure/index.d.ts +2 -1
- package/dist/layout-engine/measure/index.js +2 -1
- package/dist/layout-engine/measure/lineBreakProvider.d.ts +33 -0
- package/dist/layout-engine/measure/lineBreakProvider.js +252 -0
- package/dist/layout-engine/measure/lineBreaks.d.ts +7 -2
- package/dist/layout-engine/measure/lineBreaks.js +11 -18
- package/dist/layout-engine/measure/listMarkerWidth.d.ts +1 -0
- package/dist/layout-engine/measure/listMarkerWidth.js +12 -6
- package/dist/layout-engine/measure/measureBlocks.d.ts +1 -2
- package/dist/layout-engine/measure/measureBlocks.js +6 -36
- package/dist/layout-engine/measure/measureContainer.js +32 -9
- package/dist/layout-engine/measure/measureHelpers.js +5 -2
- package/dist/layout-engine/measure/measureParagraph.js +335 -72
- package/dist/layout-engine/measure/measureTypes.d.ts +2 -1
- package/dist/layout-engine/measure/measureWorker.d.ts +2 -2
- package/dist/layout-engine/measure/measureWorker.js +8 -19
- package/dist/layout-engine/measure/measureWorkerProtocol.d.ts +3 -14
- package/dist/layout-engine/measure/tableCellFloating.d.ts +10 -3
- package/dist/layout-engine/measure/tableCellFloating.js +37 -29
- package/dist/layout-engine/measure/tableCellFlow.d.ts +27 -0
- package/dist/layout-engine/measure/tableCellFlow.js +73 -0
- package/dist/layout-engine/measure/tableCellGrid.js +1 -1
- package/dist/layout-engine/measure/textMeasurementPolicy.d.ts +18 -0
- package/dist/layout-engine/measure/textMeasurementPolicy.js +24 -0
- package/dist/layout-engine/renderedBreakReconciliation.d.ts +6 -1
- package/dist/layout-engine/renderedBreakReconciliation.js +34 -11
- package/dist/layout-engine/tableRowBreak.d.ts +5 -2
- package/dist/layout-engine/tableRowBreak.js +62 -29
- package/dist/layout-engine/types.d.ts +40 -7
- package/dist/layout-painter/anchoredImagePosition.d.ts +23 -0
- package/dist/layout-painter/anchoredImagePosition.js +95 -0
- package/dist/layout-painter/borderStroke.d.ts +23 -0
- package/dist/layout-painter/borderStroke.js +39 -0
- package/dist/layout-painter/renderImage.d.ts +5 -4
- package/dist/layout-painter/renderImage.js +18 -4
- package/dist/layout-painter/renderPage.d.ts +2 -27
- package/dist/layout-painter/renderPage.js +13 -99
- package/dist/layout-painter/renderParagraph.js +41 -23
- package/dist/layout-painter/renderTable.d.ts +2 -0
- package/dist/layout-painter/renderTable.js +223 -43
- package/dist/managers/DocumentLoaderManager.d.ts +1 -1
- package/dist/managers/DocumentLoaderManager.js +2 -2
- package/dist/prosemirror/attrs/index.d.ts +4 -2
- package/dist/prosemirror/attrs/index.js +21 -2
- package/dist/prosemirror/commands/propertyChangeScope.js +1 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +33 -18
- package/dist/prosemirror/conversion/toProseDoc.js +50 -18
- package/dist/prosemirror/extensions/StarterKit.js +2 -0
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +7 -2
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +1 -1
- package/dist/prosemirror/extensions/features/ListExtension.js +1 -0
- package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +1 -0
- package/dist/prosemirror/extensions/marks/HighlightExtension.js +1 -1
- package/dist/prosemirror/extensions/marks/LanguageExtension.d.ts +7 -0
- package/dist/prosemirror/extensions/marks/LanguageExtension.js +30 -0
- package/dist/prosemirror/extensions/marks/RunShadingExtension.js +1 -1
- package/dist/prosemirror/extensions/marks/TextColorExtension.js +1 -1
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +1 -1
- package/dist/prosemirror/extensions/marks/markUtils.js +12 -0
- package/dist/prosemirror/extensions/nodes/ImageExtension.js +2 -1
- package/dist/prosemirror/extensions/nodes/TableExtension.js +4 -2
- package/dist/prosemirror/schema/index.d.ts +2 -2
- package/dist/prosemirror/schema/marks.d.ts +6 -1
- package/dist/prosemirror/schema/nodes.d.ts +13 -11
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
- package/dist/prosemirror/utils/tabCalculator.d.ts +3 -1
- package/dist/prosemirror/utils/tabCalculator.js +12 -10
- package/dist/prosemirror/validation.js +4 -1
- package/dist/redline.js +13 -3
- package/dist/server.d.ts +6 -3
- package/dist/server.js +5 -2
- package/dist/style-sets/extract.d.ts +35 -0
- package/dist/style-sets/extract.js +123 -0
- package/dist/style-sets/stellaStyle.d.ts +13 -0
- package/dist/style-sets/stellaStyle.js +516 -0
- package/dist/style-sets/types.d.ts +31 -0
- package/dist/style-sets/types.js +5 -0
- package/dist/utils/createDocument.d.ts +12 -2
- package/dist/utils/createDocument.js +42 -31
- package/dist/utils/fontResolver.js +6 -6
- package/dist/utils/formatToStyle.js +1 -1
- package/dist/utils/paragraphFormattingMerge.d.ts +14 -3
- package/dist/utils/paragraphFormattingMerge.js +14 -4
- package/package.json +5 -1
- package/dist/docx/capabilities.d.ts +0 -41
- package/dist/docx/capabilities.js +0 -322
package/README.md
CHANGED
|
@@ -32,6 +32,45 @@ bun add @stll/folio-core
|
|
|
32
32
|
| `@stll/folio-core/server` | DOM-free helpers for server-side use (block-id derivation, document creation, re-zip) |
|
|
33
33
|
| `@stll/folio-core/*` | the source-mirrored module tree (e.g. `@stll/folio-core/types/document`, `@stll/folio-core/prosemirror/schema`) for adapters that need lower-level building blocks |
|
|
34
34
|
|
|
35
|
+
## New documents and reusable style sets
|
|
36
|
+
|
|
37
|
+
Create a legal-shaped blank document with the built-in preset:
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import { createDocx, createEmptyDocument, createStellaStyleDocumentPreset } from "@stll/folio-core";
|
|
41
|
+
|
|
42
|
+
const document = createEmptyDocument({
|
|
43
|
+
preset: createStellaStyleDocumentPreset(),
|
|
44
|
+
});
|
|
45
|
+
const docx = await createDocx(document);
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Style sets are content-free JSON values. Inspect a source file before presenting
|
|
49
|
+
styles for selection, extract the selected dependency closure, persist the
|
|
50
|
+
result, and load it into any later document:
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import {
|
|
54
|
+
createEmptyDocument,
|
|
55
|
+
extractDocumentStyleSetFromDocx,
|
|
56
|
+
inspectDocumentStylesFromDocx,
|
|
57
|
+
} from "@stll/folio-core";
|
|
58
|
+
|
|
59
|
+
const catalog = await inspectDocumentStylesFromDocx(sourceDocx);
|
|
60
|
+
const styleSet = await extractDocumentStyleSetFromDocx(sourceDocx, {
|
|
61
|
+
name: "Firm contract styles",
|
|
62
|
+
styleIds: catalog.styles
|
|
63
|
+
.filter(({ role }) => role === "default" || role === "quick")
|
|
64
|
+
.map(({ styleId }) => styleId),
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const document = createEmptyDocument({ styleSet });
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Extraction excludes document content, metadata, relationships, media, comments,
|
|
71
|
+
and revision data. It keeps only the selected styles and the numbering, theme,
|
|
72
|
+
font-table, and settings data required to reproduce their formatting.
|
|
73
|
+
|
|
35
74
|
## License
|
|
36
75
|
|
|
37
76
|
[Apache-2.0](./LICENSE)
|
package/dist/ai-edits/apply.js
CHANGED
|
@@ -678,10 +678,24 @@ const resolveOperation = ({ snapshot, operation, liveBlocks, liveBlocksByParaId,
|
|
|
678
678
|
}
|
|
679
679
|
if (operation.type === "deleteBlock" || operation.type === "replaceBlock") {
|
|
680
680
|
const range = getTextRangeFromCleanBlock(cleanBlock);
|
|
681
|
-
if (!range)
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
681
|
+
if (!range) {
|
|
682
|
+
const insertionPoint = cleanBlock.offsets.at(0);
|
|
683
|
+
if (operation.type === "replaceBlock" && currentText.length === 0 && operation.text.length > 0 && insertionPoint !== void 0) return {
|
|
684
|
+
type: "resolved",
|
|
685
|
+
operation: {
|
|
686
|
+
operation,
|
|
687
|
+
from: insertionPoint,
|
|
688
|
+
to: insertionPoint,
|
|
689
|
+
blockFrom,
|
|
690
|
+
blockTo,
|
|
691
|
+
blockNode
|
|
692
|
+
}
|
|
693
|
+
};
|
|
694
|
+
return {
|
|
695
|
+
type: "skip",
|
|
696
|
+
reason: "unsupportedBlock"
|
|
697
|
+
};
|
|
698
|
+
}
|
|
685
699
|
if (operation.type === "replaceBlock" && operation.text === currentText) return {
|
|
686
700
|
type: "skip",
|
|
687
701
|
reason: "noopOperation"
|
|
@@ -39,10 +39,22 @@ type FolioDocumentStoryHandle = {
|
|
|
39
39
|
type: "footnote" | "endnote";
|
|
40
40
|
noteId: number;
|
|
41
41
|
};
|
|
42
|
+
type FolioEditableDocumentStoryHandle = Exclude<FolioDocumentStoryHandle, {
|
|
43
|
+
type: "footnote" | "endnote";
|
|
44
|
+
}>;
|
|
42
45
|
type FolioDocumentStory = {
|
|
43
46
|
handle: FolioDocumentStoryHandle;
|
|
44
47
|
text: string;
|
|
45
48
|
};
|
|
49
|
+
declare const FolioDocumentStoryNotFoundError_base: import("better-result").TaggedErrorClass<"FolioDocumentStoryNotFoundError", {
|
|
50
|
+
message: string;
|
|
51
|
+
story: FolioEditableDocumentStoryHandle;
|
|
52
|
+
}>;
|
|
53
|
+
declare class FolioDocumentStoryNotFoundError extends FolioDocumentStoryNotFoundError_base {}
|
|
54
|
+
type FolioApplyDocumentOperationsToStoryOptions = FolioApplyDocumentOperationsOptions & {
|
|
55
|
+
story: FolioEditableDocumentStoryHandle;
|
|
56
|
+
batch: FolioDocumentOperationBatch;
|
|
57
|
+
};
|
|
46
58
|
/** Filter for {@link FolioDocxReviewer.getChanges}. */
|
|
47
59
|
type FolioReviewChangeFilter = {
|
|
48
60
|
author?: string;
|
|
@@ -97,6 +109,7 @@ declare class FolioDocxReviewer {
|
|
|
97
109
|
private readonly baseDocument;
|
|
98
110
|
private readonly originalBuffer;
|
|
99
111
|
private state;
|
|
112
|
+
private readonly headerFooterStoryStates;
|
|
100
113
|
private readonly createdComments;
|
|
101
114
|
private readonly documentOperationUndoEntries;
|
|
102
115
|
/**
|
|
@@ -116,6 +129,8 @@ declare class FolioDocxReviewer {
|
|
|
116
129
|
* the anchor map the apply layer resolves operations against.
|
|
117
130
|
*/
|
|
118
131
|
snapshot(): FolioAIEditSnapshot;
|
|
132
|
+
/** Snapshot one editable story into stable, operation-ready blocks. */
|
|
133
|
+
snapshotStory(story: FolioEditableDocumentStoryHandle): FolioAIEditSnapshot | null;
|
|
119
134
|
/**
|
|
120
135
|
* Apply operations against the current state. Reuses the live-editor applier
|
|
121
136
|
* verbatim via a headless `{ state, dispatch }` seam; the resulting state
|
|
@@ -129,6 +144,12 @@ declare class FolioDocxReviewer {
|
|
|
129
144
|
* edit semantics.
|
|
130
145
|
*/
|
|
131
146
|
applyDocumentOperations(batch: FolioDocumentOperationBatch, options?: FolioApplyDocumentOperationsOptions): FolioDocumentOperationResult;
|
|
147
|
+
/** Apply a versioned operation batch to the main story, a header, or a footer. */
|
|
148
|
+
applyDocumentOperationsToStory({
|
|
149
|
+
story,
|
|
150
|
+
batch,
|
|
151
|
+
snapshot
|
|
152
|
+
}: FolioApplyDocumentOperationsToStoryOptions): FolioDocumentOperationResult;
|
|
132
153
|
private applyDocumentOperationsInternal;
|
|
133
154
|
/** Undo the latest unchanged document-operation batch and its created comments. */
|
|
134
155
|
undoDocumentOperations(undoHandle: FolioDocumentOperationUndoHandle): FolioDocumentOperationUndoResult;
|
|
@@ -153,9 +174,9 @@ declare class FolioDocxReviewer {
|
|
|
153
174
|
/**
|
|
154
175
|
* Header / footer and footnote / endnote text as labeled, LLM-ready lines,
|
|
155
176
|
* one per non-empty part: `[header default] …`, `[footer default] …`,
|
|
156
|
-
* `[footnote #N] …`, `[endnote #N] …`.
|
|
157
|
-
*
|
|
158
|
-
*
|
|
177
|
+
* `[footnote #N] …`, `[endnote #N] …`. Header and footer lines reflect
|
|
178
|
+
* in-memory edits; note bodies reflect the parsed source. Empty parts and
|
|
179
|
+
* separator notes are omitted.
|
|
159
180
|
*/
|
|
160
181
|
getNotesAsText(): string;
|
|
161
182
|
/** Discover every readable document story through a typed, serializable handle. */
|
|
@@ -239,6 +260,12 @@ declare class FolioDocxReviewer {
|
|
|
239
260
|
* is the graceful handling — no separate error surface is needed here.
|
|
240
261
|
*/
|
|
241
262
|
private trySelectiveSave;
|
|
263
|
+
private getEditableStoryState;
|
|
264
|
+
private requireEditableStoryState;
|
|
265
|
+
private setEditableStoryState;
|
|
266
|
+
private getHeaderFooterStory;
|
|
267
|
+
private getHeaderFooterStoryText;
|
|
268
|
+
private mergeEditedHeaderFooterStories;
|
|
242
269
|
/**
|
|
243
270
|
* Count every tracked change an accept-all / reject-all sweep resolves: the
|
|
244
271
|
* inline insertion / deletion groups {@link getChanges} enumerates, plus the
|
|
@@ -283,4 +310,4 @@ type ApplyFolioAIEditsToBufferResult = FolioAIEditApplyResult & {
|
|
|
283
310
|
*/
|
|
284
311
|
declare const applyFolioAIEditsToBuffer: (buffer: ArrayBuffer, operations: FolioAIEditOperation[], options?: ApplyFolioAIEditsToBufferOptions) => Promise<ApplyFolioAIEditsToBufferResult>;
|
|
285
312
|
//#endregion
|
|
286
|
-
export { ApplyFolioAIEditsToBufferOptions, ApplyFolioAIEditsToBufferResult, FolioApplyDocumentOperationsOptions, FolioApplyOperationsOptions, FolioDocumentStory, FolioDocumentStoryHandle, FolioDocxReviewer, FolioDocxReviewerOptions, FolioGetContentAsTextOptions, type FolioReviewChange, FolioReviewChangeFilter, type FolioReviewChangeKind, FolioReviewComment, FolioReviewCommentFilter, FolioReviewCommentReply, FolioReviewReplyInput, applyFolioAIEditsToBuffer };
|
|
313
|
+
export { ApplyFolioAIEditsToBufferOptions, ApplyFolioAIEditsToBufferResult, FolioApplyDocumentOperationsOptions, FolioApplyDocumentOperationsToStoryOptions, FolioApplyOperationsOptions, FolioDocumentStory, FolioDocumentStoryHandle, FolioDocumentStoryNotFoundError, FolioDocxReviewer, FolioDocxReviewerOptions, FolioEditableDocumentStoryHandle, FolioGetContentAsTextOptions, type FolioReviewChange, FolioReviewChangeFilter, type FolioReviewChangeKind, FolioReviewComment, FolioReviewCommentFilter, FolioReviewCommentReply, FolioReviewReplyInput, applyFolioAIEditsToBuffer };
|
|
@@ -2,18 +2,19 @@ import { buildAnnotatedBlockText } from "./clean-text.js";
|
|
|
2
2
|
import { createFolioAIEditSnapshot, normalizeFolioAIBlockText } from "./snapshot.js";
|
|
3
3
|
import { applyFolioDocumentOperations } from "../document-operations.js";
|
|
4
4
|
import { getEndnoteText, getFootnoteText, isSeparatorEndnote, isSeparatorFootnote } from "../docx/footnoteParser.js";
|
|
5
|
+
import { getHeaderFooterText } from "../docx/headerFooterParser.js";
|
|
6
|
+
import { parseDocx } from "../docx/parser.js";
|
|
5
7
|
import { deterministicHexId } from "../utils/hexId.js";
|
|
6
8
|
import { repackDocx } from "../docx/rezip.js";
|
|
7
9
|
import { getCommentAnchorsFromDoc, getTrackedChangesFromDoc } from "./read.js";
|
|
8
10
|
import { createReply } from "../docx/replyToComment.js";
|
|
9
11
|
import { attemptSelectiveSave } from "../docx/selectiveSave.js";
|
|
10
|
-
import { getHeaderFooterText } from "../docx/headerFooterParser.js";
|
|
11
|
-
import { parseDocx } from "../docx/parser.js";
|
|
12
12
|
import { acceptAIEditRevision, acceptAllChanges, rejectAIEditRevision, rejectAllChanges } from "../prosemirror/commands/comments.js";
|
|
13
|
-
import { updateDocumentContent } from "../prosemirror/conversion/fromProseDoc.js";
|
|
13
|
+
import { proseDocToBlocks, updateDocumentContent } from "../prosemirror/conversion/fromProseDoc.js";
|
|
14
14
|
import { getChangedParagraphIds, hasStructuralChanges, hasUntrackedChanges, ignoreTrackedChanges } from "../prosemirror/extensions/features/ParagraphChangeTrackerExtension.js";
|
|
15
15
|
import { schema, singletonManager } from "../prosemirror/schema/index.js";
|
|
16
|
-
import { toProseDoc } from "../prosemirror/conversion/toProseDoc.js";
|
|
16
|
+
import { headerFooterToProseDoc, toProseDoc } from "../prosemirror/conversion/toProseDoc.js";
|
|
17
|
+
import { TaggedError } from "better-result";
|
|
17
18
|
import { EditorState } from "prosemirror-state";
|
|
18
19
|
//#region src/ai-edits/headless.ts
|
|
19
20
|
/**
|
|
@@ -33,8 +34,8 @@ import { EditorState } from "prosemirror-state";
|
|
|
33
34
|
* paragraphs in `document.xml` (leaving every untouched part byte-exact), with
|
|
34
35
|
* a full repack as the fallback for structural edits.
|
|
35
36
|
*
|
|
36
|
-
* Scope:
|
|
37
|
-
*
|
|
37
|
+
* Scope: main, header, and footer blocks. Footnote and endnote bodies build on
|
|
38
|
+
* the note serialization path separately.
|
|
38
39
|
*/
|
|
39
40
|
/**
|
|
40
41
|
* Standalone comment-id allocator for the reviewer. The React editor uses
|
|
@@ -114,6 +115,9 @@ const ensureDeterministicParaIdsInState = (state) => {
|
|
|
114
115
|
tr.setMeta("addToHistory", false);
|
|
115
116
|
return state.apply(tr);
|
|
116
117
|
};
|
|
118
|
+
var FolioDocumentStoryNotFoundError = class extends TaggedError("FolioDocumentStoryNotFoundError")() {};
|
|
119
|
+
const MAIN_STORY = Object.freeze({ type: "main" });
|
|
120
|
+
const headerFooterStoryKey = ({ type, relationshipId }) => `${type}:${relationshipId}`;
|
|
117
121
|
/**
|
|
118
122
|
* One LLM-ready line for a block: `[<blockId>] text`, with an `(h<level>)` tag
|
|
119
123
|
* for headings and the list marker for list items, so a model can copy the
|
|
@@ -162,6 +166,7 @@ var FolioDocxReviewer = class FolioDocxReviewer {
|
|
|
162
166
|
baseDocument;
|
|
163
167
|
originalBuffer;
|
|
164
168
|
state;
|
|
169
|
+
headerFooterStoryStates = /* @__PURE__ */ new Map();
|
|
165
170
|
createdComments = [];
|
|
166
171
|
documentOperationUndoEntries = [];
|
|
167
172
|
/**
|
|
@@ -206,6 +211,11 @@ var FolioDocxReviewer = class FolioDocxReviewer {
|
|
|
206
211
|
snapshot() {
|
|
207
212
|
return createFolioAIEditSnapshot(this.state.doc);
|
|
208
213
|
}
|
|
214
|
+
/** Snapshot one editable story into stable, operation-ready blocks. */
|
|
215
|
+
snapshotStory(story) {
|
|
216
|
+
const state = this.getEditableStoryState(story);
|
|
217
|
+
return state ? createFolioAIEditSnapshot(state.doc) : null;
|
|
218
|
+
}
|
|
209
219
|
/**
|
|
210
220
|
* Apply operations against the current state. Reuses the live-editor applier
|
|
211
221
|
* verbatim via a headless `{ state, dispatch }` seam; the resulting state
|
|
@@ -213,10 +223,15 @@ var FolioDocxReviewer = class FolioDocxReviewer {
|
|
|
213
223
|
*/
|
|
214
224
|
applyOperations(operations, options = {}) {
|
|
215
225
|
const { applied, skipped } = this.applyDocumentOperationsInternal({
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
226
|
+
story: MAIN_STORY,
|
|
227
|
+
batch: {
|
|
228
|
+
version: 1,
|
|
229
|
+
operations,
|
|
230
|
+
mode: options.mode ?? "tracked-changes"
|
|
231
|
+
},
|
|
232
|
+
...options.snapshot !== void 0 && { snapshot: options.snapshot },
|
|
233
|
+
createUndoEntry: false
|
|
234
|
+
});
|
|
220
235
|
return {
|
|
221
236
|
applied,
|
|
222
237
|
skipped
|
|
@@ -229,21 +244,36 @@ var FolioDocxReviewer = class FolioDocxReviewer {
|
|
|
229
244
|
* edit semantics.
|
|
230
245
|
*/
|
|
231
246
|
applyDocumentOperations(batch, options = {}) {
|
|
232
|
-
return this.applyDocumentOperationsInternal(
|
|
247
|
+
return this.applyDocumentOperationsInternal({
|
|
248
|
+
story: MAIN_STORY,
|
|
249
|
+
batch,
|
|
250
|
+
...options.snapshot !== void 0 && { snapshot: options.snapshot },
|
|
251
|
+
createUndoEntry: true
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
/** Apply a versioned operation batch to the main story, a header, or a footer. */
|
|
255
|
+
applyDocumentOperationsToStory({ story, batch, snapshot }) {
|
|
256
|
+
return this.applyDocumentOperationsInternal({
|
|
257
|
+
story,
|
|
258
|
+
batch,
|
|
259
|
+
...snapshot !== void 0 && { snapshot },
|
|
260
|
+
createUndoEntry: true
|
|
261
|
+
});
|
|
233
262
|
}
|
|
234
|
-
applyDocumentOperationsInternal(batch,
|
|
235
|
-
const beforeState = this.
|
|
263
|
+
applyDocumentOperationsInternal({ story, batch, snapshot, createUndoEntry }) {
|
|
264
|
+
const beforeState = this.requireEditableStoryState(story);
|
|
236
265
|
const createdCommentsLengthBefore = this.createdComments.length;
|
|
237
266
|
const view = {
|
|
238
|
-
state:
|
|
267
|
+
state: beforeState,
|
|
239
268
|
dispatch: (transaction) => {
|
|
240
269
|
view.state = view.state.apply(transaction);
|
|
241
270
|
}
|
|
242
271
|
};
|
|
243
272
|
const result = applyFolioDocumentOperations({
|
|
244
273
|
view,
|
|
245
|
-
snapshot:
|
|
274
|
+
snapshot: snapshot ?? createFolioAIEditSnapshot(beforeState.doc),
|
|
246
275
|
batch,
|
|
276
|
+
story: story.type === "main" ? "main" : story,
|
|
247
277
|
author: this.author,
|
|
248
278
|
createCommentId: (text) => {
|
|
249
279
|
const comment = createReviewerComment(text, this.author);
|
|
@@ -255,11 +285,12 @@ var FolioDocxReviewer = class FolioDocxReviewer {
|
|
|
255
285
|
id: `headless-${String(undoHandleCursor++)}`
|
|
256
286
|
}) }
|
|
257
287
|
});
|
|
258
|
-
this.
|
|
288
|
+
this.setEditableStoryState(story, view.state);
|
|
259
289
|
if (result.undoHandle !== null) this.documentOperationUndoEntries.push({
|
|
260
290
|
undoHandle: result.undoHandle,
|
|
291
|
+
story,
|
|
261
292
|
beforeState,
|
|
262
|
-
afterState:
|
|
293
|
+
afterState: view.state,
|
|
263
294
|
createdCommentsLengthBefore,
|
|
264
295
|
createdCommentsLengthAfter: this.createdComments.length
|
|
265
296
|
});
|
|
@@ -284,12 +315,12 @@ var FolioDocxReviewer = class FolioDocxReviewer {
|
|
|
284
315
|
undoHandle,
|
|
285
316
|
reason: "unknownHandle"
|
|
286
317
|
};
|
|
287
|
-
if (this.
|
|
318
|
+
if (this.requireEditableStoryState(entry.story) !== entry.afterState || this.createdComments.length !== entry.createdCommentsLengthAfter) return {
|
|
288
319
|
status: "rejected",
|
|
289
320
|
undoHandle,
|
|
290
321
|
reason: "documentChanged"
|
|
291
322
|
};
|
|
292
|
-
this.
|
|
323
|
+
this.setEditableStoryState(entry.story, entry.beforeState);
|
|
293
324
|
this.createdComments.length = entry.createdCommentsLengthBefore;
|
|
294
325
|
this.documentOperationUndoEntries.pop();
|
|
295
326
|
return {
|
|
@@ -331,17 +362,21 @@ var FolioDocxReviewer = class FolioDocxReviewer {
|
|
|
331
362
|
/**
|
|
332
363
|
* Header / footer and footnote / endnote text as labeled, LLM-ready lines,
|
|
333
364
|
* one per non-empty part: `[header default] …`, `[footer default] …`,
|
|
334
|
-
* `[footnote #N] …`, `[endnote #N] …`.
|
|
335
|
-
*
|
|
336
|
-
*
|
|
365
|
+
* `[footnote #N] …`, `[endnote #N] …`. Header and footer lines reflect
|
|
366
|
+
* in-memory edits; note bodies reflect the parsed source. Empty parts and
|
|
367
|
+
* separator notes are omitted.
|
|
337
368
|
*/
|
|
338
369
|
getNotesAsText() {
|
|
339
370
|
const pkg = this.baseDocument.package;
|
|
340
371
|
const lines = [];
|
|
341
372
|
const pushHeaderFooter = (map, label) => {
|
|
342
373
|
if (!map) return;
|
|
343
|
-
for (const hf of map
|
|
344
|
-
const
|
|
374
|
+
for (const [relationshipId, hf] of map) {
|
|
375
|
+
const handle = {
|
|
376
|
+
type: label,
|
|
377
|
+
relationshipId
|
|
378
|
+
};
|
|
379
|
+
const text = this.getHeaderFooterStoryText(handle, hf);
|
|
345
380
|
if (text.length > 0) lines.push(`[${label} ${hf.hdrFtrType}] ${text}`);
|
|
346
381
|
}
|
|
347
382
|
};
|
|
@@ -366,20 +401,26 @@ var FolioDocxReviewer = class FolioDocxReviewer {
|
|
|
366
401
|
handle: { type: "main" },
|
|
367
402
|
text: this.getContentAsText()
|
|
368
403
|
}];
|
|
369
|
-
for (const [relationshipId, header] of pkg.headers ?? [])
|
|
370
|
-
handle
|
|
404
|
+
for (const [relationshipId, header] of pkg.headers ?? []) {
|
|
405
|
+
const handle = {
|
|
371
406
|
type: "header",
|
|
372
407
|
relationshipId
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
408
|
+
};
|
|
409
|
+
stories.push({
|
|
410
|
+
handle,
|
|
411
|
+
text: this.getHeaderFooterStoryText(handle, header)
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
for (const [relationshipId, footer] of pkg.footers ?? []) {
|
|
415
|
+
const handle = {
|
|
378
416
|
type: "footer",
|
|
379
417
|
relationshipId
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
|
|
418
|
+
};
|
|
419
|
+
stories.push({
|
|
420
|
+
handle,
|
|
421
|
+
text: this.getHeaderFooterStoryText(handle, footer)
|
|
422
|
+
});
|
|
423
|
+
}
|
|
383
424
|
for (const footnote of pkg.footnotes ?? []) if (!isSeparatorFootnote(footnote)) stories.push({
|
|
384
425
|
handle: {
|
|
385
426
|
type: "footnote",
|
|
@@ -537,6 +578,7 @@ var FolioDocxReviewer = class FolioDocxReviewer {
|
|
|
537
578
|
/** The current document model with edits merged back in. */
|
|
538
579
|
toDocument() {
|
|
539
580
|
const document = updateDocumentContent(this.baseDocument, this.state.doc);
|
|
581
|
+
this.mergeEditedHeaderFooterStories(document);
|
|
540
582
|
if (this.createdComments.length > 0 || this.resolvedOverrides.size > 0) document.package.document.comments = this.withResolvedOverrides([...document.package.document.comments ?? [], ...this.createdComments]);
|
|
541
583
|
return document;
|
|
542
584
|
}
|
|
@@ -572,6 +614,77 @@ var FolioDocxReviewer = class FolioDocxReviewer {
|
|
|
572
614
|
return null;
|
|
573
615
|
}
|
|
574
616
|
}
|
|
617
|
+
getEditableStoryState(story) {
|
|
618
|
+
if (story.type === "main") return this.state;
|
|
619
|
+
const key = headerFooterStoryKey(story);
|
|
620
|
+
const existing = this.headerFooterStoryStates.get(key);
|
|
621
|
+
if (existing) return existing.state;
|
|
622
|
+
const source = this.getHeaderFooterStory(story);
|
|
623
|
+
if (!source) return null;
|
|
624
|
+
const state = ensureDeterministicParaIdsInState(EditorState.create({
|
|
625
|
+
schema,
|
|
626
|
+
doc: headerFooterToProseDoc(source.content, {
|
|
627
|
+
...this.baseDocument.package.styles !== void 0 && { styles: this.baseDocument.package.styles },
|
|
628
|
+
...this.baseDocument.package.theme !== void 0 && { theme: this.baseDocument.package.theme }
|
|
629
|
+
}),
|
|
630
|
+
plugins: singletonManager.getPlugins()
|
|
631
|
+
}));
|
|
632
|
+
this.headerFooterStoryStates.set(key, {
|
|
633
|
+
handle: story,
|
|
634
|
+
initialState: state,
|
|
635
|
+
state
|
|
636
|
+
});
|
|
637
|
+
return state;
|
|
638
|
+
}
|
|
639
|
+
requireEditableStoryState(story) {
|
|
640
|
+
const state = this.getEditableStoryState(story);
|
|
641
|
+
if (state) return state;
|
|
642
|
+
throw new FolioDocumentStoryNotFoundError({
|
|
643
|
+
message: `Document story ${JSON.stringify(story)} was not found.`,
|
|
644
|
+
story
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
setEditableStoryState(story, state) {
|
|
648
|
+
if (story.type === "main") {
|
|
649
|
+
this.state = state;
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
const entry = this.headerFooterStoryStates.get(headerFooterStoryKey(story));
|
|
653
|
+
if (!entry) throw new FolioDocumentStoryNotFoundError({
|
|
654
|
+
message: `Document story ${JSON.stringify(story)} was not found.`,
|
|
655
|
+
story
|
|
656
|
+
});
|
|
657
|
+
entry.state = state;
|
|
658
|
+
}
|
|
659
|
+
getHeaderFooterStory(story) {
|
|
660
|
+
return (story.type === "header" ? this.baseDocument.package.headers : this.baseDocument.package.footers)?.get(story.relationshipId);
|
|
661
|
+
}
|
|
662
|
+
getHeaderFooterStoryText(story, source) {
|
|
663
|
+
const state = this.headerFooterStoryStates.get(headerFooterStoryKey(story))?.state;
|
|
664
|
+
return normalizeFolioAIBlockText(state?.doc.textContent ?? getHeaderFooterText(source));
|
|
665
|
+
}
|
|
666
|
+
mergeEditedHeaderFooterStories(document) {
|
|
667
|
+
let headers;
|
|
668
|
+
let footers;
|
|
669
|
+
for (const entry of this.headerFooterStoryStates.values()) {
|
|
670
|
+
if (entry.state === entry.initialState) continue;
|
|
671
|
+
const source = this.getHeaderFooterStory(entry.handle);
|
|
672
|
+
if (!source) continue;
|
|
673
|
+
const edited = {
|
|
674
|
+
...source,
|
|
675
|
+
content: proseDocToBlocks(entry.state.doc)
|
|
676
|
+
};
|
|
677
|
+
if (entry.handle.type === "header") {
|
|
678
|
+
headers ??= new Map(document.package.headers);
|
|
679
|
+
headers.set(entry.handle.relationshipId, edited);
|
|
680
|
+
continue;
|
|
681
|
+
}
|
|
682
|
+
footers ??= new Map(document.package.footers);
|
|
683
|
+
footers.set(entry.handle.relationshipId, edited);
|
|
684
|
+
}
|
|
685
|
+
if (headers) document.package.headers = headers;
|
|
686
|
+
if (footers) document.package.footers = footers;
|
|
687
|
+
}
|
|
575
688
|
/**
|
|
576
689
|
* Count every tracked change an accept-all / reject-all sweep resolves: the
|
|
577
690
|
* inline insertion / deletion groups {@link getChanges} enumerates, plus the
|
|
@@ -654,4 +767,4 @@ const applyFolioAIEditsToBuffer = async (buffer, operations, options = {}) => {
|
|
|
654
767
|
};
|
|
655
768
|
};
|
|
656
769
|
//#endregion
|
|
657
|
-
export { FolioDocxReviewer, applyFolioAIEditsToBuffer };
|
|
770
|
+
export { FolioDocumentStoryNotFoundError, FolioDocxReviewer, applyFolioAIEditsToBuffer };
|
package/dist/ai-edits/index.d.ts
CHANGED
|
@@ -2,11 +2,11 @@ import { FolioAIBlock, FolioAIBlockAnchor, FolioAIBlockKind, FolioAIBlockPreview
|
|
|
2
2
|
import { FolioAIEditView, applyFolioAIEditOperations } from "./apply.js";
|
|
3
3
|
import { DocPositionRange, clampRangeToDocSize, resolveFolioAIBlockRange, resolveFolioAITextRange } from "./blockRange.js";
|
|
4
4
|
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, FolioDocumentOperationType, FolioDocumentOperationUndoFailureReason, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch } from "../document-operations.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
6
|
import { FolioCommentAnchor, FolioReviewChange, FolioReviewChangeKind, getCommentAnchorsFromDoc, getTrackedChangesFromDoc } from "./read.js";
|
|
7
|
-
import { FolioDocumentStory, FolioDocumentStoryHandle } from "./headless.js";
|
|
7
|
+
import { FolioApplyDocumentOperationsToStoryOptions, FolioDocumentStory, FolioDocumentStoryHandle, FolioDocumentStoryNotFoundError, FolioEditableDocumentStoryHandle } from "./headless.js";
|
|
8
8
|
import { createFolioAIEditSnapshot, createFolioAITextRangeHandle, hashFolioAIBlockText, normalizeFolioAIBlockText } from "./snapshot.js";
|
|
9
9
|
import { getFolioDocumentOutline, readFolioDocumentSection } from "./scoped-reading.js";
|
|
10
10
|
import { getFolioParaIdFromBlockId } from "../types/block-id.js";
|
|
11
11
|
import { WordDiffSegment, diffWordSegments } from "./word-diff.js";
|
|
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, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyResult, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAIEditView, type FolioAIInlineFormatting, type FolioAISignatureParty, type FolioAITextRangeHandle, type FolioCommentAnchor, type FolioDocumentNavigationTarget, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationStatus, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocumentOutline, type FolioDocumentOutlineEntry, type FolioDocumentSection, type FolioDocumentSectionHandle, type FolioDocumentSectionReadResult, type FolioDocumentStory, type FolioDocumentStoryHandle, type FolioReviewChange, type FolioReviewChangeKind, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, type WordDiffSegment, applyFolioAIEditOperations, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, buildAnnotatedBlockText, clampRangeToDocSize, createFolioAIEditSnapshot, createFolioAITextRangeHandle, diffWordSegments, getCommentAnchorsFromDoc, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioDocumentOutline, getFolioParaIdFromBlockId, getTrackedChangesFromDoc, hashFolioAIBlockText, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, readFolioDocumentSection, resolveFolioAIBlockRange, resolveFolioAITextRange };
|
|
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, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyResult, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAIEditView, type FolioAIInlineFormatting, type FolioAISignatureParty, type FolioAITextRangeHandle, type 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 FolioReviewChange, type FolioReviewChangeKind, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, type WordDiffSegment, applyFolioAIEditOperations, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, buildAnnotatedBlockText, clampRangeToDocSize, createFolioAIEditSnapshot, createFolioAITextRangeHandle, diffWordSegments, getCommentAnchorsFromDoc, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioDocumentOutline, getFolioParaIdFromBlockId, getTrackedChangesFromDoc, hashFolioAIBlockText, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, readFolioDocumentSection, resolveFolioAIBlockRange, resolveFolioAITextRange };
|
package/dist/ai-edits/index.js
CHANGED
|
@@ -7,4 +7,5 @@ import { FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT
|
|
|
7
7
|
import { clampRangeToDocSize, resolveFolioAIBlockRange, resolveFolioAITextRange } from "./blockRange.js";
|
|
8
8
|
import { getCommentAnchorsFromDoc, getTrackedChangesFromDoc } from "./read.js";
|
|
9
9
|
import { getFolioDocumentOutline, readFolioDocumentSection } from "./scoped-reading.js";
|
|
10
|
-
|
|
10
|
+
import { FolioDocumentStoryNotFoundError } from "./headless.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, FolioDocumentStoryNotFoundError, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioAIEditOperations, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, buildAnnotatedBlockText, clampRangeToDocSize, createFolioAIEditSnapshot, createFolioAITextRangeHandle, diffWordSegments, getCommentAnchorsFromDoc, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioDocumentOutline, getFolioParaIdFromBlockId, getTrackedChangesFromDoc, hashFolioAIBlockText, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, readFolioDocumentSection, resolveFolioAIBlockRange, resolveFolioAITextRange };
|
|
@@ -22,12 +22,28 @@ const createFolioAIEditSnapshot = (doc) => {
|
|
|
22
22
|
const draftBlocks = [];
|
|
23
23
|
const hashCounts = /* @__PURE__ */ new Map();
|
|
24
24
|
const usedBlockIds = /* @__PURE__ */ new Set();
|
|
25
|
+
const emptyAnchorState = {
|
|
26
|
+
candidate: null,
|
|
27
|
+
textblockCount: 0
|
|
28
|
+
};
|
|
25
29
|
let blockIndex = 0;
|
|
26
|
-
doc.descendants((node, pos) => {
|
|
30
|
+
doc.descendants((node, pos, parent) => {
|
|
27
31
|
if (!node.isTextblock) return;
|
|
28
32
|
const { text } = buildCleanBlockText(node, pos);
|
|
29
33
|
const normalizedText = normalizeFolioAIBlockText(text);
|
|
30
|
-
if (normalizedText.length === 0)
|
|
34
|
+
if (normalizedText.length === 0) {
|
|
35
|
+
if (parent?.type !== doc.type) return;
|
|
36
|
+
emptyAnchorState.textblockCount++;
|
|
37
|
+
if (emptyAnchorState.candidate === null) {
|
|
38
|
+
const paraIdAttr = node.attrs["paraId"];
|
|
39
|
+
emptyAnchorState.candidate = {
|
|
40
|
+
from: pos,
|
|
41
|
+
to: pos + node.nodeSize,
|
|
42
|
+
paraId: typeof paraIdAttr === "string" && paraIdAttr.length > 0 ? paraIdAttr : null
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
31
47
|
const textHash = hashFolioAIBlockText(normalizedText);
|
|
32
48
|
hashCounts.set(textHash, (hashCounts.get(textHash) ?? 0) + 1);
|
|
33
49
|
blockIndex++;
|
|
@@ -72,10 +88,31 @@ const createFolioAIEditSnapshot = (doc) => {
|
|
|
72
88
|
hashOccurrenceCount: hashCounts.get(draft.anchor.textHash) ?? 0
|
|
73
89
|
};
|
|
74
90
|
}
|
|
75
|
-
|
|
91
|
+
const emptyAnchorCandidate = emptyAnchorState.candidate;
|
|
92
|
+
if (blocks.length > 0 || emptyAnchorCandidate === null) return {
|
|
76
93
|
blocks,
|
|
77
94
|
anchors
|
|
78
95
|
};
|
|
96
|
+
const emptyDocumentAnchorId = deriveBlockId({
|
|
97
|
+
paraId: emptyAnchorCandidate.paraId,
|
|
98
|
+
index: 1,
|
|
99
|
+
taken: usedBlockIds
|
|
100
|
+
});
|
|
101
|
+
const normalizedText = "";
|
|
102
|
+
anchors[emptyDocumentAnchorId] = {
|
|
103
|
+
id: emptyDocumentAnchorId,
|
|
104
|
+
from: emptyAnchorCandidate.from,
|
|
105
|
+
to: emptyAnchorCandidate.to,
|
|
106
|
+
text: "",
|
|
107
|
+
normalizedText,
|
|
108
|
+
textHash: hashFolioAIBlockText(normalizedText),
|
|
109
|
+
hashOccurrenceCount: emptyAnchorState.textblockCount
|
|
110
|
+
};
|
|
111
|
+
return {
|
|
112
|
+
blocks,
|
|
113
|
+
anchors,
|
|
114
|
+
emptyDocumentAnchorId
|
|
115
|
+
};
|
|
79
116
|
};
|
|
80
117
|
const getBlockKind = (node, headingLevel) => {
|
|
81
118
|
const listMarker = node.attrs["listMarker"];
|
package/dist/ai-edits/types.d.ts
CHANGED
|
@@ -21,7 +21,8 @@ type FolioAIBlock = {
|
|
|
21
21
|
};
|
|
22
22
|
type FolioAIEditSnapshot = {
|
|
23
23
|
blocks: FolioAIBlock[];
|
|
24
|
-
anchors: Record<string, FolioAIBlockAnchor>;
|
|
24
|
+
anchors: Record<string, FolioAIBlockAnchor>; /** Hidden empty paragraph used to anchor insertions when `blocks` is empty. */
|
|
25
|
+
emptyDocumentAnchorId?: string;
|
|
25
26
|
};
|
|
26
27
|
type FolioAIBlockAnchor = {
|
|
27
28
|
id: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FolioAIBlock, FolioAIBlockAnchor, FolioAIBlockKind, FolioAIBlockPreviewRun, FolioAIComment, FolioAIEditAppliedOperation, FolioAIEditApplyMode, FolioAIEditApplyResult, FolioAIEditOperation, FolioAIEditPrecondition, FolioAIEditReviewMeta, FolioAIEditSeverity, FolioAIEditSkipReason, FolioAIEditSkippedOperation, FolioAIEditSnapshot, FolioAISignatureParty } from "../ai-edits/types.js";
|
|
2
2
|
import { applyFolioAIEditOperations } from "../ai-edits/apply.js";
|
|
3
3
|
import { document_d_exports } from "../types/document.js";
|
|
4
|
-
import { ApplyFolioDocumentOperationsOptions, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FolioDocumentOperation, FolioDocumentOperationAffectedTarget, FolioDocumentOperationBatch, FolioDocumentOperationCapabilities, FolioDocumentOperationIssue, FolioDocumentOperationMode, FolioDocumentOperationPrecondition, FolioDocumentOperationReceipt, FolioDocumentOperationRecovery, FolioDocumentOperationResult, FolioDocumentOperationStatus, FolioDocumentOperationType, FolioDocumentOperationUndoFailureReason, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch } from "../document-operations.js";
|
|
4
|
+
import { ApplyFolioDocumentOperationsOptions, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FolioDocumentOperation, FolioDocumentOperationAffectedTarget, FolioDocumentOperationBatch, FolioDocumentOperationCapabilities, FolioDocumentOperationIssue, FolioDocumentOperationMode, FolioDocumentOperationPrecondition, FolioDocumentOperationReceipt, FolioDocumentOperationRecovery, FolioDocumentOperationResult, FolioDocumentOperationStatus, FolioDocumentOperationStory, FolioDocumentOperationType, FolioDocumentOperationUndoFailureReason, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch } from "../document-operations.js";
|
|
5
5
|
import { createFolioAIEditSnapshot, hashFolioAIBlockText, normalizeFolioAIBlockText } from "../ai-edits/snapshot.js";
|
|
6
6
|
import { DeriveBlockIdInput, FolioBlockId, deriveBlockId, getFolioParaIdFromBlockId, isFolioBlockId, isSequentialFolioBlockId } from "../types/block-id.js";
|
|
7
7
|
import { WordDiffSegment, diffWordSegments } from "../ai-edits/word-diff.js";
|
|
@@ -9,10 +9,12 @@ import { AIBarStatus, AIChatMode, AICitation, AICitationSource, AIGenerateInput,
|
|
|
9
9
|
import { ApplyResult, applySuggestions } from "../ai-suggestions/apply.js";
|
|
10
10
|
import { ResolvedAnchor, isSuggestionStale, resolveSuggestionAnchor } from "../ai-suggestions/conflict.js";
|
|
11
11
|
import { PositionalText, buildPositionalText } from "../ai-suggestions/text-positions.js";
|
|
12
|
+
import { DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DocumentPreset, DocumentStyleSet } from "../style-sets/types.js";
|
|
12
13
|
import { CreateEmptyDocumentOptions, createEmptyDocument } from "../utils/createDocument.js";
|
|
14
|
+
import { DocumentStyleCatalog, DocumentStyleCatalogEntry, ExtractDocumentStyleSetOptions, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, inspectDocumentStyles, inspectDocumentStylesFromDocx } from "../style-sets/extract.js";
|
|
15
|
+
import { STELLA_STYLE_SET_NAME, createStellaStyleDocumentPreset, createStellaStyleSet } from "../style-sets/stellaStyle.js";
|
|
13
16
|
import { createDocx } from "../docx/rezip.js";
|
|
14
|
-
import {
|
|
15
|
-
import { DocxCompatibility, DocxCompatibilityContext, DocxCompatibilityIssue, DocxCompatibilityLocation, DocxCompatibilityPart, InspectDocxCompatibilityOptions, inspectDocxCompatibility } from "../docx/compatibility.js";
|
|
17
|
+
import { DocxCompatibility, DocxCompatibilityContext, DocxCompatibilityIssue, DocxCompatibilityLocation, DocxCompatibilityPart, FolioDocxCompatibilityHost, FolioDocxCompatibilityProfile, InspectDocxCompatibilityOptions, inspectDocxCompatibility } from "../docx/compatibility.js";
|
|
16
18
|
import { setAISuggestionsMeta, setFocusedSuggestionMeta } from "../prosemirror/plugins/aiSuggestionDecorations.js";
|
|
17
19
|
import { scrollFolioPositionIntoView } from "../paged-layout/scrollToPmPosition.js";
|
|
18
20
|
import { getFolioCaretViewportRect, getFolioSelectionViewportRect } from "../paged-layout/selectionViewportRect.js";
|
|
@@ -30,4 +32,4 @@ import { getGoogleFontsEnabled, setGoogleFontsEnabled } from "../utils/fontResol
|
|
|
30
32
|
import { DOCX_CONFORMANCE_CLASSES } from "../index.js";
|
|
31
33
|
type Document = document_d_exports.Document;
|
|
32
34
|
type DocxConformanceClass = document_d_exports.DocxConformanceClass;
|
|
33
|
-
export { type AIBarStatus, type AIChatMode, type AICitation, type AICitationRange, type AICitationSource, type AIGenerateInput, type AISuggestion, type AISuggestionApplyMode, type AISuggestionPreset, type AISuggestionSeverity, type AISuggestionStatus, type AcceptAutocompleteResult, type AnonymizationMatch, type AnonymizationTerm, type ApplyFolioDocumentOperationsOptions, type ApplyResult, type AutocompleteSuggestionPluginOptions, type AutocompleteSuggestionState, type AutocompleteSuggestionStatus, type AutocompleteTriggerCheck, type AutocompleteTriggerOptions, type AutocompleteTriggerSkipReason, type CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCX_CONFORMANCE_CLASSES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocxCompatibility, type DocxCompatibilityContext, type DocxCompatibilityIssue, type DocxCompatibilityLocation, type DocxCompatibilityPart, type DocxConformanceClass, type EmbeddedFont, type EmbeddedFontParts, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES,
|
|
35
|
+
export { type AIBarStatus, type AIChatMode, type AICitation, type AICitationRange, type AICitationSource, type AIGenerateInput, type AISuggestion, type AISuggestionApplyMode, type AISuggestionPreset, type AISuggestionSeverity, type AISuggestionStatus, type AcceptAutocompleteResult, type AnonymizationMatch, type AnonymizationTerm, type ApplyFolioDocumentOperationsOptions, type ApplyResult, type AutocompleteSuggestionPluginOptions, type AutocompleteSuggestionState, type AutocompleteSuggestionStatus, type AutocompleteTriggerCheck, type AutocompleteTriggerOptions, type AutocompleteTriggerSkipReason, type CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocumentPreset, type DocumentStyleCatalog, type DocumentStyleCatalogEntry, type DocumentStyleSet, type DocxCompatibility, type DocxCompatibilityContext, type DocxCompatibilityIssue, type DocxCompatibilityLocation, type DocxCompatibilityPart, type DocxConformanceClass, type EmbeddedFont, type EmbeddedFontParts, type ExtractDocumentStyleSetOptions, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyResult, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAISignatureParty, type FolioBlockId, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationStatus, type FolioDocumentOperationStory, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocxCompatibilityHost, type FolioDocxCompatibilityProfile, type ImageMeta, type ImageRef, type InspectDocxCompatibilityOptions, InvalidFolioDocumentOperationBatchError, type MarkdownOptions, type MarkdownResult, type PositionalText, type ResolvedAnchor, STELLA_STYLE_SET_NAME, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
|