@stll/folio-core 0.55.0 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-edits/apply.js +214 -52
- package/dist/ai-edits/batch-claims.d.ts +3 -1
- package/dist/ai-edits/batch-claims.js +25 -1
- package/dist/ai-edits/headless.js +2 -2
- package/dist/ai-edits/table-row-column-mutations.js +17 -3
- package/dist/ai-edits/types.d.ts +7 -1
- package/dist/ai-suggestions/apply.js +20 -1
- package/dist/compare/compare.js +1 -0
- package/dist/compare/inline-atoms.js +40 -16
- package/dist/compare/inline-provenance.js +12 -5
- package/dist/compare/reproducible-package.d.ts +0 -17
- package/dist/compare/reproducible-package.js +12 -18
- package/dist/compat/eigenpal.d.ts +2 -1
- package/dist/compat/eigenpal.js +2 -1
- package/dist/controller/canonicalClipboard.d.ts +23 -0
- package/dist/controller/canonicalClipboard.js +482 -0
- package/dist/controller/canonicalClipboardResources.d.ts +21 -0
- package/dist/controller/canonicalClipboardResources.js +382 -0
- package/dist/controller/canonicalComments.d.ts +41 -0
- package/dist/controller/canonicalComments.js +152 -0
- package/dist/controller/canonicalComposition.d.ts +24 -3
- package/dist/controller/canonicalComposition.js +208 -48
- package/dist/controller/canonicalInlineProjection.d.ts +118 -0
- package/dist/controller/canonicalInlineProjection.js +476 -0
- package/dist/controller/canonicalInput.d.ts +13 -4
- package/dist/controller/canonicalInput.js +62 -14
- package/dist/controller/canonicalInputTimer.d.ts +16 -0
- package/dist/controller/canonicalInputTimer.js +34 -0
- package/dist/controller/canonicalPublicOperations.d.ts +48 -0
- package/dist/controller/canonicalPublicOperations.js +648 -0
- package/dist/controller/canonicalSelection.d.ts +18 -0
- package/dist/controller/canonicalSelection.js +32 -0
- package/dist/controller/canonicalSession.d.ts +27 -6
- package/dist/controller/canonicalSession.js +298 -116
- package/dist/controller/canonicalStoryEditor.d.ts +7 -3
- package/dist/controller/canonicalStoryEditor.js +27 -2
- package/dist/controller/canonicalStructure.js +57 -4
- package/dist/controller/canonicalTocSelection.d.ts +11 -0
- package/dist/controller/canonicalTocSelection.js +43 -0
- package/dist/controller/folioEditor.d.ts +2 -9
- package/dist/controller/folioEditor.js +18 -4
- package/dist/controller/headerFooterEditorManager.d.ts +2 -1
- package/dist/controller/headerFooterEditorManager.js +26 -11
- package/dist/controller/hiddenEditorApi.d.ts +24 -3
- package/dist/controller/hiddenEditorApi.js +8 -0
- package/dist/controller/hiddenEditorManager.d.ts +5 -1
- package/dist/controller/hiddenEditorManager.js +378 -43
- package/dist/controller/noteEditorManager.d.ts +2 -1
- package/dist/controller/noteEditorManager.js +29 -13
- package/dist/document-operations.d.ts +8 -1
- package/dist/document-operations.js +6 -4
- package/dist/docx/blockPlainText.d.ts +1 -1
- package/dist/docx/blockPlainText.js +11 -3
- package/dist/docx/builtInStyles.js +13 -6
- package/dist/docx/canonicalResourceSave.d.ts +16 -0
- package/dist/docx/canonicalResourceSave.js +27 -0
- package/dist/docx/canonicalSave.d.ts +29 -0
- package/dist/docx/canonicalSave.js +101 -0
- package/dist/docx/canonicalStoryRepack.d.ts +1 -1
- package/dist/docx/canonicalStoryRepack.js +38 -5
- package/dist/docx/containerChildren.gen.d.ts +3 -1
- package/dist/docx/containerChildren.gen.js +33 -1
- package/dist/docx/documentParser.d.ts +1 -13
- package/dist/docx/documentParser.js +1 -47
- package/dist/docx/ensureParaIds.js +10 -4
- package/dist/docx/fieldParser.js +14 -2
- package/dist/docx/footnoteParser.d.ts +1 -11
- package/dist/docx/footnoteParser.js +1 -16
- package/dist/docx/headerFooterParser.d.ts +1 -9
- package/dist/docx/headerFooterParser.js +1 -12
- package/dist/docx/headerFooterVerbatim.d.ts +26 -1
- package/dist/docx/headerFooterVerbatim.js +81 -3
- package/dist/docx/hyperlinkParser.d.ts +1 -1
- package/dist/docx/hyperlinkParser.js +20 -1
- package/dist/docx/imageParser.d.ts +13 -1
- package/dist/docx/imageParser.js +20 -11
- package/dist/docx/inlineWrapperContent.d.ts +4 -4
- package/dist/docx/inlineWrapperContent.js +4 -4
- package/dist/docx/linkedSdtPreservation.d.ts +10 -0
- package/dist/docx/linkedSdtPreservation.js +37 -0
- package/dist/docx/metadataPrivacy.js +6 -1
- package/dist/docx/packageParts.js +9 -3
- package/dist/docx/paragraphParser.js +88 -67
- package/dist/docx/paragraphPropertySource.d.ts +22 -1
- package/dist/docx/paragraphPropertySource.js +109 -2
- package/dist/docx/parser.js +2 -1
- package/dist/docx/preservedRunContent.js +2 -1
- package/dist/docx/relsParser.js +26 -2
- package/dist/docx/removeHeaderFooterParts.js +17 -6
- package/dist/docx/rezip.d.ts +49 -5
- package/dist/docx/rezip.js +754 -235
- package/dist/docx/saveDiagnostics.d.ts +11 -0
- package/dist/docx/selectiveSave.d.ts +2 -1
- package/dist/docx/selectiveSave.js +42 -11
- package/dist/docx/selectiveXmlPatch.js +7 -5
- package/dist/docx/serializer/commentSerializer.d.ts +4 -1
- package/dist/docx/serializer/commentSerializer.js +7 -3
- package/dist/docx/serializer/documentSerializer.d.ts +9 -2
- package/dist/docx/serializer/documentSerializer.js +29 -10
- package/dist/docx/serializer/paragraphSerializer.js +207 -94
- package/dist/docx/server/applyDocxXmlPatchProposal.js +14 -9
- package/dist/docx/server/materializeYjsDocx.js +14 -6
- package/dist/docx/server/migrateYjsAttrSchema.js +17 -5
- package/dist/docx/storyBlockReplay.d.ts +21 -1
- package/dist/docx/storyBlockReplay.js +113 -9
- package/dist/docx/storyPlainText.d.ts +20 -0
- package/dist/docx/storyPlainText.js +23 -0
- package/dist/docx/structuralXmlPatch.js +10 -22
- package/dist/docx/styleParser.d.ts +5 -1
- package/dist/docx/styleParser.js +1 -1
- package/dist/docx/tableParser.d.ts +1 -8
- package/dist/docx/tableParser.js +1 -28
- package/dist/docx/textBoxParser.d.ts +1 -5
- package/dist/docx/textBoxParser.js +1 -20
- package/dist/docx/unzip.js +6 -1
- package/dist/i18n/messages/ar.gen.js +4 -0
- package/dist/i18n/messages/catalogs.gen.d.ts +68 -0
- package/dist/i18n/messages/catalogs.gen.js +68 -0
- package/dist/i18n/messages/cs.gen.js +4 -0
- package/dist/i18n/messages/de.gen.js +4 -0
- package/dist/i18n/messages/en.gen.js +4 -0
- package/dist/i18n/messages/es.gen.js +4 -0
- package/dist/i18n/messages/et.gen.js +4 -0
- package/dist/i18n/messages/fr.gen.js +4 -0
- package/dist/i18n/messages/he.gen.js +4 -0
- package/dist/i18n/messages/hi.gen.js +4 -0
- package/dist/i18n/messages/hu.gen.js +4 -0
- package/dist/i18n/messages/lt.gen.js +4 -0
- package/dist/i18n/messages/lv.gen.js +4 -0
- package/dist/i18n/messages/messages.gen.d.ts +4 -0
- package/dist/i18n/messages/pl.gen.js +4 -0
- package/dist/i18n/messages/pt-BR.gen.js +4 -0
- package/dist/i18n/messages/sk.gen.js +4 -0
- package/dist/i18n/messages/tr.gen.js +4 -0
- package/dist/i18n/messages/zh-CN.gen.js +4 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/internal/acceptedBlockProjection.d.ts +12 -0
- package/dist/internal/acceptedBlockProjection.js +45 -0
- package/dist/internal/revisionResolutionInline.js +25 -3
- package/dist/managers/DocumentLoaderManager.js +2 -1
- package/dist/markdown/escape.d.ts +3 -1
- package/dist/markdown/escape.js +9 -2
- package/dist/markdown/renderBlock.js +5 -120
- package/dist/markdown/renderParagraph.js +4 -2
- package/dist/markdown/renderRuns.d.ts +7 -1
- package/dist/markdown/renderRuns.js +33 -24
- package/dist/panel-layout.d.ts +11 -9
- package/dist/panel-layout.js +13 -9
- package/dist/prosemirror/addTrackedDeletionMark.d.ts +18 -0
- package/dist/prosemirror/addTrackedDeletionMark.js +87 -0
- package/dist/prosemirror/attrs/index.js +5 -0
- package/dist/prosemirror/canonicalCommands.d.ts +28 -4
- package/dist/prosemirror/canonicalCommands.js +11 -4
- package/dist/prosemirror/canonicalSelectionRange.d.ts +9 -0
- package/dist/prosemirror/canonicalSelectionRange.js +15 -0
- package/dist/prosemirror/clipboardIntent.d.ts +7 -0
- package/dist/prosemirror/clipboardIntent.js +9 -0
- package/dist/prosemirror/commands/comments.js +60 -35
- package/dist/prosemirror/commands/pageBreak.js +2 -2
- package/dist/prosemirror/commands/pastePlainText.js +2 -1
- package/dist/prosemirror/commands/propertyChangeScope.js +3 -6
- package/dist/prosemirror/commands/resolveParagraphProperties.js +22 -13
- package/dist/prosemirror/commentOps.js +15 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +22 -3
- package/dist/prosemirror/conversion/hyphenTextCarriers.d.ts +8 -0
- package/dist/prosemirror/conversion/hyphenTextCarriers.js +8 -0
- package/dist/prosemirror/conversion/toProseDoc.d.ts +7 -1
- package/dist/prosemirror/conversion/toProseDoc.js +124 -22
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +61 -35
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +74 -25
- package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +11 -0
- package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +65 -29
- package/dist/prosemirror/extensions/marks/markUtils.js +11 -8
- package/dist/prosemirror/extensions/marks/noteReferenceDeletion.js +5 -2
- package/dist/prosemirror/fieldRepresentation.d.ts +8 -0
- package/dist/prosemirror/fieldRepresentation.js +18 -0
- package/dist/prosemirror/hyperlinkRemoval.d.ts +13 -1
- package/dist/prosemirror/hyperlinkRemoval.js +28 -9
- package/dist/prosemirror/insertOperations.js +2 -1
- package/dist/prosemirror/listNumbering.js +11 -5
- package/dist/prosemirror/noteReferenceOccurrenceId.d.ts +5 -0
- package/dist/prosemirror/noteReferenceOccurrenceId.js +5 -0
- package/dist/prosemirror/noteReferenceOccurrences.d.ts +21 -0
- package/dist/prosemirror/noteReferenceOccurrences.js +185 -0
- package/dist/prosemirror/noteReferenceReview.js +14 -1
- package/dist/prosemirror/paragraphPropertyCarry.d.ts +7 -1
- package/dist/prosemirror/paragraphPropertyCarry.js +8 -3
- package/dist/prosemirror/plugins/documentStyles.d.ts +4 -1
- package/dist/prosemirror/plugins/documentStyles.js +17 -10
- package/dist/prosemirror/plugins/suggestionMode.js +48 -48
- package/dist/prosemirror/preservedXmlReview.d.ts +6 -0
- package/dist/prosemirror/preservedXmlReview.js +35 -0
- package/dist/prosemirror/runFormattingFromMarks.js +2 -2
- package/dist/prosemirror/runFormattingReconciliation.js +5 -4
- package/dist/prosemirror/runPropertyChangeResolution.d.ts +8 -1
- package/dist/prosemirror/runPropertyChangeResolution.js +24 -2
- package/dist/prosemirror/runStyleFormatting.d.ts +3 -1
- package/dist/prosemirror/runStyleFormatting.js +3 -1
- package/dist/prosemirror/schema/marks.d.ts +1 -0
- package/dist/prosemirror/schema/nodes.d.ts +2 -0
- package/dist/prosemirror/styles/paragraphStyleCascade.js +4 -1
- package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +15 -15
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +69 -28
- package/dist/prosemirror/textInput.d.ts +5 -1
- package/dist/prosemirror/textInput.js +3 -3
- package/dist/prosemirror/trackedRevisionPath.d.ts +5 -1
- package/dist/prosemirror/trackedRevisionPath.js +39 -1
- package/dist/prosemirror/validation.js +3 -5
- package/dist/prosemirror/yjsDocumentMetadata.d.ts +9 -3
- package/dist/prosemirror/yjsDocumentMetadata.js +37 -8
- package/dist/types/canonicalCapabilities.d.ts +201 -0
- package/dist/types/canonicalCapabilities.js +198 -0
- package/dist/types/canonicalComments.d.ts +51 -0
- package/dist/types/canonicalComments.js +0 -0
- package/dist/types/canonicalSave.d.ts +11 -0
- package/dist/types/canonicalSave.js +0 -0
- package/dist/types/canonicalSections.d.ts +12 -0
- package/dist/types/canonicalSections.js +0 -0
- package/dist/types/docxSerialization.d.ts +14 -0
- package/dist/types/docxSerialization.js +7 -0
- package/dist/utils/headingCollector.js +45 -4
- package/dist/utils/outlineDepth.d.ts +9 -0
- package/dist/utils/outlineDepth.js +9 -0
- package/package.json +4 -4
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { CanonicalGap } from "../types/canonicalCapabilities.js";
|
|
2
3
|
import { HiddenEditorApi } from "./hiddenEditorApi.js";
|
|
3
4
|
import { NoteStoryKey } from "../types/editor-story.js";
|
|
4
5
|
import { Plugin } from "prosemirror-state";
|
|
@@ -15,7 +16,7 @@ type NoteEditorManagerDeps = {
|
|
|
15
16
|
getDocument: () => document_d_exports.Document | null;
|
|
16
17
|
getCanonicalApi?: (() => HiddenEditorApi | null) | undefined;
|
|
17
18
|
getExperimentalSession?: (() => "canonical" | undefined) | undefined;
|
|
18
|
-
onSessionRefusal?: ((reason: string) => void) | undefined;
|
|
19
|
+
onSessionRefusal?: ((reason: string, gap: CanonicalGap, error?: Error) => void) | undefined;
|
|
19
20
|
getHost: () => HTMLElement | null;
|
|
20
21
|
getPlugins?: (() => Plugin[]) | undefined;
|
|
21
22
|
getStyles: () => document_d_exports.StyleDefinitions | null | undefined;
|
|
@@ -7,10 +7,13 @@ import { ExtensionManager } from "../prosemirror/extensions/ExtensionManager.js"
|
|
|
7
7
|
import { createStarterKit } from "../prosemirror/extensions/StarterKit.js";
|
|
8
8
|
import { ensureBaseDirectionInState } from "../prosemirror/extensions/features/AutoBidiDetectionExtension.js";
|
|
9
9
|
import { ensureParaIdsInState } from "../prosemirror/extensions/features/ParaIdAllocatorExtension.js";
|
|
10
|
+
import { noteReferenceTransactionIssue } from "../prosemirror/noteReferenceOccurrences.js";
|
|
10
11
|
import { createDocumentNumberingPlugin } from "../prosemirror/plugins/documentNumbering.js";
|
|
11
|
-
import { createDocumentStylesPlugin } from "../prosemirror/plugins/documentStyles.js";
|
|
12
|
+
import { createDocumentStyleContextPlugin, createDocumentStylesPlugin } from "../prosemirror/plugins/documentStyles.js";
|
|
12
13
|
import { schema } from "../prosemirror/schema/index.js";
|
|
13
14
|
import { storyListNumbering } from "../prosemirror/storyListNumbering.js";
|
|
15
|
+
import { CANONICAL_GAP, usesCanonicalSession } from "../types/canonicalCapabilities.js";
|
|
16
|
+
import { CanonicalSessionError } from "./canonicalSession.js";
|
|
14
17
|
import { createCanonicalStoryEditor } from "./canonicalStoryEditor.js";
|
|
15
18
|
import { OP_STORIES } from "@stll/docx-core/ops";
|
|
16
19
|
import { EditorState, TextSelection } from "prosemirror-state";
|
|
@@ -87,11 +90,12 @@ const createNoteEditorManager = (deps) => {
|
|
|
87
90
|
mounted.clear();
|
|
88
91
|
active = null;
|
|
89
92
|
};
|
|
93
|
+
const getOwnedDocument = () => usesCanonicalSession(deps.getExperimentalSession?.(), CANONICAL_GAP.authorityRouting) ? deps.getCanonicalApi?.()?.getCanonicalDocument() ?? null : deps.getDocument();
|
|
90
94
|
const sync = () => {
|
|
91
95
|
const host = deps.getHost();
|
|
92
96
|
if (!host) return;
|
|
93
|
-
if (deps.getExperimentalSession?.()
|
|
94
|
-
const document =
|
|
97
|
+
if (usesCanonicalSession(deps.getExperimentalSession?.(), CANONICAL_GAP.authorityRouting) && !deps.getCanonicalApi?.()?.getCanonicalStoryProjection(OP_STORIES.MAIN)) return;
|
|
98
|
+
const document = getOwnedDocument();
|
|
95
99
|
const styles = deps.getStyles();
|
|
96
100
|
const theme = deps.getTheme();
|
|
97
101
|
const numbering = document?.package.numbering;
|
|
@@ -115,7 +119,7 @@ const createNoteEditorManager = (deps) => {
|
|
|
115
119
|
const existing = mounted.get(key);
|
|
116
120
|
if (existing) {
|
|
117
121
|
if (existing.mountNode.parentElement !== host) host.append(existing.mountNode);
|
|
118
|
-
if (deps.getExperimentalSession?.()
|
|
122
|
+
if (usesCanonicalSession(deps.getExperimentalSession?.(), CANONICAL_GAP.authorityRouting)) {
|
|
119
123
|
const projected = deps.getCanonicalApi?.()?.getCanonicalStoryProjection({
|
|
120
124
|
kind: storyKey.kind,
|
|
121
125
|
id: storyKey.noteId
|
|
@@ -175,7 +179,7 @@ const createNoteEditorManager = (deps) => {
|
|
|
175
179
|
},
|
|
176
180
|
getView: () => view,
|
|
177
181
|
getApi: () => deps.getCanonicalApi?.() ?? null,
|
|
178
|
-
enabled: () => deps.getExperimentalSession?.()
|
|
182
|
+
enabled: () => usesCanonicalSession(deps.getExperimentalSession?.(), CANONICAL_GAP.authorityRouting),
|
|
179
183
|
onRefusal: deps.onSessionRefusal,
|
|
180
184
|
onSelectionChange: () => deps.onTransaction?.({
|
|
181
185
|
...storyKey,
|
|
@@ -184,11 +188,11 @@ const createNoteEditorManager = (deps) => {
|
|
|
184
188
|
selectionChanged: true
|
|
185
189
|
})
|
|
186
190
|
});
|
|
187
|
-
const canonicalProjection = deps.getExperimentalSession?.()
|
|
191
|
+
const canonicalProjection = usesCanonicalSession(deps.getExperimentalSession?.(), CANONICAL_GAP.authorityRouting) ? deps.getCanonicalApi?.()?.getCanonicalStoryProjection({
|
|
188
192
|
kind: storyKey.kind,
|
|
189
193
|
id: storyKey.noteId
|
|
190
194
|
}) : null;
|
|
191
|
-
if (deps.getExperimentalSession?.()
|
|
195
|
+
if (usesCanonicalSession(deps.getExperimentalSession?.(), CANONICAL_GAP.authorityRouting) && !canonicalProjection) {
|
|
192
196
|
manager.destroy();
|
|
193
197
|
mountNode.remove();
|
|
194
198
|
continue;
|
|
@@ -197,16 +201,20 @@ const createNoteEditorManager = (deps) => {
|
|
|
197
201
|
...canonical.props,
|
|
198
202
|
state: canonicalProjection ? EditorState.create({
|
|
199
203
|
doc: canonicalProjection,
|
|
200
|
-
plugins: [
|
|
204
|
+
plugins: [createDocumentStyleContextPlugin(styles), createDocumentNumberingPlugin(numbering)]
|
|
201
205
|
}) : buildInitialState(proseDocument, styles, numbering, manager, externalPlugins),
|
|
202
206
|
dispatchTransaction(transaction) {
|
|
203
207
|
if (canonical.dispatch(transaction)) return;
|
|
204
|
-
view.
|
|
208
|
+
const nextState = view.state.apply(transaction);
|
|
209
|
+
const docChanged = !nextState.doc.eq(view.state.doc);
|
|
210
|
+
view.updateState(nextState);
|
|
211
|
+
const noteIssue = noteReferenceTransactionIssue(transaction);
|
|
212
|
+
if (noteIssue) deps.onSessionRefusal?.(noteIssue.message, CANONICAL_GAP.dispatch, noteIssue);
|
|
205
213
|
const mountedStory = mounted.get(key);
|
|
206
|
-
if (mountedStory &&
|
|
214
|
+
if (mountedStory && docChanged) mountedStory.dirty = true;
|
|
207
215
|
deps.onTransaction?.({
|
|
208
216
|
...storyKey,
|
|
209
|
-
docChanged
|
|
217
|
+
docChanged,
|
|
210
218
|
selectionChanged: transaction.selectionSet,
|
|
211
219
|
view
|
|
212
220
|
});
|
|
@@ -244,9 +252,17 @@ const createNoteEditorManager = (deps) => {
|
|
|
244
252
|
destroy,
|
|
245
253
|
getActive: () => active,
|
|
246
254
|
getView: (story) => mounted.get(storyMapKey(story))?.view ?? null,
|
|
247
|
-
listStories: () => enumerateDocumentNoteStories(
|
|
255
|
+
listStories: () => enumerateDocumentNoteStories(getOwnedDocument()),
|
|
248
256
|
snapshotDocument: (document) => {
|
|
249
|
-
if (deps.getExperimentalSession?.()
|
|
257
|
+
if (usesCanonicalSession(deps.getExperimentalSession?.(), CANONICAL_GAP.authorityRouting)) {
|
|
258
|
+
const canonical = deps.getCanonicalApi?.()?.getCanonicalDocument();
|
|
259
|
+
if (canonical) return canonical;
|
|
260
|
+
throw new CanonicalSessionError({
|
|
261
|
+
gap: CANONICAL_GAP.authorityRouting,
|
|
262
|
+
reason: "refused",
|
|
263
|
+
message: "Canonical story snapshot is unavailable."
|
|
264
|
+
});
|
|
265
|
+
}
|
|
250
266
|
let footnotes = document.package.footnotes;
|
|
251
267
|
let endnotes = document.package.endnotes;
|
|
252
268
|
let footnotesChanged = false;
|
|
@@ -132,6 +132,7 @@ type FolioDocumentOperationIssue = {
|
|
|
132
132
|
code: FolioAIEditSkippedOperation["reason"];
|
|
133
133
|
retryable: boolean;
|
|
134
134
|
recovery: FolioDocumentOperationRecovery;
|
|
135
|
+
canonicalRefusal?: FolioAIEditSkippedOperation["canonicalRefusal"];
|
|
135
136
|
/** The skip's detail, when it has one; see {@link FolioAIEditSkippedOperation.message}. */
|
|
136
137
|
message?: string;
|
|
137
138
|
};
|
|
@@ -264,6 +265,12 @@ type FolioDocumentOperationResult = (FolioDocumentOperationResultBase & {
|
|
|
264
265
|
declare const getFolioDocumentOperationIssues: (operations: readonly FolioDocumentOperation[], skipped: readonly FolioAIEditSkippedOperation[]) => FolioDocumentOperationIssue[];
|
|
265
266
|
/** Build deterministic affected-target receipts from operations and their applied entries. */
|
|
266
267
|
declare const getFolioDocumentOperationReceipts: (operations: readonly FolioDocumentOperation[], applied: readonly FolioAIEditAppliedOperation[]) => FolioDocumentOperationReceipt[];
|
|
268
|
+
type GetFolioDocumentOperationReceiptsForStoryOptions = {
|
|
269
|
+
operations: readonly FolioDocumentOperation[];
|
|
270
|
+
applied: readonly FolioAIEditAppliedOperation[];
|
|
271
|
+
story: FolioDocumentOperationStory;
|
|
272
|
+
};
|
|
273
|
+
declare const getFolioDocumentOperationReceiptsForStory: ({ operations, applied, story }: GetFolioDocumentOperationReceiptsForStoryOptions) => FolioDocumentOperationReceipt[];
|
|
267
274
|
type ApplyFolioDocumentOperationsOptions = {
|
|
268
275
|
view: FolioAIEditView;
|
|
269
276
|
snapshot: FolioAIEditSnapshot;
|
|
@@ -301,4 +308,4 @@ type ApplyFolioDocumentOperationsOptions = {
|
|
|
301
308
|
};
|
|
302
309
|
declare const applyFolioDocumentOperations: ({ view, snapshot, batch, story, author, createCommentId, createUndoHandle, revisionStamp, wordDiff, tableTemplates, replacementBackground, undefinedStyles }: ApplyFolioDocumentOperationsOptions) => FolioDocumentOperationResult;
|
|
303
310
|
//#endregion
|
|
304
|
-
export { ApplyFolioDocumentOperationsOptions, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_BATCH_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_KEYS_BY_TYPE, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PAGE_BREAK_CLEAR_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, FolioDocumentOperation, FolioDocumentOperationAffectedTarget, FolioDocumentOperationBatch, FolioDocumentOperationBatchPrecondition, FolioDocumentOperationCapabilities, FolioDocumentOperationIssue, FolioDocumentOperationMode, FolioDocumentOperationPrecondition, FolioDocumentOperationQueuedOperation, FolioDocumentOperationReceipt, FolioDocumentOperationRecovery, FolioDocumentOperationResult, FolioDocumentOperationResultBase, FolioDocumentOperationStatus, FolioDocumentOperationStory, FolioDocumentOperationType, FolioDocumentOperationUndoFailureReason, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch };
|
|
311
|
+
export { ApplyFolioDocumentOperationsOptions, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_BATCH_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_KEYS_BY_TYPE, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PAGE_BREAK_CLEAR_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, FolioDocumentOperation, FolioDocumentOperationAffectedTarget, FolioDocumentOperationBatch, FolioDocumentOperationBatchPrecondition, FolioDocumentOperationCapabilities, FolioDocumentOperationIssue, FolioDocumentOperationMode, FolioDocumentOperationPrecondition, FolioDocumentOperationQueuedOperation, FolioDocumentOperationReceipt, FolioDocumentOperationRecovery, FolioDocumentOperationResult, FolioDocumentOperationResultBase, FolioDocumentOperationStatus, FolioDocumentOperationStory, FolioDocumentOperationType, FolioDocumentOperationUndoFailureReason, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioDocumentOperationReceiptsForStory, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch };
|
|
@@ -1072,22 +1072,24 @@ const recoveryByReason = {
|
|
|
1072
1072
|
missingStyle: "refreshDocument",
|
|
1073
1073
|
missingNumbering: "refreshDocument",
|
|
1074
1074
|
invalidResult: "refreshDocument",
|
|
1075
|
-
pendingDeletion: "resolveTrackedChange"
|
|
1075
|
+
pendingDeletion: "resolveTrackedChange",
|
|
1076
|
+
pendingParagraphMarkDeletion: "resolveTrackedChange"
|
|
1076
1077
|
};
|
|
1077
1078
|
const getFolioDocumentOperationIssues = (operations, skipped) => {
|
|
1078
1079
|
const indexById = /* @__PURE__ */ new Map();
|
|
1079
1080
|
operations.forEach(({ id }, index) => {
|
|
1080
1081
|
indexById.set(id, index);
|
|
1081
1082
|
});
|
|
1082
|
-
return skipped.map(({ id, reason, message }) => {
|
|
1083
|
+
return skipped.map(({ id, reason, message, canonicalRefusal }) => {
|
|
1083
1084
|
const operationIndex = indexById.get(id) ?? -1;
|
|
1084
1085
|
return {
|
|
1085
1086
|
operationId: id,
|
|
1086
1087
|
operationIndex,
|
|
1087
1088
|
path: `$.operations[${operationIndex}]`,
|
|
1088
1089
|
code: reason,
|
|
1089
|
-
retryable: reason !== "emptyOperation" && reason !== "noopOperation" && reason !== "pendingParagraphPropertyChange" && reason !== "pendingRunPropertyChange" && reason !== "pendingDeletion" && reason !== "payloadDoesNotFit" && reason !== "protectedReference" && reason !== "invalidResult",
|
|
1090
|
+
retryable: reason !== "emptyOperation" && reason !== "noopOperation" && reason !== "pendingParagraphPropertyChange" && reason !== "pendingRunPropertyChange" && reason !== "pendingDeletion" && reason !== "pendingParagraphMarkDeletion" && reason !== "payloadDoesNotFit" && reason !== "protectedReference" && reason !== "invalidResult",
|
|
1090
1091
|
recovery: recoveryByReason[reason],
|
|
1092
|
+
...canonicalRefusal === void 0 ? {} : { canonicalRefusal },
|
|
1091
1093
|
...message !== void 0 && { message }
|
|
1092
1094
|
};
|
|
1093
1095
|
});
|
|
@@ -1468,4 +1470,4 @@ const applyFolioDocumentOperations = ({ view, snapshot, batch, story = "main", a
|
|
|
1468
1470
|
};
|
|
1469
1471
|
};
|
|
1470
1472
|
//#endregion
|
|
1471
|
-
export { FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_BATCH_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_KEYS_BY_TYPE, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PAGE_BREAK_CLEAR_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch };
|
|
1473
|
+
export { FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_BATCH_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_KEYS_BY_TYPE, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PAGE_BREAK_CLEAR_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioDocumentOperationReceiptsForStory, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
2
|
//#region src/docx/blockPlainText.d.ts
|
|
3
|
-
/** One entry per block
|
|
3
|
+
/** One entry per accepted block; deleted breaks and table structure resolve together. */
|
|
4
4
|
declare const collectBlockTexts: (blocks: readonly document_d_exports.BlockContent[]) => string[];
|
|
5
5
|
declare const blockPlainText: (blocks: readonly document_d_exports.BlockContent[]) => string;
|
|
6
6
|
//#endregion
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { projectAcceptedBlocks } from "../internal/acceptedBlockProjection.js";
|
|
1
2
|
import { ALT_CHUNK_READER_DIAGNOSTIC, isAltChunkMarkup } from "./altChunk.js";
|
|
2
3
|
import { OPAQUE_REVISION_CARRIER_READER_DIAGNOSTIC, isOpaqueNestedRowMarkup, opaqueRevisionCarrierName } from "./opaqueCarrier.js";
|
|
3
4
|
import { getParagraphText } from "./paragraphParser.js";
|
|
@@ -18,7 +19,7 @@ import { panic } from "better-result";
|
|
|
18
19
|
* everything below block level and reads the accepted tracked-change view.
|
|
19
20
|
*/
|
|
20
21
|
/** One entry per block, so callers can join or count lines as they need. */
|
|
21
|
-
const
|
|
22
|
+
const collectResolvedBlockTexts = (blocks) => {
|
|
22
23
|
const texts = [];
|
|
23
24
|
for (const block of blocks) switch (block.type) {
|
|
24
25
|
case "paragraph":
|
|
@@ -27,12 +28,12 @@ const collectBlockTexts = (blocks) => {
|
|
|
27
28
|
case "table":
|
|
28
29
|
for (const row of block.rows) {
|
|
29
30
|
if (row.formatting?.hidden === true) continue;
|
|
30
|
-
texts.push(row.cells.map((cell) =>
|
|
31
|
+
texts.push(row.cells.map((cell) => collectResolvedBlockTexts(cell.content).join("\n")).join(" "));
|
|
31
32
|
}
|
|
32
33
|
break;
|
|
33
34
|
case "blockSdt":
|
|
34
35
|
case "blockCustomXml":
|
|
35
|
-
texts.push(...
|
|
36
|
+
texts.push(...collectResolvedBlockTexts(block.content));
|
|
36
37
|
break;
|
|
37
38
|
case "preservedBlock":
|
|
38
39
|
if (isAltChunkMarkup(block.xml)) texts.push(block.readerText === void 0 ? ALT_CHUNK_READER_DIAGNOSTIC : `${ALT_CHUNK_READER_DIAGNOSTIC}\n${block.readerText}`);
|
|
@@ -45,6 +46,13 @@ const collectBlockTexts = (blocks) => {
|
|
|
45
46
|
}
|
|
46
47
|
return texts;
|
|
47
48
|
};
|
|
49
|
+
/** One entry per accepted block; deleted breaks and table structure resolve together. */
|
|
50
|
+
const collectBlockTexts = (blocks) => {
|
|
51
|
+
const projection = projectAcceptedBlocks(blocks, void 0);
|
|
52
|
+
const texts = collectResolvedBlockTexts(projection?.blocks ?? blocks);
|
|
53
|
+
if (projection?.completeness === "partial") texts.push("[Unresolved tracked structural changes]");
|
|
54
|
+
return texts;
|
|
55
|
+
};
|
|
48
56
|
const blockPlainText = (blocks) => collectBlockTexts(blocks).join("\n");
|
|
49
57
|
//#endregion
|
|
50
58
|
export { blockPlainText, collectBlockTexts };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BUILT_IN_DEFAULT_PARAGRAPH_STYLE_NAME, resolveDefaultParagraphStyle } from "./defaultParagraphStyle.js";
|
|
2
|
-
import { headingLevelOf } from "@stll/docx-core/model";
|
|
2
|
+
import { headingLevelOf, headingOutlineLevel } from "@stll/docx-core/model";
|
|
3
3
|
//#region src/docx/builtInStyles.ts
|
|
4
4
|
/**
|
|
5
5
|
* Whether a paragraph is a heading, and of which level, without reading the
|
|
@@ -134,20 +134,27 @@ const headingOutlineLevelFromStyleName = (name) => {
|
|
|
134
134
|
const CANONICAL_BY_NORMALIZED = new Map(Object.values(BUILT_IN_STYLE_NAME).map((name) => [normalizeStyleName(name), name]));
|
|
135
135
|
const asBuiltInName = (normalized) => CANONICAL_BY_NORMALIZED.get(normalized);
|
|
136
136
|
/**
|
|
137
|
-
* The outline
|
|
138
|
-
* the
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
137
|
+
* The effective outline contribution of a style chain: the nearest explicit
|
|
138
|
+
* `w:outlineLvl` wins across the chain; only when none exists does the nearest
|
|
139
|
+
* built-in heading name supply its implicit level. `styleParser` already flattens
|
|
140
|
+
* `w:basedOn` for a parsed package, but a style set built in memory carries the
|
|
141
|
+
* raw chain, so the walk keeps both kinds of input on the same answer. `seen`
|
|
142
|
+
* guards the circular `basedOn` a malformed package can contain.
|
|
142
143
|
*/
|
|
143
144
|
const inheritedOutlineLevel = (style, styleById) => {
|
|
144
145
|
const seen = /* @__PURE__ */ new Set();
|
|
145
146
|
let current = style;
|
|
147
|
+
let nearestImplicitHeadingLevel;
|
|
146
148
|
while (current && !seen.has(current.styleId)) {
|
|
147
149
|
seen.add(current.styleId);
|
|
148
150
|
if (current.pPr?.outlineLevel !== void 0) return current.pPr.outlineLevel;
|
|
151
|
+
if (nearestImplicitHeadingLevel === void 0) {
|
|
152
|
+
const namedLevel = headingOutlineLevelFromStyleName(current.name);
|
|
153
|
+
if (namedLevel !== void 0) nearestImplicitHeadingLevel = headingOutlineLevel(namedLevel);
|
|
154
|
+
}
|
|
149
155
|
current = current.basedOn === void 0 ? void 0 : styleById.get(current.basedOn);
|
|
150
156
|
}
|
|
157
|
+
return nearestImplicitHeadingLevel;
|
|
151
158
|
};
|
|
152
159
|
/** The level a heading style is indexed under, or undefined if it is not one. */
|
|
153
160
|
const headingLevelForIndex = (namedLevel, statedLevel) => {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { CANONICAL_GAP } from "../types/canonicalCapabilities.js";
|
|
3
|
+
import { SaveDiagnostic } from "./saveDiagnostics.js";
|
|
4
|
+
//#region src/docx/canonicalResourceSave.d.ts
|
|
5
|
+
declare const CanonicalResourceSaveRefusalError_base: import("better-result").TaggedErrorClass<"CanonicalResourceSaveRefusalError">;
|
|
6
|
+
declare class CanonicalResourceSaveRefusalError extends CanonicalResourceSaveRefusalError_base<{
|
|
7
|
+
message: string;
|
|
8
|
+
gap: typeof CANONICAL_GAP.resourceReplacement;
|
|
9
|
+
diagnostic: Extract<SaveDiagnostic, {
|
|
10
|
+
type: "canonicalResourceReplacement";
|
|
11
|
+
}>;
|
|
12
|
+
}> {}
|
|
13
|
+
/** Full and selective package writers preserve existing style/media source entries. */
|
|
14
|
+
declare const canonicalResourceReplacementOf: (document: document_d_exports.Document) => string | undefined;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { CanonicalResourceSaveRefusalError, canonicalResourceReplacementOf };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { canonicalJson } from "../utils/canonicalJson.js";
|
|
2
|
+
import { getDocumentSourceBaseline } from "./headerFooterVerbatim.js";
|
|
3
|
+
import { TaggedError } from "better-result";
|
|
4
|
+
//#region src/docx/canonicalResourceSave.ts
|
|
5
|
+
var CanonicalResourceSaveRefusalError = class extends TaggedError("CanonicalResourceSaveRefusalError") {};
|
|
6
|
+
/** Full and selective package writers preserve existing style/media source entries. */
|
|
7
|
+
const canonicalResourceReplacementOf = (document) => {
|
|
8
|
+
const source = getDocumentSourceBaseline(document);
|
|
9
|
+
if (source.type !== "captured" || !document.originalBuffer) return void 0;
|
|
10
|
+
const baseline = source.resourceStyles;
|
|
11
|
+
const current = document.package.styles;
|
|
12
|
+
if (baseline) {
|
|
13
|
+
const { styles: sourceStyles, ...sourceDefaults } = baseline;
|
|
14
|
+
const { styles: currentStyles, ...currentDefaults } = current ?? { styles: [] };
|
|
15
|
+
const currentById = new Map(currentStyles.map((style) => [style.styleId, style]));
|
|
16
|
+
if (canonicalJson(sourceDefaults) !== canonicalJson(currentDefaults) || sourceStyles.some((style) => canonicalJson(style) !== canonicalJson(currentById.get(style.styleId)))) return "word/styles.xml";
|
|
17
|
+
}
|
|
18
|
+
for (const [path, media] of source.resourceMedia) {
|
|
19
|
+
const currentMedia = document.package.media?.get(path);
|
|
20
|
+
if (!currentMedia || media.mimeType !== currentMedia.mimeType) return path;
|
|
21
|
+
const sourceBytes = new Uint8Array(media.data);
|
|
22
|
+
const currentBytes = new Uint8Array(currentMedia.data);
|
|
23
|
+
if (sourceBytes.length !== currentBytes.length || sourceBytes.some((byte, index) => byte !== currentBytes[index])) return path;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
//#endregion
|
|
27
|
+
export { CanonicalResourceSaveRefusalError, canonicalResourceReplacementOf };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { CANONICAL_GAP } from "../types/canonicalCapabilities.js";
|
|
2
|
+
import { SaveDiagnostic } from "./saveDiagnostics.js";
|
|
3
|
+
import { CanonicalSaveSnapshot } from "../types/canonicalSave.js";
|
|
4
|
+
import { FolioGetDocxOptions } from "../types/docxSerialization.js";
|
|
5
|
+
import { TripwireResult } from "./selectiveSaveTripwire.js";
|
|
6
|
+
import { FolioSelectiveSaveFlags } from "./selectiveSaveFlags.js";
|
|
7
|
+
//#region src/docx/canonicalSave.d.ts
|
|
8
|
+
declare const CanonicalSaveDiagnosticError_base: import("better-result").TaggedErrorClass<"CanonicalSaveDiagnosticError">;
|
|
9
|
+
/** Forward a fidelity fallback through the adapters' existing error channel. */
|
|
10
|
+
declare class CanonicalSaveDiagnosticError extends CanonicalSaveDiagnosticError_base<{
|
|
11
|
+
message: string;
|
|
12
|
+
gap: typeof CANONICAL_GAP.save;
|
|
13
|
+
diagnostic: SaveDiagnostic;
|
|
14
|
+
}> {}
|
|
15
|
+
type SerializeCanonicalSaveOptions = {
|
|
16
|
+
snapshot: CanonicalSaveSnapshot;
|
|
17
|
+
options?: FolioGetDocxOptions | undefined;
|
|
18
|
+
featureFlags?: FolioSelectiveSaveFlags | undefined;
|
|
19
|
+
};
|
|
20
|
+
/** Model and change signals come from one committed snapshot, never from PM. */
|
|
21
|
+
declare const serializeCanonicalSave: ({ snapshot, options, featureFlags }: SerializeCanonicalSaveOptions) => Promise<{
|
|
22
|
+
buffer: ArrayBuffer;
|
|
23
|
+
document: import("@stll/docx-core").Document;
|
|
24
|
+
version: number;
|
|
25
|
+
diagnostics: SaveDiagnostic[];
|
|
26
|
+
tripwireResult: TripwireResult | null;
|
|
27
|
+
}>;
|
|
28
|
+
//#endregion
|
|
29
|
+
export { CanonicalSaveDiagnosticError, serializeCanonicalSave };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { withoutUnreferencedNotes } from "../prosemirror/noteReferenceReview.js";
|
|
2
|
+
import { CANONICAL_GAP } from "../types/canonicalCapabilities.js";
|
|
3
|
+
import { FOLIO_DOCX_SERIALIZATION_MODE } from "../types/docxSerialization.js";
|
|
4
|
+
import { CanonicalResourceSaveRefusalError, canonicalResourceReplacementOf } from "./canonicalResourceSave.js";
|
|
5
|
+
import { repackWithCanonicalStoryRemovals } from "./canonicalStoryRepack.js";
|
|
6
|
+
import { getDocumentSourceBaseline } from "./headerFooterVerbatim.js";
|
|
7
|
+
import { resolveSelectiveSaveFlags } from "./selectiveSaveFlags.js";
|
|
8
|
+
import { Result, TaggedError } from "better-result";
|
|
9
|
+
//#region src/docx/canonicalSave.ts
|
|
10
|
+
/** Forward a fidelity fallback through the adapters' existing error channel. */
|
|
11
|
+
var CanonicalSaveDiagnosticError = class extends TaggedError("CanonicalSaveDiagnosticError") {};
|
|
12
|
+
/** Model and change signals come from one committed snapshot, never from PM. */
|
|
13
|
+
const serializeCanonicalSave = async ({ snapshot, options, featureFlags }) => {
|
|
14
|
+
const document = withoutUnreferencedNotes(snapshot.document);
|
|
15
|
+
const replacementPart = snapshot.structure === "changed" ? canonicalResourceReplacementOf(document) : void 0;
|
|
16
|
+
if (replacementPart) {
|
|
17
|
+
const diagnostic = {
|
|
18
|
+
type: "canonicalResourceReplacement",
|
|
19
|
+
gap: CANONICAL_GAP.resourceReplacement,
|
|
20
|
+
part: replacementPart
|
|
21
|
+
};
|
|
22
|
+
options?.onDiagnostic?.(diagnostic);
|
|
23
|
+
throw new CanonicalResourceSaveRefusalError({
|
|
24
|
+
message: "Canonical save cannot preserve this package resource replacement.",
|
|
25
|
+
gap: CANONICAL_GAP.resourceReplacement,
|
|
26
|
+
diagnostic
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
const baseline = document.originalBuffer;
|
|
30
|
+
const flags = resolveSelectiveSaveFlags(featureFlags);
|
|
31
|
+
const diagnostics = [];
|
|
32
|
+
const onDiagnostic = (diagnostic) => {
|
|
33
|
+
if (!diagnostics.some((existing) => existing.type === diagnostic.type && existing.part === diagnostic.part)) diagnostics.push(diagnostic);
|
|
34
|
+
};
|
|
35
|
+
const { repackDocx, createDocx } = await import("./rezip.js");
|
|
36
|
+
const useSelective = flags.selectiveSave && options?.mode !== FOLIO_DOCX_SERIALIZATION_MODE.full;
|
|
37
|
+
let selectiveBuffer = null;
|
|
38
|
+
if (baseline && (useSelective || flags.selectiveSaveTripwire)) {
|
|
39
|
+
const { attemptSelectiveSave } = await import("./selectiveSave.js");
|
|
40
|
+
selectiveBuffer = await attemptSelectiveSave(document, baseline, {
|
|
41
|
+
bodyAuthority: "canonical",
|
|
42
|
+
changedParaIds: new Set(snapshot.changedBlockIds),
|
|
43
|
+
structuralChange: snapshot.structure === "changed",
|
|
44
|
+
hasUntrackedChanges: false,
|
|
45
|
+
maxBytes: flags.selectiveSaveMaxBytes,
|
|
46
|
+
onDiagnostic
|
|
47
|
+
});
|
|
48
|
+
if (useSelective && !selectiveBuffer) onDiagnostic({
|
|
49
|
+
type: "selectiveSaveRefused",
|
|
50
|
+
part: "word/document.xml"
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
const repack = () => {
|
|
54
|
+
if (baseline && getDocumentSourceBaseline(document).type === "missing") onDiagnostic({
|
|
55
|
+
type: "sourceReplayUnavailable",
|
|
56
|
+
part: "word/document.xml"
|
|
57
|
+
});
|
|
58
|
+
return baseline ? repackWithCanonicalStoryRemovals({
|
|
59
|
+
document,
|
|
60
|
+
repack: () => repackDocx(document, {
|
|
61
|
+
onDiagnostic,
|
|
62
|
+
bodyAuthority: "canonical"
|
|
63
|
+
})
|
|
64
|
+
}) : createDocx(document, {
|
|
65
|
+
onDiagnostic,
|
|
66
|
+
bodyAuthority: "canonical"
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
let buffer = useSelective ? selectiveBuffer : null;
|
|
70
|
+
let fullBuffer = null;
|
|
71
|
+
if (!buffer) {
|
|
72
|
+
fullBuffer = await repack();
|
|
73
|
+
buffer = fullBuffer;
|
|
74
|
+
} else if (flags.selectiveSaveTripwire) {
|
|
75
|
+
const full = await Result.tryPromise({
|
|
76
|
+
try: repack,
|
|
77
|
+
catch: (error) => error
|
|
78
|
+
});
|
|
79
|
+
if (full.isOk()) fullBuffer = full.value;
|
|
80
|
+
}
|
|
81
|
+
let tripwireResult = null;
|
|
82
|
+
if (flags.selectiveSaveTripwire && fullBuffer) {
|
|
83
|
+
const { compareSelectiveVsFull } = await import("./selectiveSaveTripwire.js");
|
|
84
|
+
const capturedFullBuffer = fullBuffer;
|
|
85
|
+
const compared = await Result.tryPromise({
|
|
86
|
+
try: () => compareSelectiveVsFull(selectiveBuffer, capturedFullBuffer),
|
|
87
|
+
catch: (error) => error
|
|
88
|
+
});
|
|
89
|
+
if (compared.isOk()) tripwireResult = compared.value;
|
|
90
|
+
}
|
|
91
|
+
for (const diagnostic of diagnostics) options?.onDiagnostic?.(diagnostic);
|
|
92
|
+
return {
|
|
93
|
+
buffer,
|
|
94
|
+
document,
|
|
95
|
+
version: snapshot.version,
|
|
96
|
+
diagnostics,
|
|
97
|
+
tripwireResult
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
//#endregion
|
|
101
|
+
export { CanonicalSaveDiagnosticError, serializeCanonicalSave };
|
|
@@ -4,7 +4,7 @@ type CanonicalStoryRepackOptions<T> = {
|
|
|
4
4
|
document: document_d_exports.Document;
|
|
5
5
|
repack: () => Promise<T>;
|
|
6
6
|
};
|
|
7
|
-
/** Authorize
|
|
7
|
+
/** Authorize exact canonical section removals and references missing from the committed snapshot. */
|
|
8
8
|
declare const repackWithCanonicalStoryRemovals: <T>({ document, repack }: CanonicalStoryRepackOptions<T>) => Promise<T>;
|
|
9
9
|
//#endregion
|
|
10
10
|
export { repackWithCanonicalStoryRemovals };
|
|
@@ -1,17 +1,28 @@
|
|
|
1
|
+
import { withTrackedSectionEndpointRemoval } from "../internal/sectionEndpointResolution.js";
|
|
1
2
|
import { withSectionReferenceResolution } from "../internal/sectionReferenceResolution.js";
|
|
2
3
|
import { readDocumentSectionFacts } from "./documentSectionFacts.js";
|
|
4
|
+
import { parseDocx } from "./parser.js";
|
|
5
|
+
import { assertSectionCarriersMatchModel } from "./rezip.js";
|
|
3
6
|
import { serializeDocument } from "./serializer/documentSerializer.js";
|
|
4
7
|
import JSZip from "jszip";
|
|
5
8
|
//#region src/docx/canonicalStoryRepack.ts
|
|
6
9
|
/** Canonical snapshots own explicit section references; the PM projection does not. */
|
|
7
10
|
const referenceKey = ({ element, type, rId }) => `${element}:${type}:${rId}`;
|
|
8
|
-
|
|
11
|
+
const xmlFingerprint = async (xml) => {
|
|
12
|
+
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(xml));
|
|
13
|
+
let fingerprint = "";
|
|
14
|
+
for (const byte of new Uint8Array(digest)) fingerprint += byte.toString(16).padStart(2, "0");
|
|
15
|
+
return fingerprint;
|
|
16
|
+
};
|
|
17
|
+
/** Authorize exact canonical section removals and references missing from the committed snapshot. */
|
|
9
18
|
const repackWithCanonicalStoryRemovals = async ({ document, repack }) => {
|
|
10
|
-
|
|
11
|
-
|
|
19
|
+
const originalBuffer = document.originalBuffer;
|
|
20
|
+
if (!originalBuffer) return repack();
|
|
21
|
+
const xml = await (await JSZip.loadAsync(originalBuffer)).file("word/document.xml")?.async("text");
|
|
12
22
|
if (!xml) return repack();
|
|
13
23
|
const before = readDocumentSectionFacts(xml);
|
|
14
|
-
const
|
|
24
|
+
const serializedXml = serializeDocument(document);
|
|
25
|
+
const after = readDocumentSectionFacts(serializedXml);
|
|
15
26
|
const remaining = /* @__PURE__ */ new Map();
|
|
16
27
|
for (const reference of after.headerFooterReferences) {
|
|
17
28
|
const key = referenceKey(reference);
|
|
@@ -34,7 +45,29 @@ const repackWithCanonicalStoryRemovals = async ({ document, repack }) => {
|
|
|
34
45
|
return withSectionReferenceResolution({
|
|
35
46
|
document,
|
|
36
47
|
removedReferences,
|
|
37
|
-
repack
|
|
48
|
+
repack: async () => {
|
|
49
|
+
if (after.sectionCount >= before.sectionCount) return repack();
|
|
50
|
+
const baseline = await parseDocx(originalBuffer, { preloadFonts: false });
|
|
51
|
+
const baselineXml = serializeDocument(baseline);
|
|
52
|
+
const baselineFacts = readDocumentSectionFacts(baselineXml);
|
|
53
|
+
if (baselineFacts.sectionCount !== before.sectionCount) return repack();
|
|
54
|
+
assertSectionCarriersMatchModel({
|
|
55
|
+
doc: baseline,
|
|
56
|
+
serializedSectionCount: baselineFacts.sectionCount
|
|
57
|
+
});
|
|
58
|
+
return withTrackedSectionEndpointRemoval({
|
|
59
|
+
document,
|
|
60
|
+
resolution: {
|
|
61
|
+
type: "tracked-section-endpoint-removal",
|
|
62
|
+
sourceParagraphEndpointCount: before.sectionCount,
|
|
63
|
+
expectedParagraphEndpointCount: after.sectionCount,
|
|
64
|
+
sourceEndpointFingerprint: await xmlFingerprint(baselineXml),
|
|
65
|
+
expectedEndpointFingerprint: await xmlFingerprint(serializedXml),
|
|
66
|
+
removedReferences
|
|
67
|
+
},
|
|
68
|
+
repack
|
|
69
|
+
});
|
|
70
|
+
}
|
|
38
71
|
});
|
|
39
72
|
};
|
|
40
73
|
//#endregion
|
|
@@ -35,9 +35,11 @@ declare const CONTAINER_CHILDREN: {
|
|
|
35
35
|
readonly "w:fldSimple": readonly ["bdo", "bookmarkEnd", "bookmarkStart", "commentRangeEnd", "commentRangeStart", "customXml", "customXmlDelRangeEnd", "customXmlDelRangeStart", "customXmlInsRangeEnd", "customXmlInsRangeStart", "customXmlMoveFromRangeEnd", "customXmlMoveFromRangeStart", "customXmlMoveToRangeEnd", "customXmlMoveToRangeStart", "del", "dir", "fldData", "fldSimple", "hyperlink", "ins", "moveFrom", "moveFromRangeEnd", "moveFromRangeStart", "moveTo", "moveToRangeEnd", "moveToRangeStart", "permEnd", "permStart", "proofErr", "r", "sdt", "smartTag", "subDoc"];
|
|
36
36
|
readonly "block-content": readonly ["altChunk", "bookmarkEnd", "bookmarkStart", "commentRangeEnd", "commentRangeStart", "customXml", "customXmlDelRangeEnd", "customXmlDelRangeStart", "customXmlInsRangeEnd", "customXmlInsRangeStart", "customXmlMoveFromRangeEnd", "customXmlMoveFromRangeStart", "customXmlMoveToRangeEnd", "customXmlMoveToRangeStart", "del", "ins", "moveFrom", "moveFromRangeEnd", "moveFromRangeStart", "moveTo", "moveToRangeEnd", "moveToRangeStart", "p", "permEnd", "permStart", "proofErr", "sdt", "sectPr", "tbl", "tcPr"];
|
|
37
37
|
};
|
|
38
|
+
/** WordprocessingML children permitted directly inside CT_RunTrackChange. */
|
|
39
|
+
declare const TRACKED_RUN_WORDPROCESSING_CHILDREN: readonly ["bdo", "bookmarkEnd", "bookmarkStart", "commentRangeEnd", "commentRangeStart", "customXml", "customXmlDelRangeEnd", "customXmlDelRangeStart", "customXmlInsRangeEnd", "customXmlInsRangeStart", "customXmlMoveFromRangeEnd", "customXmlMoveFromRangeStart", "customXmlMoveToRangeEnd", "customXmlMoveToRangeStart", "del", "dir", "ins", "moveFrom", "moveFromRangeEnd", "moveFromRangeStart", "moveTo", "moveToRangeEnd", "moveToRangeStart", "permEnd", "permStart", "proofErr", "r", "sdt", "smartTag"];
|
|
38
40
|
/** A container the shared child dispatcher covers. */
|
|
39
41
|
type DispatchedContainer = keyof typeof CONTAINER_CHILDREN;
|
|
40
42
|
/** Every child name the schema declares for `Container`. */
|
|
41
43
|
type DeclaredChild<Container extends DispatchedContainer> = (typeof CONTAINER_CHILDREN)[Container][number];
|
|
42
44
|
//#endregion
|
|
43
|
-
export { CONTAINER_CHILDREN, DeclaredChild, DispatchedContainer };
|
|
45
|
+
export { CONTAINER_CHILDREN, DeclaredChild, DispatchedContainer, TRACKED_RUN_WORDPROCESSING_CHILDREN };
|
|
@@ -260,5 +260,37 @@ const CONTAINER_CHILDREN = {
|
|
|
260
260
|
],
|
|
261
261
|
...SEQUENCE_CHILDREN
|
|
262
262
|
};
|
|
263
|
+
/** WordprocessingML children permitted directly inside CT_RunTrackChange. */
|
|
264
|
+
const TRACKED_RUN_WORDPROCESSING_CHILDREN = [
|
|
265
|
+
"bdo",
|
|
266
|
+
"bookmarkEnd",
|
|
267
|
+
"bookmarkStart",
|
|
268
|
+
"commentRangeEnd",
|
|
269
|
+
"commentRangeStart",
|
|
270
|
+
"customXml",
|
|
271
|
+
"customXmlDelRangeEnd",
|
|
272
|
+
"customXmlDelRangeStart",
|
|
273
|
+
"customXmlInsRangeEnd",
|
|
274
|
+
"customXmlInsRangeStart",
|
|
275
|
+
"customXmlMoveFromRangeEnd",
|
|
276
|
+
"customXmlMoveFromRangeStart",
|
|
277
|
+
"customXmlMoveToRangeEnd",
|
|
278
|
+
"customXmlMoveToRangeStart",
|
|
279
|
+
"del",
|
|
280
|
+
"dir",
|
|
281
|
+
"ins",
|
|
282
|
+
"moveFrom",
|
|
283
|
+
"moveFromRangeEnd",
|
|
284
|
+
"moveFromRangeStart",
|
|
285
|
+
"moveTo",
|
|
286
|
+
"moveToRangeEnd",
|
|
287
|
+
"moveToRangeStart",
|
|
288
|
+
"permEnd",
|
|
289
|
+
"permStart",
|
|
290
|
+
"proofErr",
|
|
291
|
+
"r",
|
|
292
|
+
"sdt",
|
|
293
|
+
"smartTag"
|
|
294
|
+
];
|
|
263
295
|
//#endregion
|
|
264
|
-
export { CONTAINER_CHILDREN };
|
|
296
|
+
export { CONTAINER_CHILDREN, TRACKED_RUN_WORDPROCESSING_CHILDREN };
|
|
@@ -54,22 +54,10 @@ declare function getAllParagraphs(body: document_d_exports.DocumentBody): docume
|
|
|
54
54
|
* Get all tables from document body
|
|
55
55
|
*/
|
|
56
56
|
declare function getAllTables(body: document_d_exports.DocumentBody): document_d_exports.Table[];
|
|
57
|
-
/**
|
|
58
|
-
* Get plain text from entire document body
|
|
59
|
-
*/
|
|
60
|
-
declare function getDocumentText(body: document_d_exports.DocumentBody): string;
|
|
61
57
|
/**
|
|
62
58
|
* Count total paragraphs in document
|
|
63
59
|
*/
|
|
64
60
|
declare function getParagraphCount(body: document_d_exports.DocumentBody): number;
|
|
65
|
-
/**
|
|
66
|
-
* Count total words in document (approximate)
|
|
67
|
-
*/
|
|
68
|
-
declare function getWordCount(body: document_d_exports.DocumentBody): number;
|
|
69
|
-
/**
|
|
70
|
-
* Count total characters in document
|
|
71
|
-
*/
|
|
72
|
-
declare function getCharacterCount(body: document_d_exports.DocumentBody): number;
|
|
73
61
|
/**
|
|
74
62
|
* Get section count
|
|
75
63
|
*/
|
|
@@ -79,4 +67,4 @@ declare function getSectionCount(body: document_d_exports.DocumentBody): number;
|
|
|
79
67
|
*/
|
|
80
68
|
declare function hasTemplateVariables(body: document_d_exports.DocumentBody): boolean;
|
|
81
69
|
//#endregion
|
|
82
|
-
export { extractAllTemplateVariables, extractTemplateVariables, getAllParagraphs, getAllTables,
|
|
70
|
+
export { extractAllTemplateVariables, extractTemplateVariables, getAllParagraphs, getAllTables, getParagraphCount, getSectionCount, hasTemplateVariables, parseDocumentBody, parseDocumentBodyTree };
|