@stll/folio-core 0.35.1 → 0.37.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 +59 -1
- package/dist/ai-edits/apply.js +878 -377
- package/dist/ai-edits/block-identity.d.ts +4 -1
- package/dist/ai-edits/block-identity.js +4 -1
- package/dist/ai-edits/blockRange.js +14 -14
- package/dist/ai-edits/clean-text.d.ts +40 -1
- package/dist/ai-edits/clean-text.js +52 -2
- package/dist/ai-edits/headless.d.ts +3 -1
- package/dist/ai-edits/headless.js +141 -73
- package/dist/ai-edits/index.d.ts +3 -3
- package/dist/ai-edits/index.js +2 -2
- package/dist/ai-edits/read.js +38 -20
- package/dist/ai-edits/snapshot.d.ts +14 -6
- package/dist/ai-edits/snapshot.js +105 -20
- package/dist/ai-edits/table-cell-mutations.js +1 -1
- package/dist/ai-edits/table-row-column-mutations.js +7 -0
- package/dist/ai-edits/table-template.d.ts +11 -1
- package/dist/ai-edits/table-template.js +49 -17
- package/dist/ai-edits/types.d.ts +62 -61
- package/dist/ai-edits/word-diff.d.ts +18 -3
- package/dist/ai-edits/word-diff.js +556 -67
- package/dist/ai-suggestions/conflict.js +1 -4
- package/dist/ai-suggestions/text-positions.d.ts +8 -0
- package/dist/ai-suggestions/text-positions.js +27 -5
- package/dist/compare/__fixtures__/body-sequence.js +3 -4
- package/dist/compare/column-alignment.d.ts +13 -13
- package/dist/compare/column-alignment.js +78 -39
- package/dist/compare/compare.d.ts +4 -3
- package/dist/compare/compare.js +48 -21
- package/dist/compare/content-alignment.d.ts +95 -0
- package/dist/compare/content-alignment.js +1450 -0
- package/dist/compare/content-types.d.ts +100 -0
- package/dist/compare/content-types.js +0 -0
- package/dist/compare/content.d.ts +209 -0
- package/dist/compare/content.js +885 -0
- package/dist/compare/formatting.d.ts +5 -5
- package/dist/compare/formatting.js +6 -4
- package/dist/compare/plan.d.ts +6 -1
- package/dist/compare/plan.js +171 -566
- package/dist/compare/scenario.d.ts +2 -2
- package/dist/compare/types.d.ts +3 -3
- package/dist/compare/verification.d.ts +8 -9
- package/dist/compare/verification.js +72 -50
- package/dist/compat/eigenpal.d.ts +5 -3
- package/dist/compat/eigenpal.js +3 -2
- package/dist/controller/headerFooterEditorManager.js +18 -10
- package/dist/controller/hiddenEditorApi.js +1 -1
- package/dist/controller/hiddenEditorManager.d.ts +7 -2
- package/dist/controller/hiddenEditorManager.js +15 -6
- package/dist/controller/layoutPipeline.js +5 -3
- package/dist/controller/noteEditorManager.js +12 -7
- package/dist/display-list/build/headerFooterPrimitives.js +1 -0
- package/dist/display-list/build/storyPrimitives.d.ts +5 -2
- package/dist/display-list/build/storyPrimitives.js +60 -3
- package/dist/display-list/build/tablePrimitives.js +30 -0
- package/dist/display-list/primitives.d.ts +1 -1
- package/dist/document-operations.d.ts +8 -4
- package/dist/document-operations.js +104 -12
- package/dist/docx/blockContentParser.js +6 -27
- package/dist/docx/commentParser.js +2 -4
- package/dist/docx/commentRangeIntegrity.js +2 -4
- package/dist/docx/documentClone.d.ts +2 -0
- package/dist/docx/documentClone.js +2 -0
- package/dist/docx/ensureParaIds.js +9 -4
- package/dist/docx/headerFooterParser.js +2 -4
- package/dist/docx/normalizeBaseDirection.js +5 -7
- package/dist/docx/numberingParser.d.ts +3 -1
- package/dist/docx/numberingParser.js +4 -1
- package/dist/docx/paragraphParser.js +34 -35
- package/dist/docx/paragraphPropertySource.d.ts +49 -0
- package/dist/docx/paragraphPropertySource.js +113 -0
- package/dist/docx/paragraphTraversal.js +30 -34
- package/dist/docx/rezip.d.ts +0 -8
- package/dist/docx/rezip.js +41 -16
- package/dist/docx/runConsolidator.js +2 -4
- package/dist/docx/runParser.js +6 -17
- package/dist/docx/sectionParser.js +1 -15
- package/dist/docx/serializer/paragraphSerializer.js +289 -30
- package/dist/docx/serializer/runSerializer.js +6 -12
- package/dist/docx/serializer/sectionPropertiesSerializer.js +2 -10
- package/dist/docx/serializer/tableSerializer.js +4 -23
- package/dist/docx/serializer/trackedChangeAttributes.d.ts +11 -0
- package/dist/docx/serializer/trackedChangeAttributes.js +31 -0
- package/dist/docx/server/build.d.ts +1 -1
- package/dist/docx/server/createBilingualDocument.js +8 -10
- package/dist/docx/server/evaluateDocxXmlPatchProposal.js +22 -13
- package/dist/docx/server/validateDocxConformance.js +17 -13
- package/dist/docx/tableParser.js +1 -37
- package/dist/docx/trackedChangeInfo.d.ts +11 -0
- package/dist/docx/trackedChangeInfo.js +38 -0
- package/dist/docx/verbatimCapture.d.ts +20 -9
- package/dist/docx/verbatimCapture.js +208 -8
- package/dist/docx/xmlParser.d.ts +3 -1
- package/dist/docx/xmlParser.js +6 -1
- package/dist/docx/xmlSafety.d.ts +1 -1
- package/dist/docx/xmlSafety.js +157 -0
- package/dist/headless-layout.js +5 -4
- package/dist/index.d.ts +5 -3
- package/dist/index.js +3 -2
- package/dist/internal/headlessRevisionResolution.d.ts +23 -0
- package/dist/internal/headlessRevisionResolution.js +155 -0
- package/dist/internal/headlessRevisionResolutionGuard.d.ts +12 -0
- package/dist/internal/headlessRevisionResolutionGuard.js +28 -0
- package/dist/internal/pageBreakRunDescendantIndex.d.ts +9 -0
- package/dist/internal/pageBreakRunDescendantIndex.js +27 -0
- package/dist/internal/pageBreakRunPartition.d.ts +26 -0
- package/dist/internal/pageBreakRunPartition.js +35 -0
- package/dist/internal/pageBreakRunSourceDescendantIndex.d.ts +15 -0
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +126 -0
- package/dist/internal/sectionEndpointResolution.d.ts +32 -0
- package/dist/internal/sectionEndpointResolution.js +38 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +16 -4
- package/dist/layout-bridge/convert/headerFooterLayout.js +52 -9
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +4 -0
- package/dist/layout-bridge/convert/toFlowBlocks.js +391 -82
- package/dist/layout-bridge/dom/clickToPositionDom.d.ts +8 -1
- package/dist/layout-bridge/dom/clickToPositionDom.js +114 -40
- package/dist/layout-bridge/dom/textStreamDom.d.ts +24 -0
- package/dist/layout-bridge/dom/textStreamDom.js +75 -0
- package/dist/layout-bridge/headerFooterLayout.js +16 -30
- package/dist/layout-engine/index.js +12 -3
- package/dist/layout-engine/measure/tableFragmentBorderGeometry.d.ts +17 -0
- package/dist/layout-engine/measure/tableFragmentBorderGeometry.js +24 -0
- package/dist/layout-engine/renderedBreakReconciliation.js +1 -1
- package/dist/layout-engine/types.d.ts +7 -0
- package/dist/layout-painter/imageLayout.d.ts +1 -1
- package/dist/layout-painter/renderTable.js +20 -0
- package/dist/markdown/renderBlock.js +7 -10
- package/dist/model.d.ts +1 -1
- package/dist/paged-layout/rangeProjection.js +6 -9
- package/dist/paged-layout/transactionDirtyRange.d.ts +3 -1
- package/dist/paged-layout/transactionDirtyRange.js +23 -1
- package/dist/prosemirror/attrs/index.d.ts +7 -3
- package/dist/prosemirror/attrs/index.js +128 -7
- package/dist/prosemirror/bookmarkBoundaryIntegrity.d.ts +9 -0
- package/dist/prosemirror/bookmarkBoundaryIntegrity.js +22 -0
- package/dist/prosemirror/commands/comments.d.ts +10 -1
- package/dist/prosemirror/commands/comments.js +551 -87
- package/dist/prosemirror/commands/formatPainter.d.ts +45 -10
- package/dist/prosemirror/commands/formatPainter.js +319 -63
- package/dist/prosemirror/commands/index.d.ts +2 -2
- package/dist/prosemirror/commands/pageBreak.d.ts +5 -2
- package/dist/prosemirror/commands/pageBreak.js +18 -36
- package/dist/prosemirror/commands/propertyChangeScope.d.ts +27 -3
- package/dist/prosemirror/commands/propertyChangeScope.js +85 -14
- package/dist/prosemirror/conversion/fromProseDoc.d.ts +8 -5
- package/dist/prosemirror/conversion/fromProseDoc.js +935 -223
- package/dist/prosemirror/conversion/runShadingMark.js +2 -2
- package/dist/prosemirror/conversion/toProseDoc.d.ts +26 -1
- package/dist/prosemirror/conversion/toProseDoc.js +439 -291
- package/dist/prosemirror/extensions/StarterKit.js +4 -0
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +54 -6
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +7 -1
- package/dist/prosemirror/extensions/features/ListExtension.js +95 -123
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +19 -6
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +27 -1
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +134 -30
- package/dist/prosemirror/extensions/features/pasteCleanup.js +9 -15
- package/dist/prosemirror/extensions/marks/BoldExtension.js +4 -3
- package/dist/prosemirror/extensions/marks/CharacterStyleExtension.d.ts +4 -7
- package/dist/prosemirror/extensions/marks/CharacterStyleExtension.js +5 -11
- package/dist/prosemirror/extensions/marks/FontSizeExtension.js +3 -3
- package/dist/prosemirror/extensions/marks/ItalicExtension.js +4 -3
- package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.d.ts +13 -0
- package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.js +39 -0
- package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.d.ts +7 -1
- package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.js +67 -21
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +2 -0
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +8 -1
- package/dist/prosemirror/extensions/marks/markUtils.js +88 -2
- package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +44 -3
- package/dist/prosemirror/extensions/nodes/FieldExtension.js +1 -1
- package/dist/prosemirror/extensions/nodes/HardBreakExtension.js +15 -4
- package/dist/prosemirror/extensions/nodes/PageBreakExtension.d.ts +6 -0
- package/dist/prosemirror/extensions/nodes/PageBreakExtension.js +6 -0
- package/dist/prosemirror/extensions/nodes/PageBreakRunExtension.d.ts +6 -0
- package/dist/prosemirror/extensions/nodes/PageBreakRunExtension.js +36 -0
- package/dist/prosemirror/findReplaceSelection.js +8 -3
- package/dist/prosemirror/index.d.ts +3 -3
- package/dist/prosemirror/listMarker.d.ts +26 -1
- package/dist/prosemirror/listMarker.js +108 -14
- package/dist/prosemirror/pageBreakRunProjection.d.ts +28 -0
- package/dist/prosemirror/pageBreakRunProjection.js +47 -0
- package/dist/prosemirror/paraText.js +6 -0
- package/dist/prosemirror/paragraphAlignment.d.ts +12 -0
- package/dist/prosemirror/paragraphAlignment.js +13 -0
- package/dist/prosemirror/paragraphSpacing.d.ts +29 -0
- package/dist/prosemirror/paragraphSpacing.js +125 -0
- package/dist/prosemirror/plugins/documentNumbering.d.ts +8 -0
- package/dist/prosemirror/plugins/documentNumbering.js +18 -0
- package/dist/prosemirror/plugins/pmTextScan.d.ts +3 -2
- package/dist/prosemirror/plugins/pmTextScan.js +14 -4
- package/dist/prosemirror/plugins/suggestionMode.js +9 -11
- package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +16 -0
- package/dist/prosemirror/rebaseParagraphRunFormatting.js +61 -0
- package/dist/prosemirror/runFormattingInlineCarriers.d.ts +64 -0
- package/dist/prosemirror/runFormattingInlineCarriers.js +121 -0
- package/dist/prosemirror/runFormattingProvenance.d.ts +12 -0
- package/dist/prosemirror/runFormattingProvenance.js +48 -0
- package/dist/prosemirror/runFormattingReconciliation.d.ts +25 -0
- package/dist/prosemirror/runFormattingReconciliation.js +54 -0
- package/dist/prosemirror/runPropertyChangeResolution.d.ts +18 -0
- package/dist/prosemirror/runPropertyChangeResolution.js +18 -0
- package/dist/prosemirror/runStyleFormatting.d.ts +50 -0
- package/dist/prosemirror/runStyleFormatting.js +105 -0
- package/dist/prosemirror/schema/index.d.ts +3 -3
- package/dist/prosemirror/schema/marks.d.ts +84 -9
- package/dist/prosemirror/schema/marks.js +73 -1
- package/dist/prosemirror/schema/nodes.d.ts +30 -6
- package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +14 -2
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +45 -23
- package/dist/prosemirror/styles/styleResolver.d.ts +10 -13
- package/dist/prosemirror/styles/styleResolver.js +3 -3
- package/dist/prosemirror/styles/styleToggleCascade.d.ts +8 -1
- package/dist/prosemirror/styles/styleToggleCascade.js +24 -1
- package/dist/prosemirror/tableGridMutation.d.ts +20 -0
- package/dist/prosemirror/tableGridMutation.js +30 -0
- package/dist/prosemirror/trackedRunInlineAtoms.d.ts +31 -0
- package/dist/prosemirror/trackedRunInlineAtoms.js +39 -0
- package/dist/prosemirror/utils/visualLineNavigation.js +27 -31
- package/dist/prosemirror/validation.js +23 -4
- package/dist/redline.js +4 -1
- package/dist/render-dom/HeaderFooterSelectionOverlay.js +20 -20
- package/dist/render-dom/RenderedDomContext.js +17 -34
- package/dist/server.d.ts +4 -4
- package/dist/server.js +2 -2
- package/dist/style-engine/styleEngine.d.ts +1 -1
- package/dist/utils/clipboard.js +1 -1
- package/dist/utils/findReplace.js +38 -21
- package/dist/utils/mergeDocumentContent.js +3 -3
- package/dist/utils/replaceText.js +2 -1
- package/dist/version-comparison.d.ts +38 -44
- package/dist/version-comparison.js +270 -399
- package/dist/watermark/index.js +2 -4
- package/package.json +8 -2
|
@@ -5,6 +5,7 @@ import { ExtensionManager } from "../prosemirror/extensions/ExtensionManager.js"
|
|
|
5
5
|
import { createStarterKit } from "../prosemirror/extensions/StarterKit.js";
|
|
6
6
|
import { ensureBaseDirectionInState } from "../prosemirror/extensions/features/AutoBidiDetectionExtension.js";
|
|
7
7
|
import { ensureParaIdsInState } from "../prosemirror/extensions/features/ParaIdAllocatorExtension.js";
|
|
8
|
+
import { createDocumentNumberingPlugin } from "../prosemirror/plugins/documentNumbering.js";
|
|
8
9
|
import { createDocumentStylesPlugin } from "../prosemirror/plugins/documentStyles.js";
|
|
9
10
|
import { schema } from "../prosemirror/schema/index.js";
|
|
10
11
|
import { EditorState } from "prosemirror-state";
|
|
@@ -31,14 +32,15 @@ const noteToProseDocument = (note, styles, theme) => {
|
|
|
31
32
|
if (theme !== void 0) options.theme = theme;
|
|
32
33
|
return footnoteToProseDoc(note.content, options);
|
|
33
34
|
};
|
|
34
|
-
const buildInitialState = (document, styles, manager, externalPlugins) => {
|
|
35
|
+
const buildInitialState = (document, styles, numbering, manager, externalPlugins) => {
|
|
35
36
|
return ensureBaseDirectionInState(ensureParaIdsInState(EditorState.create({
|
|
36
37
|
doc: document,
|
|
37
38
|
schema,
|
|
38
39
|
plugins: [
|
|
39
40
|
...manager.getPlugins(),
|
|
40
41
|
...externalPlugins,
|
|
41
|
-
createDocumentStylesPlugin(styles)
|
|
42
|
+
createDocumentStylesPlugin(styles),
|
|
43
|
+
createDocumentNumberingPlugin(numbering)
|
|
42
44
|
]
|
|
43
45
|
})));
|
|
44
46
|
};
|
|
@@ -65,6 +67,7 @@ const createNoteEditorManager = (deps) => {
|
|
|
65
67
|
const document = deps.getDocument();
|
|
66
68
|
const styles = deps.getStyles();
|
|
67
69
|
const theme = deps.getTheme();
|
|
70
|
+
const numbering = document?.package.numbering;
|
|
68
71
|
const externalPlugins = deps.getPlugins?.() ?? EMPTY_PLUGINS;
|
|
69
72
|
const wanted = new Map(enumerateDocumentNoteStories(document).map((story) => [storyMapKey(story), story]));
|
|
70
73
|
const activeKey = active ? storyMapKey(active) : null;
|
|
@@ -81,18 +84,19 @@ const createNoteEditorManager = (deps) => {
|
|
|
81
84
|
if (existing) {
|
|
82
85
|
if (existing.mountNode.parentElement !== host) host.append(existing.mountNode);
|
|
83
86
|
const nextProseDocument = noteToProseDocument(note, styles, theme);
|
|
84
|
-
const contextIsCurrent = existing.appliedStyles === styles && existing.appliedTheme === theme && existing.appliedPlugins === externalPlugins;
|
|
87
|
+
const contextIsCurrent = existing.appliedStyles === styles && existing.appliedTheme === theme && existing.appliedNumbering === numbering && existing.appliedPlugins === externalPlugins;
|
|
85
88
|
if ((existing.appliedNote === note && existing.appliedContent === note.content || existing.appliedProseDocument.eq(nextProseDocument)) && contextIsCurrent) {
|
|
86
89
|
existing.appliedNote = note;
|
|
87
90
|
existing.appliedContent = note.content;
|
|
88
91
|
existing.appliedProseDocument = nextProseDocument;
|
|
89
92
|
continue;
|
|
90
93
|
}
|
|
91
|
-
existing.view.updateState(buildInitialState(nextProseDocument, styles, existing.manager, externalPlugins));
|
|
94
|
+
existing.view.updateState(buildInitialState(nextProseDocument, styles, numbering, existing.manager, externalPlugins));
|
|
92
95
|
existing.appliedNote = note;
|
|
93
96
|
existing.appliedContent = note.content;
|
|
94
97
|
existing.appliedStyles = styles;
|
|
95
98
|
existing.appliedTheme = theme;
|
|
99
|
+
existing.appliedNumbering = numbering;
|
|
96
100
|
existing.appliedPlugins = externalPlugins;
|
|
97
101
|
existing.appliedProseDocument = nextProseDocument;
|
|
98
102
|
existing.dirty = false;
|
|
@@ -107,7 +111,7 @@ const createNoteEditorManager = (deps) => {
|
|
|
107
111
|
host.append(mountNode);
|
|
108
112
|
const proseDocument = noteToProseDocument(note, styles, theme);
|
|
109
113
|
const view = new EditorView(mountNode, {
|
|
110
|
-
state: buildInitialState(proseDocument, styles, manager, externalPlugins),
|
|
114
|
+
state: buildInitialState(proseDocument, styles, numbering, manager, externalPlugins),
|
|
111
115
|
dispatchTransaction(transaction) {
|
|
112
116
|
view.updateState(view.state.apply(transaction));
|
|
113
117
|
const mountedStory = mounted.get(key);
|
|
@@ -123,6 +127,7 @@ const createNoteEditorManager = (deps) => {
|
|
|
123
127
|
mounted.set(key, {
|
|
124
128
|
appliedContent: note.content,
|
|
125
129
|
appliedNote: note,
|
|
130
|
+
appliedNumbering: numbering,
|
|
126
131
|
appliedPlugins: externalPlugins,
|
|
127
132
|
appliedProseDocument: proseDocument,
|
|
128
133
|
appliedStyles: styles,
|
|
@@ -169,7 +174,7 @@ const createNoteEditorManager = (deps) => {
|
|
|
169
174
|
}
|
|
170
175
|
const updated = {
|
|
171
176
|
...current,
|
|
172
|
-
content: proseDocToBlocks(story.view.state.doc)
|
|
177
|
+
content: proseDocToBlocks(story.view.state.doc, current.content, document.package.styles)
|
|
173
178
|
};
|
|
174
179
|
footnotes[index] = updated;
|
|
175
180
|
story.appliedNote = updated;
|
|
@@ -186,7 +191,7 @@ const createNoteEditorManager = (deps) => {
|
|
|
186
191
|
}
|
|
187
192
|
const updated = {
|
|
188
193
|
...current,
|
|
189
|
-
content: proseDocToBlocks(story.view.state.doc)
|
|
194
|
+
content: proseDocToBlocks(story.view.state.doc, current.content, document.package.styles)
|
|
190
195
|
};
|
|
191
196
|
endnotes[index] = updated;
|
|
192
197
|
story.appliedNote = updated;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FlowBlock, Measure } from "../../layout-engine/types.js";
|
|
1
|
+
import { FlowBlock, Measure, Page } from "../../layout-engine/types.js";
|
|
2
2
|
import { BuildContext } from "./buildContext.js";
|
|
3
3
|
import { PageComposer } from "./regions.js";
|
|
4
4
|
//#region src/display-list/build/storyPrimitives.d.ts
|
|
@@ -13,6 +13,9 @@ type PaintStoryOptions = {
|
|
|
13
13
|
readonly context: BuildContext;
|
|
14
14
|
readonly label: string;
|
|
15
15
|
};
|
|
16
|
+
type PaintHeaderFooterStoryOptions = PaintStoryOptions & {
|
|
17
|
+
readonly page: Page;
|
|
18
|
+
};
|
|
16
19
|
/**
|
|
17
20
|
* A footnote body: every block stacks by its measured height, which is the
|
|
18
21
|
* height the paginator reserved the band from.
|
|
@@ -24,6 +27,6 @@ declare const paintFootnoteBlocks: ({ composer, blocks, measures, xPx, yPx, widt
|
|
|
24
27
|
* they are reported rather than painted: their position resolves against page
|
|
25
28
|
* and margin anchors the display list producer does not carry.
|
|
26
29
|
*/
|
|
27
|
-
declare const paintHeaderFooterBlocks: ({ composer, blocks, measures, xPx, yPx, widthPx, context, label }:
|
|
30
|
+
declare const paintHeaderFooterBlocks: ({ composer, blocks, measures, xPx, yPx, widthPx, page, context, label }: PaintHeaderFooterStoryOptions) => void;
|
|
28
31
|
//#endregion
|
|
29
32
|
export { PaintStoryOptions, paintFootnoteBlocks, paintHeaderFooterBlocks };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isFloatingImageRun, isFloatingTextBoxBlock } from "../../layout-engine/types.js";
|
|
2
|
+
import { resolveAnchoredImagePosition } from "../../layout-painter/anchoredImagePosition.js";
|
|
2
3
|
import { HIT_REGION_KINDS } from "../primitives.js";
|
|
3
|
-
import { paintImageFragment } from "./imagePrimitives.js";
|
|
4
|
+
import { paintImage, paintImageFragment } from "./imagePrimitives.js";
|
|
4
5
|
import { paintParagraphFragment } from "./paragraphPrimitives.js";
|
|
5
6
|
import { blockRegion } from "./regions.js";
|
|
6
7
|
import { paintTableFragment } from "./tablePrimitives.js";
|
|
@@ -150,6 +151,47 @@ const measuredHeightPx = (measure) => {
|
|
|
150
151
|
default: return 0;
|
|
151
152
|
}
|
|
152
153
|
};
|
|
154
|
+
const paintHeaderFooterFloatingImage = ({ composer, run, block, paragraphYPx, page, context, label }) => {
|
|
155
|
+
const contentWidth = page.size.w - page.margins.left - page.margins.right;
|
|
156
|
+
const geometry = {
|
|
157
|
+
pageWidth: page.size.w,
|
|
158
|
+
pageHeight: page.size.h,
|
|
159
|
+
marginLeft: page.margins.left,
|
|
160
|
+
marginTop: page.margins.top,
|
|
161
|
+
marginRight: page.margins.right,
|
|
162
|
+
marginBottom: page.margins.bottom,
|
|
163
|
+
...page.authoredMargins === void 0 ? {} : { authoredMargins: page.authoredMargins },
|
|
164
|
+
contentWidth,
|
|
165
|
+
contentHeight: page.size.h - page.margins.top - page.margins.bottom
|
|
166
|
+
};
|
|
167
|
+
const position = resolveAnchoredImagePosition(run, paragraphYPx - page.margins.top, geometry);
|
|
168
|
+
const fragment = {
|
|
169
|
+
blockId: block.id,
|
|
170
|
+
x: page.margins.left + position.x,
|
|
171
|
+
y: page.margins.top + position.y,
|
|
172
|
+
width: run.width,
|
|
173
|
+
height: run.height,
|
|
174
|
+
...run.pmStart === void 0 ? {} : { pmStart: run.pmStart },
|
|
175
|
+
...run.pmEnd === void 0 ? {} : { pmEnd: run.pmEnd }
|
|
176
|
+
};
|
|
177
|
+
composer.region(blockRegion({
|
|
178
|
+
fragment,
|
|
179
|
+
kind: HIT_REGION_KINDS.image,
|
|
180
|
+
context
|
|
181
|
+
}), () => {
|
|
182
|
+
composer.push(paintImage({
|
|
183
|
+
source: run,
|
|
184
|
+
rect: {
|
|
185
|
+
xPx: fragment.x,
|
|
186
|
+
yPx: fragment.y,
|
|
187
|
+
widthPx: fragment.width,
|
|
188
|
+
heightPx: fragment.height
|
|
189
|
+
},
|
|
190
|
+
context,
|
|
191
|
+
label: `${label} floating image`
|
|
192
|
+
}));
|
|
193
|
+
});
|
|
194
|
+
};
|
|
153
195
|
/**
|
|
154
196
|
* A footnote body: every block stacks by its measured height, which is the
|
|
155
197
|
* height the paginator reserved the band from.
|
|
@@ -182,7 +224,7 @@ const paintFootnoteBlocks = ({ composer, blocks, measures, xPx, yPx, widthPx, co
|
|
|
182
224
|
* they are reported rather than painted: their position resolves against page
|
|
183
225
|
* and margin anchors the display list producer does not carry.
|
|
184
226
|
*/
|
|
185
|
-
const paintHeaderFooterBlocks = ({ composer, blocks, measures, xPx, yPx, widthPx, context, label }) => {
|
|
227
|
+
const paintHeaderFooterBlocks = ({ composer, blocks, measures, xPx, yPx, widthPx, page, context, label }) => {
|
|
186
228
|
let cursorYPx = yPx;
|
|
187
229
|
const reportOutOfFlow = (detail) => {
|
|
188
230
|
context.unsupported.report(UNSUPPORTED_CONSTRUCT.headerFooterContent, context.pageIndex, `${label}: ${detail}`);
|
|
@@ -196,7 +238,6 @@ const paintHeaderFooterBlocks = ({ composer, blocks, measures, xPx, yPx, widthPx
|
|
|
196
238
|
switch (block.kind) {
|
|
197
239
|
case "paragraph":
|
|
198
240
|
if (measure.kind !== "paragraph") break;
|
|
199
|
-
if (block.runs.some((run) => run.kind === "image" && (isFloatingImageRun(run) || run.position !== void 0))) reportOutOfFlow(`paragraph ${String(block.id)} anchors a floating picture, which resolves against page and margin anchors the display list does not carry`);
|
|
200
241
|
paintStoryBlock({
|
|
201
242
|
composer,
|
|
202
243
|
block,
|
|
@@ -208,6 +249,22 @@ const paintHeaderFooterBlocks = ({ composer, blocks, measures, xPx, yPx, widthPx
|
|
|
208
249
|
label,
|
|
209
250
|
construct: UNSUPPORTED_CONSTRUCT.headerFooterContent
|
|
210
251
|
});
|
|
252
|
+
for (const run of block.runs) {
|
|
253
|
+
if (run.kind !== "image" || !isFloatingImageRun(run) && run.position === void 0) continue;
|
|
254
|
+
if (run.wrapType === "behind") {
|
|
255
|
+
reportOutOfFlow(`paragraph ${String(block.id)} anchors a behind-text picture that requires the page-underlay paint phase`);
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
paintHeaderFooterFloatingImage({
|
|
259
|
+
composer,
|
|
260
|
+
run,
|
|
261
|
+
block,
|
|
262
|
+
paragraphYPx: cursorYPx,
|
|
263
|
+
page,
|
|
264
|
+
context,
|
|
265
|
+
label
|
|
266
|
+
});
|
|
267
|
+
}
|
|
211
268
|
cursorYPx += measure.totalHeight;
|
|
212
269
|
continue;
|
|
213
270
|
case "table":
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createTableCellFlowState, placeTableCellBlock } from "../../layout-engine/measure/tableCellFlow.js";
|
|
2
2
|
import { buildTableCellGrid, buildTableCellPlacements, getSourceCellAt } from "../../layout-engine/measure/tableCellGrid.js";
|
|
3
|
+
import { tableFragmentBottomBorders } from "../../layout-engine/measure/tableFragmentBorderGeometry.js";
|
|
3
4
|
import { resolveTableCellPadding } from "../../layout-engine/types.js";
|
|
4
5
|
import { HIT_REGION_KINDS } from "../primitives.js";
|
|
5
6
|
import { parseDisplayColor } from "./colors.js";
|
|
@@ -332,6 +333,28 @@ const paintTableBody = ({ composer, block, measure, xPx, yPx, fromRow, toRow, he
|
|
|
332
333
|
cursorYPx += rowMeasure.height;
|
|
333
334
|
}
|
|
334
335
|
};
|
|
336
|
+
const paintFragmentBottomBorders = ({ composer, fragment, block, measure, context }) => {
|
|
337
|
+
if (fragment.continuesOnNext !== true || fragment.bottomClip === void 0) return;
|
|
338
|
+
const primitives = [];
|
|
339
|
+
for (const { left, width, border } of tableFragmentBottomBorders({
|
|
340
|
+
fragment,
|
|
341
|
+
block,
|
|
342
|
+
measure
|
|
343
|
+
})) {
|
|
344
|
+
const stroke = strokeFor(border, context, "table fragment bottom border");
|
|
345
|
+
if (!stroke) continue;
|
|
346
|
+
const yPx = fragment.y + fragment.height - stroke.thicknessPx / 2;
|
|
347
|
+
primitives.push({
|
|
348
|
+
kind: "line",
|
|
349
|
+
x1Px: fragment.x + left,
|
|
350
|
+
y1Px: yPx,
|
|
351
|
+
x2Px: fragment.x + left + width,
|
|
352
|
+
y2Px: yPx,
|
|
353
|
+
stroke
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
composer.push(primitives);
|
|
357
|
+
};
|
|
335
358
|
/** A whole, unpaginated table: what a nested table inside a cell or box is. */
|
|
336
359
|
const paintTableBlock = ({ composer, block, measure, xPx, yPx, context, paintTextBox }) => paintTableBody({
|
|
337
360
|
composer,
|
|
@@ -404,6 +427,13 @@ const paintTableFragment = ({ composer, fragment, block, measure, context, paint
|
|
|
404
427
|
children: [...clipped.primitives()],
|
|
405
428
|
regions: [...clipped.regions()]
|
|
406
429
|
}]);
|
|
430
|
+
paintFragmentBottomBorders({
|
|
431
|
+
composer,
|
|
432
|
+
fragment,
|
|
433
|
+
block,
|
|
434
|
+
measure,
|
|
435
|
+
context
|
|
436
|
+
});
|
|
407
437
|
};
|
|
408
438
|
//#endregion
|
|
409
439
|
export { paintTableBlock, paintTableFragment };
|
|
@@ -15,7 +15,7 @@ import { hasComplexScript, isComplexScriptCodePoint } from "../utils/scriptSegme
|
|
|
15
15
|
* advances rightward from its origin whatever the paragraph does.
|
|
16
16
|
*/
|
|
17
17
|
declare const glyphCellOffsetsPx: (run: DisplayGlyphRun) => readonly number[];
|
|
18
|
-
declare const DISPLAY_PRIMITIVE_KINDS: ("
|
|
18
|
+
declare const DISPLAY_PRIMITIVE_KINDS: ("image" | "line" | "rect" | "glyphRun" | "clipGroup" | "rotateGroup" | "opacityGroup")[];
|
|
19
19
|
/**
|
|
20
20
|
* Dash geometry of each stroke pattern, as multiples of the stroke thickness.
|
|
21
21
|
*
|
|
@@ -3,6 +3,10 @@ import { FolioAIEditAppliedOperation, FolioAIEditApplyMode, FolioAIEditNormaliza
|
|
|
3
3
|
import { FolioAIEditView, FolioRevisionStamp, FolioWordDiffOptions } from "./ai-edits/apply.js";
|
|
4
4
|
//#region src/document-operations.d.ts
|
|
5
5
|
declare const FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION: 1;
|
|
6
|
+
/** Direct paragraph-alignment values accepted by the operation contract. */
|
|
7
|
+
declare const FOLIO_PARAGRAPH_ALIGNMENT_VALUES: readonly ("left" | "center" | "right" | "both" | "distribute" | "mediumKashida" | "highKashida" | "lowKashida" | "thaiDistribute")[];
|
|
8
|
+
/** `w:spacing/@w:lineRule` values accepted by the operation contract. */
|
|
9
|
+
declare const FOLIO_LINE_SPACING_RULE_VALUES: readonly ("auto" | "exact" | "atLeast")[];
|
|
6
10
|
declare const FOLIO_DOCUMENT_OPERATION_TYPES: readonly ["replaceInBlock", "replaceRange", "commentOnRange", "formatRange", "insertAfterBlock", "insertBeforeBlock", "replaceBlock", "deleteBlock", "splitBlock", "mergeBlockWithNext", "setBlockParagraphProperties", "insertTable", "deleteTable", "commentOnBlock", "insertSignatureTable", "insertTableRow", "deleteTableRow", "insertTableColumn", "deleteTableColumn", "mergeTableCells", "splitTableCell"];
|
|
7
11
|
declare const FOLIO_DOCUMENT_OPERATION_MODES: readonly ["direct", "tracked-changes", "suggested"];
|
|
8
12
|
declare const FOLIO_DOCUMENT_OPERATION_STORIES: readonly ["main", "header", "footer", "footnote", "endnote"];
|
|
@@ -93,8 +97,8 @@ declare const FOLIO_DOCUMENT_OPERATION_KEYS_BY_TYPE: Readonly<{
|
|
|
93
97
|
readonly replaceRange: readonly ["id", "type", "range", "severity", "area", "precondition", "suggestionId", "replace", "comment"];
|
|
94
98
|
readonly commentOnRange: readonly ["id", "type", "range", "severity", "area", "precondition", "comment"];
|
|
95
99
|
readonly formatRange: readonly ["id", "type", "range", "severity", "area", "precondition", "suggestionId", "formatting"];
|
|
96
|
-
readonly insertAfterBlock: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "text", "inheritFormatting", "listLevel", "moveId", "pageBreakBefore", "styleId", "comment"];
|
|
97
|
-
readonly insertBeforeBlock: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "text", "inheritFormatting", "listLevel", "moveId", "pageBreakBefore", "styleId", "comment"];
|
|
100
|
+
readonly insertAfterBlock: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "text", "inheritFormatting", "alignment", "spacing", "listLevel", "moveId", "pageBreakBefore", "styleId", "comment"];
|
|
101
|
+
readonly insertBeforeBlock: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "text", "inheritFormatting", "alignment", "spacing", "listLevel", "moveId", "pageBreakBefore", "styleId", "comment"];
|
|
98
102
|
readonly replaceBlock: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "text", "preserveFormatting", "styleId", "comment"];
|
|
99
103
|
readonly deleteBlock: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "moveId", "comment"];
|
|
100
104
|
readonly splitBlock: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "offset", "separator"];
|
|
@@ -117,7 +121,7 @@ declare const parseFolioDocumentOperationBatch: (value: unknown) => FolioDocumen
|
|
|
117
121
|
* review queue instead of applying it; the core apply path never produces it.
|
|
118
122
|
*/
|
|
119
123
|
type FolioDocumentOperationStatus = "committed" | "previewed" | "rejected" | "queued";
|
|
120
|
-
type FolioDocumentOperationRecovery = "refreshDocument" | "narrowMatch" | "changeMode" | "changeTarget" | "removeOperation" | "inspectBatch" | "retryLater";
|
|
124
|
+
type FolioDocumentOperationRecovery = "refreshDocument" | "narrowMatch" | "changeMode" | "changeTarget" | "removeOperation" | "inspectBatch" | "resolveTrackedChange" | "retryLater";
|
|
121
125
|
type FolioDocumentOperationIssue = {
|
|
122
126
|
operationId: string;
|
|
123
127
|
operationIndex: number;
|
|
@@ -278,4 +282,4 @@ type ApplyFolioDocumentOperationsOptions = {
|
|
|
278
282
|
};
|
|
279
283
|
declare const applyFolioDocumentOperations: ({ view, snapshot, batch, story, author, createCommentId, createUndoHandle, revisionStamp, wordDiff, tableTemplates }: ApplyFolioDocumentOperationsOptions) => FolioDocumentOperationResult;
|
|
280
284
|
//#endregion
|
|
281
|
-
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, 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 };
|
|
285
|
+
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_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 };
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { applyFolioAIEditOperations, previewFolioAIEditOperations } from "./ai-edits/apply.js";
|
|
2
|
+
import { LINE_SPACING_RULE_VALUES, PARAGRAPH_ALIGNMENT_VALUES } from "./types/documentEnumValues.js";
|
|
2
3
|
import { TaggedError } from "better-result";
|
|
3
4
|
//#region src/document-operations.ts
|
|
4
5
|
const FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION = 1;
|
|
6
|
+
/** Direct paragraph-alignment values accepted by the operation contract. */
|
|
7
|
+
const FOLIO_PARAGRAPH_ALIGNMENT_VALUES = Object.freeze([...PARAGRAPH_ALIGNMENT_VALUES]);
|
|
8
|
+
/** `w:spacing/@w:lineRule` values accepted by the operation contract. */
|
|
9
|
+
const FOLIO_LINE_SPACING_RULE_VALUES = Object.freeze([...LINE_SPACING_RULE_VALUES]);
|
|
5
10
|
const FOLIO_DOCUMENT_OPERATION_TYPES = Object.freeze([
|
|
6
11
|
"replaceInBlock",
|
|
7
12
|
"replaceRange",
|
|
@@ -143,6 +148,12 @@ const readOptionalBoolean = (value, key, path) => {
|
|
|
143
148
|
if (typeof candidate === "boolean") return candidate;
|
|
144
149
|
return invalidBatch(`${path}.${key}`, "expected a boolean when provided");
|
|
145
150
|
};
|
|
151
|
+
const readClearableBoolean = (value, key, path) => {
|
|
152
|
+
const candidate = value[key];
|
|
153
|
+
if (candidate === void 0 || candidate === null) return candidate;
|
|
154
|
+
if (typeof candidate === "boolean") return candidate;
|
|
155
|
+
return invalidBatch(`${path}.${key}`, "expected a boolean or null when provided");
|
|
156
|
+
};
|
|
146
157
|
const readClearableNonEmptyString = (value, key, path) => {
|
|
147
158
|
const candidate = value[key];
|
|
148
159
|
if (candidate === void 0 || candidate === null) return candidate;
|
|
@@ -172,8 +183,8 @@ const readOptionalStringArray = (value, key, path) => {
|
|
|
172
183
|
};
|
|
173
184
|
const readNonNegativeInteger = (value, key, path) => {
|
|
174
185
|
const candidate = value[key];
|
|
175
|
-
if (typeof candidate === "number" && Number.
|
|
176
|
-
return invalidBatch(`${path}.${key}`, "expected a non-negative integer");
|
|
186
|
+
if (typeof candidate === "number" && Number.isSafeInteger(candidate) && candidate >= 0) return candidate;
|
|
187
|
+
return invalidBatch(`${path}.${key}`, "expected a non-negative safe integer");
|
|
177
188
|
};
|
|
178
189
|
/**
|
|
179
190
|
* A non-negative integer that may also be cleared. `undefined` is "say
|
|
@@ -185,6 +196,52 @@ const readClearableNonNegativeInteger = (value, key, path) => {
|
|
|
185
196
|
if (candidate === void 0) return;
|
|
186
197
|
return candidate === null ? null : readNonNegativeInteger(value, key, path);
|
|
187
198
|
};
|
|
199
|
+
const readClearableParagraphAlignment = ({ value, key, path }) => {
|
|
200
|
+
const candidate = value[key];
|
|
201
|
+
if (candidate === void 0 || candidate === null) return candidate;
|
|
202
|
+
for (const alignment of FOLIO_PARAGRAPH_ALIGNMENT_VALUES) if (candidate === alignment) return alignment;
|
|
203
|
+
return invalidBatch(`${path}.${key}`, `expected one of ${FOLIO_PARAGRAPH_ALIGNMENT_VALUES.join(", ")} or null when provided`);
|
|
204
|
+
};
|
|
205
|
+
const PARAGRAPH_SPACING_KEYS = [
|
|
206
|
+
"spaceBefore",
|
|
207
|
+
"spaceAfter",
|
|
208
|
+
"lineSpacing",
|
|
209
|
+
"lineSpacingRule",
|
|
210
|
+
"beforeAutospacing",
|
|
211
|
+
"afterAutospacing"
|
|
212
|
+
];
|
|
213
|
+
const isLineSpacingRule = (value) => FOLIO_LINE_SPACING_RULE_VALUES.some((rule) => value === rule);
|
|
214
|
+
/**
|
|
215
|
+
* Read one complete direct `w:spacing` cluster. Individual fields are
|
|
216
|
+
* optional so explicit zero and false survive; null removes the child.
|
|
217
|
+
*/
|
|
218
|
+
const readClearableParagraphSpacing = ({ value, key, path }) => {
|
|
219
|
+
const candidate = value[key];
|
|
220
|
+
if (candidate === void 0 || candidate === null) return candidate;
|
|
221
|
+
const spacingPath = `${path}.${key}`;
|
|
222
|
+
if (!isPlainObject(candidate)) return invalidBatch(spacingPath, "expected an object or null when provided");
|
|
223
|
+
assertAllowedKeys(candidate, spacingPath, PARAGRAPH_SPACING_KEYS);
|
|
224
|
+
if (Object.keys(candidate).length === 0) return invalidBatch(spacingPath, "expected at least one spacing property");
|
|
225
|
+
const spacing = {};
|
|
226
|
+
for (const unsignedKey of ["spaceBefore", "spaceAfter"]) if (candidate[unsignedKey] !== void 0) spacing[unsignedKey] = readNonNegativeInteger(candidate, unsignedKey, spacingPath);
|
|
227
|
+
const lineSpacing = candidate["lineSpacing"];
|
|
228
|
+
if (lineSpacing !== void 0) {
|
|
229
|
+
if (typeof lineSpacing !== "number" || !Number.isSafeInteger(lineSpacing)) return invalidBatch(`${spacingPath}.lineSpacing`, "expected a safe signed integer when provided");
|
|
230
|
+
spacing.lineSpacing = lineSpacing;
|
|
231
|
+
}
|
|
232
|
+
const lineSpacingRule = candidate["lineSpacingRule"];
|
|
233
|
+
if (lineSpacingRule !== void 0) {
|
|
234
|
+
if (!isLineSpacingRule(lineSpacingRule)) return invalidBatch(`${spacingPath}.lineSpacingRule`, `expected one of ${FOLIO_LINE_SPACING_RULE_VALUES.join(", ")} when provided`);
|
|
235
|
+
spacing.lineSpacingRule = lineSpacingRule;
|
|
236
|
+
}
|
|
237
|
+
for (const booleanKey of ["beforeAutospacing", "afterAutospacing"]) {
|
|
238
|
+
const booleanValue = candidate[booleanKey];
|
|
239
|
+
if (booleanValue === void 0) continue;
|
|
240
|
+
if (typeof booleanValue !== "boolean") return invalidBatch(`${spacingPath}.${booleanKey}`, "expected a boolean when provided");
|
|
241
|
+
spacing[booleanKey] = booleanValue;
|
|
242
|
+
}
|
|
243
|
+
return spacing;
|
|
244
|
+
};
|
|
188
245
|
/**
|
|
189
246
|
* A rectangular grid of cell texts. Rectangular because a table whose rows
|
|
190
247
|
* hold different cell counts is not a table any consumer can lay out, and the
|
|
@@ -209,13 +266,30 @@ const readParagraphProperties = (value, path) => {
|
|
|
209
266
|
const candidate = value["properties"];
|
|
210
267
|
const propertiesPath = `${path}.properties`;
|
|
211
268
|
if (!isPlainObject(candidate)) return invalidBatch(propertiesPath, "expected an object");
|
|
212
|
-
assertAllowedKeys(candidate, propertiesPath, [
|
|
269
|
+
assertAllowedKeys(candidate, propertiesPath, [
|
|
270
|
+
"styleId",
|
|
271
|
+
"listLevel",
|
|
272
|
+
"alignment",
|
|
273
|
+
"spacing"
|
|
274
|
+
]);
|
|
213
275
|
const styleId = candidate["styleId"] === null ? null : readOptionalString(candidate, "styleId", propertiesPath);
|
|
214
276
|
const listLevel = readClearableNonNegativeInteger(candidate, "listLevel", propertiesPath);
|
|
215
|
-
|
|
277
|
+
const alignment = readClearableParagraphAlignment({
|
|
278
|
+
value: candidate,
|
|
279
|
+
key: "alignment",
|
|
280
|
+
path: propertiesPath
|
|
281
|
+
});
|
|
282
|
+
const spacing = readClearableParagraphSpacing({
|
|
283
|
+
value: candidate,
|
|
284
|
+
key: "spacing",
|
|
285
|
+
path: propertiesPath
|
|
286
|
+
});
|
|
287
|
+
if (styleId === void 0 && listLevel === void 0 && alignment === void 0 && spacing === void 0) return invalidBatch(propertiesPath, "expected at least one property to set");
|
|
216
288
|
return {
|
|
217
289
|
...styleId !== void 0 && { styleId },
|
|
218
|
-
...listLevel !== void 0 && { listLevel }
|
|
290
|
+
...listLevel !== void 0 && { listLevel },
|
|
291
|
+
...alignment !== void 0 && { alignment },
|
|
292
|
+
...spacing !== void 0 && { spacing }
|
|
219
293
|
};
|
|
220
294
|
};
|
|
221
295
|
const readTextRange = (value, path) => {
|
|
@@ -261,10 +335,10 @@ const readInlineFormatting = (value, path) => {
|
|
|
261
335
|
"fontSizePt",
|
|
262
336
|
"color"
|
|
263
337
|
]);
|
|
264
|
-
const bold =
|
|
265
|
-
const italic =
|
|
266
|
-
const underline =
|
|
267
|
-
const strike =
|
|
338
|
+
const bold = readClearableBoolean(candidate, "bold", formattingPath);
|
|
339
|
+
const italic = readClearableBoolean(candidate, "italic", formattingPath);
|
|
340
|
+
const underline = readClearableBoolean(candidate, "underline", formattingPath);
|
|
341
|
+
const strike = readClearableBoolean(candidate, "strike", formattingPath);
|
|
268
342
|
const fontFamily = readClearableNonEmptyString(candidate, "fontFamily", formattingPath);
|
|
269
343
|
const fontSizePt = readClearableFontSize(candidate, "fontSizePt", formattingPath);
|
|
270
344
|
const color = readClearableRgbColor(candidate, "color", formattingPath);
|
|
@@ -354,6 +428,8 @@ const FOLIO_DOCUMENT_OPERATION_KEYS_BY_TYPE = Object.freeze({
|
|
|
354
428
|
...COMMON_OPERATION_KEYS,
|
|
355
429
|
"text",
|
|
356
430
|
"inheritFormatting",
|
|
431
|
+
"alignment",
|
|
432
|
+
"spacing",
|
|
357
433
|
"listLevel",
|
|
358
434
|
"moveId",
|
|
359
435
|
"pageBreakBefore",
|
|
@@ -364,6 +440,8 @@ const FOLIO_DOCUMENT_OPERATION_KEYS_BY_TYPE = Object.freeze({
|
|
|
364
440
|
...COMMON_OPERATION_KEYS,
|
|
365
441
|
"text",
|
|
366
442
|
"inheritFormatting",
|
|
443
|
+
"alignment",
|
|
444
|
+
"spacing",
|
|
367
445
|
"listLevel",
|
|
368
446
|
"moveId",
|
|
369
447
|
"pageBreakBefore",
|
|
@@ -545,6 +623,16 @@ const parseDocumentOperation = (value, index) => {
|
|
|
545
623
|
const styleId = value["styleId"] === null ? null : readOptionalString(value, "styleId", path);
|
|
546
624
|
const moveId = readOptionalString(value, "moveId", path);
|
|
547
625
|
const listLevel = readClearableNonNegativeInteger(value, "listLevel", path);
|
|
626
|
+
const alignment = readClearableParagraphAlignment({
|
|
627
|
+
value,
|
|
628
|
+
key: "alignment",
|
|
629
|
+
path
|
|
630
|
+
});
|
|
631
|
+
const spacing = readClearableParagraphSpacing({
|
|
632
|
+
value,
|
|
633
|
+
key: "spacing",
|
|
634
|
+
path
|
|
635
|
+
});
|
|
548
636
|
return {
|
|
549
637
|
...operationMeta,
|
|
550
638
|
id,
|
|
@@ -552,6 +640,8 @@ const parseDocumentOperation = (value, index) => {
|
|
|
552
640
|
blockId,
|
|
553
641
|
text: readString(value, "text", path),
|
|
554
642
|
...inheritFormatting !== void 0 && { inheritFormatting },
|
|
643
|
+
...alignment !== void 0 && { alignment },
|
|
644
|
+
...spacing !== void 0 && { spacing },
|
|
555
645
|
...listLevel !== void 0 && { listLevel },
|
|
556
646
|
...moveId !== void 0 && { moveId },
|
|
557
647
|
...pageBreakBefore !== void 0 && { pageBreakBefore },
|
|
@@ -561,7 +651,7 @@ const parseDocumentOperation = (value, index) => {
|
|
|
561
651
|
}
|
|
562
652
|
if (type === "replaceBlock") {
|
|
563
653
|
const preserveFormatting = readOptionalBoolean(value, "preserveFormatting", path);
|
|
564
|
-
const styleId = readOptionalString(value, "styleId", path);
|
|
654
|
+
const styleId = value["styleId"] === null ? null : readOptionalString(value, "styleId", path);
|
|
565
655
|
return {
|
|
566
656
|
...operationMeta,
|
|
567
657
|
id,
|
|
@@ -735,6 +825,8 @@ const recoveryByReason = {
|
|
|
735
825
|
preconditionFailed: "refreshDocument",
|
|
736
826
|
staleRange: "refreshDocument",
|
|
737
827
|
emptyOperation: "removeOperation",
|
|
828
|
+
pendingParagraphPropertyChange: "resolveTrackedChange",
|
|
829
|
+
pendingRunPropertyChange: "resolveTrackedChange",
|
|
738
830
|
noopOperation: "removeOperation",
|
|
739
831
|
documentVersionMismatch: "refreshDocument",
|
|
740
832
|
documentNotEditable: "retryLater"
|
|
@@ -751,7 +843,7 @@ const getFolioDocumentOperationIssues = (operations, skipped) => {
|
|
|
751
843
|
operationIndex,
|
|
752
844
|
path: `$.operations[${operationIndex}]`,
|
|
753
845
|
code: reason,
|
|
754
|
-
retryable: reason !== "emptyOperation" && reason !== "noopOperation",
|
|
846
|
+
retryable: reason !== "emptyOperation" && reason !== "noopOperation" && reason !== "pendingParagraphPropertyChange" && reason !== "pendingRunPropertyChange",
|
|
755
847
|
recovery: recoveryByReason[reason]
|
|
756
848
|
};
|
|
757
849
|
});
|
|
@@ -981,4 +1073,4 @@ const applyFolioDocumentOperations = ({ view, snapshot, batch, story = "main", a
|
|
|
981
1073
|
};
|
|
982
1074
|
};
|
|
983
1075
|
//#endregion
|
|
984
|
-
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, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch };
|
|
1076
|
+
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_PARAGRAPH_ALIGNMENT_VALUES, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch };
|
|
@@ -9,7 +9,7 @@ import { parseTable } from "./tableParser.js";
|
|
|
9
9
|
import { captureVerbatimXml } from "./verbatimCapture.js";
|
|
10
10
|
import { findChild, getChildElements, getLocalName, mergeXmlnsDeclarations } from "./xmlParser.js";
|
|
11
11
|
//#region src/docx/blockContentParser.ts
|
|
12
|
-
const computeListMarker = (paragraph, { numbering, listCounters, abstractCounters, restartedNumIds, previousList
|
|
12
|
+
const computeListMarker = (paragraph, { numbering, listCounters, abstractCounters, restartedNumIds, previousList }) => {
|
|
13
13
|
const listRendering = paragraph.listRendering;
|
|
14
14
|
if (!listRendering || !numbering) {
|
|
15
15
|
previousList.abstractNumId = null;
|
|
@@ -26,26 +26,17 @@ const computeListMarker = (paragraph, { numbering, listCounters, abstractCounter
|
|
|
26
26
|
}
|
|
27
27
|
const firstEncounter = !listCounters.has(numId);
|
|
28
28
|
if (firstEncounter) listCounters.set(numId, Array.from({ length: 9 }).fill(NaN));
|
|
29
|
-
|
|
29
|
+
let counters = listCounters.get(numId);
|
|
30
30
|
if (!counters) return;
|
|
31
31
|
const abstractNumId = numbering.getAbstractNumId(numId);
|
|
32
|
-
if (firstEncounter && abstractNumId !== null) {
|
|
33
|
-
let siblingNumIds = siblingNumIdsByAbstractNumId.get(abstractNumId);
|
|
34
|
-
if (!siblingNumIds) {
|
|
35
|
-
siblingNumIds = /* @__PURE__ */ new Set();
|
|
36
|
-
siblingNumIdsByAbstractNumId.set(abstractNumId, siblingNumIds);
|
|
37
|
-
}
|
|
38
|
-
siblingNumIds.add(numId);
|
|
39
|
-
}
|
|
40
32
|
const styleNumbering = paragraph.formatting?.numPrFromStyle;
|
|
41
|
-
let resumedAbstractCounters;
|
|
42
33
|
const resumesRestartedInstance = firstEncounter && listRendering.startOverride === void 0 && abstractNumId !== null && previousList.abstractNumId === abstractNumId && previousList.numId !== null && previousList.numId !== numId && restartedNumIds.has(previousList.numId);
|
|
43
34
|
const resumesStyleInstance = firstEncounter && !styleNumbering && listRendering.startOverride === void 0 && abstractNumId !== null && previousList.abstractNumId === abstractNumId && previousList.fromStyle === true;
|
|
44
35
|
if (abstractNumId !== null && (styleNumbering || resumesRestartedInstance || resumesStyleInstance)) {
|
|
45
36
|
const latestAbstractCounters = abstractCounters.get(abstractNumId);
|
|
46
37
|
if (latestAbstractCounters) {
|
|
47
|
-
|
|
48
|
-
|
|
38
|
+
counters = latestAbstractCounters;
|
|
39
|
+
listCounters.set(numId, counters);
|
|
49
40
|
}
|
|
50
41
|
}
|
|
51
42
|
if (listRendering.startOverride !== void 0 || resumesRestartedInstance || previousList.numId === numId && restartedNumIds.has(numId)) restartedNumIds.add(numId);
|
|
@@ -64,17 +55,7 @@ const computeListMarker = (paragraph, { numbering, listCounters, abstractCounter
|
|
|
64
55
|
const childCounter = counters[level + 1];
|
|
65
56
|
counters[level + 1] = (childCounter === void 0 || Number.isNaN(childCounter) ? 0 : childCounter) + childAdvances;
|
|
66
57
|
}
|
|
67
|
-
if (abstractNumId !== null)
|
|
68
|
-
if (resumedAbstractCounters) {
|
|
69
|
-
const siblingNumIds = siblingNumIdsByAbstractNumId.get(abstractNumId);
|
|
70
|
-
for (const otherNumId of siblingNumIds ?? []) {
|
|
71
|
-
const otherCounters = listCounters.get(otherNumId);
|
|
72
|
-
if (otherNumId === numId || !otherCounters || !otherCounters.every((value, index) => Object.is(value, resumedAbstractCounters[index]))) continue;
|
|
73
|
-
for (let i = 0; i < otherCounters.length; i += 1) otherCounters[i] = counters[i] ?? NaN;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
abstractCounters.set(abstractNumId, [...counters]);
|
|
77
|
-
}
|
|
58
|
+
if (abstractNumId !== null) abstractCounters.set(abstractNumId, counters);
|
|
78
59
|
previousList.abstractNumId = abstractNumId;
|
|
79
60
|
previousList.fromStyle = Boolean(styleNumbering);
|
|
80
61
|
previousList.numId = numId;
|
|
@@ -108,7 +89,6 @@ const parseBlockContent = (parent, styles, theme, numbering, rels, media, option
|
|
|
108
89
|
fromStyle: false,
|
|
109
90
|
numId: null
|
|
110
91
|
},
|
|
111
|
-
siblingNumIdsByAbstractNumId: /* @__PURE__ */ new Map(),
|
|
112
92
|
options: {
|
|
113
93
|
...options,
|
|
114
94
|
rootXmlns: mergeXmlnsDeclarations(options?.rootXmlns ?? {}, parent)
|
|
@@ -129,8 +109,7 @@ const parseBlockContentWithState = (parent, styles, theme, numbering, rels, medi
|
|
|
129
109
|
listCounters: state.listCounters,
|
|
130
110
|
abstractCounters: state.abstractCounters,
|
|
131
111
|
restartedNumIds: state.restartedNumIds,
|
|
132
|
-
previousList: state.previousList
|
|
133
|
-
siblingNumIdsByAbstractNumId: state.siblingNumIdsByAbstractNumId
|
|
112
|
+
previousList: state.previousList
|
|
134
113
|
});
|
|
135
114
|
content.push(paragraph);
|
|
136
115
|
continue;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { parseParagraph } from "./paragraphParser.js";
|
|
2
|
+
import { cloneParagraphWithPropertySource } from "./paragraphPropertySource.js";
|
|
2
3
|
import { parseRunProperties } from "./runParser.js";
|
|
3
4
|
import { findChild, getAttribute, getChildElements, getLocalName, parseXml } from "./xmlParser.js";
|
|
4
5
|
//#region src/docx/commentParser.ts
|
|
@@ -14,10 +15,7 @@ const normalizeFirstCommentParagraph = (paragraphElement, paragraph, theme) => {
|
|
|
14
15
|
const annotationReferenceFormatting = normalizeAnnotationReferenceFormatting(runProperties ? parseRunProperties(runProperties, theme) : void 0);
|
|
15
16
|
const firstParsedContent = paragraph.content.at(0);
|
|
16
17
|
return {
|
|
17
|
-
paragraph: firstParsedContent?.type === "run" && firstParsedContent.content.length === 0 ? {
|
|
18
|
-
...paragraph,
|
|
19
|
-
content: paragraph.content.slice(1)
|
|
20
|
-
} : paragraph,
|
|
18
|
+
paragraph: firstParsedContent?.type === "run" && firstParsedContent.content.length === 0 ? cloneParagraphWithPropertySource(paragraph, { content: paragraph.content.slice(1) }) : paragraph,
|
|
21
19
|
...annotationReferenceFormatting !== void 0 ? { annotationReferenceFormatting } : {}
|
|
22
20
|
};
|
|
23
21
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { cloneParagraphWithPropertySource } from "./paragraphPropertySource.js";
|
|
1
2
|
//#region src/docx/commentRangeIntegrity.ts
|
|
2
3
|
const withoutOrphanCommentRanges = (doc) => {
|
|
3
4
|
const validCommentIds = new Set((doc.package.document.comments ?? []).map((comment) => comment.id));
|
|
@@ -176,10 +177,7 @@ const withoutOrphanParagraphMarkers = (paragraph, validCommentIds) => {
|
|
|
176
177
|
content.push(item);
|
|
177
178
|
}
|
|
178
179
|
if (!changed) return paragraph;
|
|
179
|
-
return {
|
|
180
|
-
...paragraph,
|
|
181
|
-
content
|
|
182
|
-
};
|
|
180
|
+
return cloneParagraphWithPropertySource(paragraph, { content });
|
|
183
181
|
};
|
|
184
182
|
const isCommentMarker = (content) => content.type === "commentRangeStart" || content.type === "commentRangeEnd" || content.type === "commentReference";
|
|
185
183
|
//#endregion
|