@stll/folio-core 0.12.0 → 0.14.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.d.ts +2 -1
- package/dist/ai-edits/apply.js +118 -40
- package/dist/ai-edits/blockRange.js +1 -1
- package/dist/ai-edits/clean-text.js +2 -1
- package/dist/ai-edits/headless.js +3 -3
- package/dist/ai-edits/snapshot.js +21 -3
- package/dist/ai-edits/table-cell-mutations.js +2 -1
- package/dist/ai-edits/table-row-column-mutations.d.ts +9 -1
- package/dist/ai-edits/table-row-column-mutations.js +1 -1
- package/dist/ai-edits/types.d.ts +28 -1
- package/dist/ai-edits/word-diff.js +21 -0
- package/dist/compat/eigenpal.d.ts +3 -3
- package/dist/compat/eigenpal.js +3 -3
- package/dist/controller/headerFooterEditorManager.js +1 -1
- package/dist/controller/hiddenEditorManager.js +12 -1
- package/dist/controller/layoutPipeline.js +1 -1
- package/dist/controller/noteEditorManager.js +1 -1
- package/dist/document-operations.d.ts +13 -13
- package/dist/document-operations.js +31 -21
- package/dist/docx/blockContentParser.js +19 -5
- package/dist/docx/commentRangeIntegrity.d.ts +6 -0
- package/dist/docx/commentRangeIntegrity.js +186 -0
- package/dist/docx/conformance.js +57 -3
- package/dist/docx/encryption/agileDecryption.js +12 -2
- package/dist/docx/encryption/compoundFile.js +6 -1
- package/dist/docx/encryption/encryptionInfo.d.ts +9 -1
- package/dist/docx/encryption/encryptionInfo.js +18 -2
- package/dist/docx/encryption/openEncryptedDocx.js +1 -1
- package/dist/docx/ensureParaIds.js +7 -6
- package/dist/docx/groupDrawingParser.js +10 -5
- package/dist/docx/hyperlinkParser.js +1 -1
- package/dist/docx/imageParser.js +10 -6
- package/dist/docx/metadataPrivacy.js +17 -3
- package/dist/docx/paragraphParser.js +7 -3
- package/dist/docx/rezip.js +19 -8
- package/dist/docx/runParser.js +13 -4
- package/dist/docx/sectionParser.js +17 -4
- package/dist/docx/selectiveSave.js +4 -0
- package/dist/docx/selectiveXmlPatch.d.ts +22 -1
- package/dist/docx/selectiveXmlPatch.js +61 -1
- package/dist/docx/serializer/blockSdtSerializer.js +3 -2
- package/dist/docx/serializer/commentSerializer.js +4 -4
- package/dist/docx/serializer/paragraphSerializer.js +16 -14
- package/dist/docx/serializer/runSerializer.js +21 -19
- package/dist/docx/serializer/sectionPropertiesSerializer.js +2 -1
- package/dist/docx/serializer/tableSerializer.js +9 -7
- package/dist/docx/serializer/xmlUtils.d.ts +13 -1
- package/dist/docx/serializer/xmlUtils.js +27 -1
- package/dist/docx/server/docxToMarkdown.d.ts +15 -0
- package/dist/docx/server/docxToMarkdown.js +17 -0
- package/dist/docx/server/extractDocxText.js +55 -8
- package/dist/docx/settingsParser.js +15 -2
- package/dist/docx/tableParser.d.ts +8 -1
- package/dist/docx/tableParser.js +29 -8
- package/dist/docx/unzip.js +1 -0
- package/dist/docx/vmlImageParser.js +11 -3
- package/dist/docx/xmlParser.js +11 -1
- package/dist/fonts/embeddedFonts.d.ts +33 -5
- package/dist/fonts/embeddedFonts.js +37 -8
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/layout-bridge/convert/toFlowBlocks.js +15 -0
- package/dist/layout-engine/index.js +19 -12
- package/dist/layout-engine/measure/cache.js +2 -0
- package/dist/layout-engine/measure/effectiveLineBreakPolicy.js +8 -2
- package/dist/layout-engine/measure/floatingTablePosition.d.ts +9 -0
- package/dist/layout-engine/measure/floatingTablePosition.js +17 -0
- package/dist/layout-engine/measure/index.d.ts +2 -1
- package/dist/layout-engine/measure/index.js +2 -1
- package/dist/layout-engine/measure/lineBreakProvider.d.ts +2 -2
- package/dist/layout-engine/measure/lineBreakProvider.js +3 -3
- package/dist/layout-engine/measure/measureBlocks.js +11 -8
- package/dist/layout-engine/measure/measureHelpers.d.ts +10 -1
- package/dist/layout-engine/measure/measureHelpers.js +12 -1
- package/dist/layout-engine/measure/measureParagraph.js +16 -0
- package/dist/layout-engine/types.d.ts +22 -2
- package/dist/layout-painter/renderImage.d.ts +12 -1
- package/dist/layout-painter/renderImage.js +21 -4
- package/dist/layout-painter/renderPage.js +5 -8
- package/dist/layout-painter/renderParagraph.js +33 -9
- package/dist/layout-painter/renderTable.js +2 -1
- package/dist/layout-painter/renderWatermark.d.ts +1 -1
- package/dist/layout-painter/renderWatermark.js +2 -1
- package/dist/markdown/fromMarkdown.js +1 -1
- package/dist/prosemirror/attrs/index.d.ts +1 -1
- package/dist/prosemirror/attrs/index.js +21 -0
- package/dist/prosemirror/commands/comments.d.ts +76 -1
- package/dist/prosemirror/commands/comments.js +401 -28
- package/dist/prosemirror/commands/hyperlink.js +15 -1
- package/dist/prosemirror/commands/image.js +7 -1
- package/dist/prosemirror/commands/index.d.ts +2 -2
- package/dist/prosemirror/commands/index.js +2 -2
- package/dist/prosemirror/commands/tableCellMergeResolution.js +1 -1
- package/dist/prosemirror/commentIdAllocator.js +13 -3
- package/dist/prosemirror/conversion/fromProseDoc.js +122 -5
- package/dist/prosemirror/conversion/index.js +1 -1
- package/dist/prosemirror/conversion/toProseDoc.js +20 -8
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +2 -1
- package/dist/prosemirror/extensions/features/ImagePasteExtension.js +10 -2
- package/dist/prosemirror/extensions/features/pasteCleanup.js +15 -2
- package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +30 -4
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +49 -13
- package/dist/prosemirror/extensions/nodes/TableExtension.d.ts +1 -1
- package/dist/prosemirror/extensions/nodes/TableExtension.js +5 -3
- package/dist/prosemirror/index.d.ts +1 -1
- package/dist/prosemirror/index.js +1 -1
- package/dist/prosemirror/plugins/contentControlWidgets.d.ts +2 -2
- package/dist/prosemirror/plugins/contentControlWidgets.js +4 -4
- package/dist/prosemirror/plugins/revisionIds.d.ts +23 -0
- package/dist/prosemirror/plugins/revisionIds.js +57 -0
- package/dist/prosemirror/plugins/suggestionMode.js +4 -3
- package/dist/prosemirror/runFormattingMarkNames.d.ts +14 -0
- package/dist/prosemirror/runFormattingMarkNames.js +40 -0
- package/dist/prosemirror/schema/index.d.ts +1 -1
- package/dist/prosemirror/schema/marks.d.ts +27 -4
- package/dist/prosemirror/schema/marks.js +15 -0
- package/dist/prosemirror/schema/nodes.d.ts +50 -2
- package/dist/prosemirror/utils/tabCalculator.js +3 -3
- package/dist/render-dom/RemoteSelectionOverlay.js +2 -2
- package/dist/server.d.ts +3 -2
- package/dist/server.js +4 -3
- package/dist/utils/clipboard.d.ts +10 -1
- package/dist/utils/clipboard.js +33 -6
- package/dist/utils/colorResolver.d.ts +8 -1
- package/dist/utils/colorResolver.js +35 -5
- package/dist/utils/fontResolver.d.ts +2 -1
- package/dist/utils/fontResolver.js +9 -3
- package/dist/utils/hexId.d.ts +11 -1
- package/dist/utils/hexId.js +11 -1
- package/dist/utils/sanitizeImageSrc.d.ts +21 -0
- package/dist/utils/sanitizeImageSrc.js +30 -0
- package/dist/utils/stripXmlDeclarations.d.ts +11 -0
- package/dist/utils/stripXmlDeclarations.js +35 -0
- package/dist/version-comparison.d.ts +22 -2
- package/dist/version-comparison.js +41 -12
- package/dist/watermark/index.d.ts +11 -1
- package/dist/watermark/index.js +22 -1
- package/package.json +3 -2
|
@@ -87,6 +87,14 @@ type RunFormatting = {
|
|
|
87
87
|
changeAuthor?: string; /** Date of the tracked change */
|
|
88
88
|
changeDate?: string; /** Revision ID of the tracked change (for sidebar matching) */
|
|
89
89
|
changeRevisionId?: number;
|
|
90
|
+
/**
|
|
91
|
+
* Whether this tracked insertion/deletion is an AI-proposed *suggestion*
|
|
92
|
+
* rather than a user change. Suggestions render with the same grammar but a
|
|
93
|
+
* dotted stroke and a dedicated hue; they are stripped from serialized DOCX
|
|
94
|
+
* until accepted.
|
|
95
|
+
*/
|
|
96
|
+
isSuggestion?: boolean; /** Groups a suggestion's runs for accept/reject and scroll-to. */
|
|
97
|
+
suggestionId?: string;
|
|
90
98
|
};
|
|
91
99
|
/**
|
|
92
100
|
* Hyperlink information for a run.
|
|
@@ -179,7 +187,10 @@ type ImageRun = {
|
|
|
179
187
|
cropTop?: number;
|
|
180
188
|
cropRight?: number;
|
|
181
189
|
cropBottom?: number;
|
|
182
|
-
cropLeft?: number; /**
|
|
190
|
+
cropLeft?: number; /** CSS border width in pixels. eigenpal #1096. */
|
|
191
|
+
borderWidth?: number; /** CSS border color. eigenpal #1096. */
|
|
192
|
+
borderColor?: string; /** CSS border style. eigenpal #1096. */
|
|
193
|
+
borderStyle?: string; /** Whether this picture is itself a tracked insertion (`<w:ins>`). eigenpal #641. */
|
|
183
194
|
isInsertion?: boolean; /** Whether this picture is itself a tracked deletion (`<w:del>`). eigenpal #641. */
|
|
184
195
|
isDeletion?: boolean; /** Author of the tracked change wrapping the picture. eigenpal #641. */
|
|
185
196
|
changeAuthor?: string; /** Date of the tracked change wrapping the picture. eigenpal #641. */
|
|
@@ -377,6 +388,12 @@ type ParagraphAttrs = {
|
|
|
377
388
|
listMarkerHidden?: boolean;
|
|
378
389
|
listMarkerFontFamily?: string;
|
|
379
390
|
listMarkerFontSize?: number;
|
|
391
|
+
/**
|
|
392
|
+
* Effective paragraph-mark size used only to measure a visible list
|
|
393
|
+
* paragraph's final line. Word lets the inherited complex-script size raise
|
|
394
|
+
* that line box without enlarging the marker or Western text glyphs.
|
|
395
|
+
*/
|
|
396
|
+
listParagraphMarkFontSize?: number;
|
|
380
397
|
listMarkerBold?: boolean; /** Horizontal alignment of the marker around the paragraph's list anchor. */
|
|
381
398
|
listMarkerAlignment?: "left" | "center" | "right";
|
|
382
399
|
/**
|
|
@@ -566,7 +583,10 @@ type ImageBlock = {
|
|
|
566
583
|
cropTop?: number;
|
|
567
584
|
cropRight?: number;
|
|
568
585
|
cropBottom?: number;
|
|
569
|
-
cropLeft?: number;
|
|
586
|
+
cropLeft?: number; /** CSS border width in pixels. eigenpal #1096. */
|
|
587
|
+
borderWidth?: number; /** CSS border color. eigenpal #1096. */
|
|
588
|
+
borderColor?: string; /** CSS border style. eigenpal #1096. */
|
|
589
|
+
borderStyle?: string;
|
|
570
590
|
pmStart?: number;
|
|
571
591
|
pmEnd?: number;
|
|
572
592
|
};
|
|
@@ -21,6 +21,17 @@ type ImageVisualAttrs = {
|
|
|
21
21
|
cropBottom?: number;
|
|
22
22
|
cropLeft?: number;
|
|
23
23
|
};
|
|
24
|
+
type ImageBorderAttrs = {
|
|
25
|
+
borderWidth?: number;
|
|
26
|
+
borderColor?: string;
|
|
27
|
+
borderStyle?: string;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Paint image borders carried through the layout model. Folio's PM schema
|
|
31
|
+
* uses `borderStyle` (not upstream's `borderKind`); the painter mirrors the
|
|
32
|
+
* editor DOM serialization while keeping the authored image box size stable.
|
|
33
|
+
*/
|
|
34
|
+
declare function applyImageBorder(element: HTMLElement, border: ImageBorderAttrs): void;
|
|
24
35
|
/**
|
|
25
36
|
* True when any visual attribute is set. Cheap call-site guard so the no-op
|
|
26
37
|
* common case skips the helper call.
|
|
@@ -86,4 +97,4 @@ type RenderImageFragmentOptions = {
|
|
|
86
97
|
*/
|
|
87
98
|
declare function renderImageFragment(fragment: ImageFragment, block: ImageBlock, _measure: ImageMeasure, _context: RenderContext, options?: RenderImageFragmentOptions): HTMLElement;
|
|
88
99
|
//#endregion
|
|
89
|
-
export { IMAGE_CLASS_NAMES, ImageVisualAttrs, RenderImageFragmentOptions, applyImageVisualAttrs, hasImageCrop, hasImageVisualAttrs, renderImageFragment, wrapImageWithCrop };
|
|
100
|
+
export { IMAGE_CLASS_NAMES, ImageBorderAttrs, ImageVisualAttrs, RenderImageFragmentOptions, applyImageBorder, applyImageVisualAttrs, hasImageCrop, hasImageVisualAttrs, renderImageFragment, wrapImageWithCrop };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { sanitizeExternalUrl } from "../utils/urlSecurity.js";
|
|
2
|
+
import { applySanitizedImageSrc } from "../utils/sanitizeImageSrc.js";
|
|
1
3
|
//#region src/layout-painter/renderImage.ts
|
|
2
4
|
/**
|
|
3
5
|
* CSS class names for image elements
|
|
@@ -7,6 +9,18 @@ const IMAGE_CLASS_NAMES = {
|
|
|
7
9
|
imageAnchored: "layout-image-anchored"
|
|
8
10
|
};
|
|
9
11
|
/**
|
|
12
|
+
* Paint image borders carried through the layout model. Folio's PM schema
|
|
13
|
+
* uses `borderStyle` (not upstream's `borderKind`); the painter mirrors the
|
|
14
|
+
* editor DOM serialization while keeping the authored image box size stable.
|
|
15
|
+
*/
|
|
16
|
+
function applyImageBorder(element, border) {
|
|
17
|
+
if (border.borderWidth == null || border.borderWidth <= 0) return;
|
|
18
|
+
const borderStyle = border.borderStyle || "solid";
|
|
19
|
+
const borderColor = border.borderColor || "#000000";
|
|
20
|
+
element.style.border = `${border.borderWidth}px ${borderStyle} ${borderColor}`;
|
|
21
|
+
element.style.boxSizing = "border-box";
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
10
24
|
* True when any visual attribute is set. Cheap call-site guard so the no-op
|
|
11
25
|
* common case skips the helper call.
|
|
12
26
|
*
|
|
@@ -118,7 +132,7 @@ function renderImageFragment(fragment, block, _measure, _context, options = {})
|
|
|
118
132
|
if (fragment.pmStart !== void 0) containerEl.dataset["pmStart"] = String(fragment.pmStart);
|
|
119
133
|
if (fragment.pmEnd !== void 0) containerEl.dataset["pmEnd"] = String(fragment.pmEnd);
|
|
120
134
|
const imgEl = doc.createElement("img");
|
|
121
|
-
imgEl
|
|
135
|
+
applySanitizedImageSrc(imgEl, block.src);
|
|
122
136
|
imgEl.alt = block.alt ?? "";
|
|
123
137
|
imgEl.style.width = "100%";
|
|
124
138
|
imgEl.style.height = "100%";
|
|
@@ -127,9 +141,10 @@ function renderImageFragment(fragment, block, _measure, _context, options = {})
|
|
|
127
141
|
if (block.transform) imgEl.style.transform = block.transform;
|
|
128
142
|
if (hasImageVisualAttrs(block)) applyImageVisualAttrs(imgEl, block);
|
|
129
143
|
imgEl.draggable = false;
|
|
130
|
-
|
|
144
|
+
const hlinkHref = sanitizeExternalUrl(block.hlinkHref);
|
|
145
|
+
if (hlinkHref) {
|
|
131
146
|
const linkEl = doc.createElement("a");
|
|
132
|
-
linkEl.href =
|
|
147
|
+
linkEl.href = hlinkHref;
|
|
133
148
|
linkEl.target = "_blank";
|
|
134
149
|
linkEl.rel = "noopener noreferrer";
|
|
135
150
|
linkEl.style.display = "block";
|
|
@@ -138,7 +153,9 @@ function renderImageFragment(fragment, block, _measure, _context, options = {})
|
|
|
138
153
|
linkEl.append(imgEl);
|
|
139
154
|
containerEl.append(linkEl);
|
|
140
155
|
} else containerEl.append(imgEl);
|
|
156
|
+
if (hasImageCrop(block)) applyImageBorder(containerEl, block);
|
|
157
|
+
else applyImageBorder(imgEl, block);
|
|
141
158
|
return containerEl;
|
|
142
159
|
}
|
|
143
160
|
//#endregion
|
|
144
|
-
export { IMAGE_CLASS_NAMES, applyImageVisualAttrs, hasImageCrop, hasImageVisualAttrs, renderImageFragment, wrapImageWithCrop };
|
|
161
|
+
export { IMAGE_CLASS_NAMES, applyImageBorder, applyImageVisualAttrs, hasImageCrop, hasImageVisualAttrs, renderImageFragment, wrapImageWithCrop };
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { eighthsToPixels, pointsToPixels } from "../utils/units.js";
|
|
2
2
|
import { resolveFontFamily } from "../utils/fontResolver.js";
|
|
3
3
|
import { borderToStyle } from "../utils/formatToStyle.js";
|
|
4
|
+
import { applySanitizedImageSrc } from "../utils/sanitizeImageSrc.js";
|
|
4
5
|
import { floatingTextBoxReservesBand, floatingTextBoxWrapsText, isFloatingImageRun, isFloatingTextBoxBlock, isTextWrappingFloatingImageRun } from "../layout-engine/types.js";
|
|
5
6
|
import { rectsToFloatingZones } from "../layout-engine/measure/floatingZones.js";
|
|
6
7
|
import { measureParagraph } from "../layout-engine/measure/measureParagraph.js";
|
|
8
|
+
import { resolveFloatingTableX } from "../layout-engine/measure/floatingTablePosition.js";
|
|
7
9
|
import { emuToPixels } from "./renderUtils.js";
|
|
8
10
|
import { resolveAnchoredImagePosition as resolveAnchoredImagePosition$1 } from "./anchoredImagePosition.js";
|
|
9
11
|
import { renderFragment } from "./renderFragment.js";
|
|
@@ -239,12 +241,7 @@ function resolveHeaderFooterFloatingTablePosition(floating, measure, layout, sou
|
|
|
239
241
|
const horzFrameOffset = horzAnchor === "page" ? -layout.flowLeft : 0;
|
|
240
242
|
const vertFrameHeight = vertAnchor === "page" ? layout.pageHeight : layout.pageHeight - layout.margins.top - layout.margins.bottom;
|
|
241
243
|
const vertFrameOffset = vertAnchor === "page" ? -layout.flowTop : layout.margins.top - layout.flowTop;
|
|
242
|
-
|
|
243
|
-
const xSpec = floating.tblpXSpec;
|
|
244
|
-
if (xSpec === "left" || xSpec === "inside") left = horzFrameOffset;
|
|
245
|
-
else if (xSpec === "right" || xSpec === "outside") left = horzFrameOffset + horzFrameWidth - measure.totalWidth;
|
|
246
|
-
else if (xSpec === "center") left = horzFrameOffset + (horzFrameWidth - measure.totalWidth) / 2;
|
|
247
|
-
else if (floating.tblpX !== void 0) left = horzFrameOffset + floating.tblpX;
|
|
244
|
+
const left = horzFrameOffset + resolveFloatingTableX(floating, void 0, measure.totalWidth, horzFrameWidth);
|
|
248
245
|
let top = sourceY;
|
|
249
246
|
if (floating.tblpYSpec === "top") top = vertFrameOffset;
|
|
250
247
|
else if (floating.tblpYSpec === "bottom") top = vertFrameOffset + vertFrameHeight - measure.totalHeight;
|
|
@@ -380,7 +377,7 @@ function renderFloatingImagesLayer(floatingImages, doc, layerMode = "front") {
|
|
|
380
377
|
if (floatImg.pmStart !== void 0) container.dataset["pmStart"] = String(floatImg.pmStart);
|
|
381
378
|
if (floatImg.pmEnd !== void 0) container.dataset["pmEnd"] = String(floatImg.pmEnd);
|
|
382
379
|
const img = doc.createElement("img");
|
|
383
|
-
img
|
|
380
|
+
applySanitizedImageSrc(img, floatImg.src);
|
|
384
381
|
img.style.width = `${floatImg.width}px`;
|
|
385
382
|
img.style.height = `${floatImg.height}px`;
|
|
386
383
|
img.style.display = "block";
|
|
@@ -509,7 +506,7 @@ function renderHeaderFooterContent(content, context, options, layout) {
|
|
|
509
506
|
}
|
|
510
507
|
for (const floatImg of floatingImages) {
|
|
511
508
|
const img = doc.createElement("img");
|
|
512
|
-
img
|
|
509
|
+
applySanitizedImageSrc(img, floatImg.src);
|
|
513
510
|
img.width = floatImg.width;
|
|
514
511
|
img.height = floatImg.height;
|
|
515
512
|
if (floatImg.alt) img.alt = floatImg.alt;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { parseXmlDocument } from "../docx/xmlParser.js";
|
|
2
2
|
import { resolveFontFamily } from "../utils/fontResolver.js";
|
|
3
3
|
import { detectBaseDirection } from "../utils/baseDirection.js";
|
|
4
|
+
import { applySanitizedImageSrc } from "../utils/sanitizeImageSrc.js";
|
|
4
5
|
import { AUTHOR_COLORS, getAuthorColorIdx } from "../utils/authorColors.js";
|
|
5
6
|
import { FONT_KERNING_MODE, countCompressibleSpaces, getFontKerningMode, getRunFontKerningMode, toPaintedText } from "../layout-engine/measure/textMeasurementPolicy.js";
|
|
6
7
|
import "../utils/fontWeights.js";
|
|
@@ -12,7 +13,7 @@ import { isFloatingImageRun } from "../layout-engine/types.js";
|
|
|
12
13
|
import { getListMarkerInlineWidth, getListMarkerVisualOffset } from "../layout-engine/measure/listMarkerWidth.js";
|
|
13
14
|
import { resolveImageLineAlign } from "./renderUtils.js";
|
|
14
15
|
import { applySdtDataAttrs } from "./sdtBoundary.js";
|
|
15
|
-
import { applyImageVisualAttrs, hasImageVisualAttrs, wrapImageWithCrop } from "./renderImage.js";
|
|
16
|
+
import { applyImageBorder, applyImageVisualAttrs, hasImageCrop, hasImageVisualAttrs, wrapImageWithCrop } from "./renderImage.js";
|
|
16
17
|
import { ommlToMathml } from "../docx/mathToMathml.js";
|
|
17
18
|
import { evaluateFieldInstruction } from "../fields/evaluateField.js";
|
|
18
19
|
import { borderStrokeToCss, resolveParagraphBorderHorizontalOutsets } from "./borderStroke.js";
|
|
@@ -75,6 +76,9 @@ function isMathRun(run) {
|
|
|
75
76
|
const AUTOMATIC_TEXT_COLOR_VALUES = /* @__PURE__ */ new Set(["auto", "windowtext"]);
|
|
76
77
|
const DEFAULT_BLACK_TEXT_COLOR_VALUES = /* @__PURE__ */ new Set(["000000", "000"]);
|
|
77
78
|
const DOCX_SUPERSCRIPT_SCALE = .75;
|
|
79
|
+
const SUGGESTION_COLOR_CSS = "var(--suggestion-color, #6d3bd6)";
|
|
80
|
+
const SUGGESTION_TINT_CSS = "var(--suggestion-bg, color-mix(in oklch, #6d3bd6 12%, transparent))";
|
|
81
|
+
const SUGGESTION_TINT_LAYER_CSS = `linear-gradient(${SUGGESTION_TINT_CSS}, ${SUGGESTION_TINT_CSS})`;
|
|
78
82
|
function normalizeTextColorValue(color) {
|
|
79
83
|
return color.trim().toLowerCase().replace(/^#/u, "");
|
|
80
84
|
}
|
|
@@ -192,13 +196,21 @@ function applyRunStyles(element, run) {
|
|
|
192
196
|
if (run.isInsertion) {
|
|
193
197
|
const authorIdx = getAuthorColorIdx(run.changeAuthor ?? "");
|
|
194
198
|
const authorColor = AUTHOR_COLORS[authorIdx];
|
|
195
|
-
|
|
199
|
+
const strokeColor = run.isSuggestion ? SUGGESTION_COLOR_CSS : authorColor;
|
|
200
|
+
element.style.color = strokeColor;
|
|
196
201
|
if (!decorations.includes("underline")) decorations.push("underline");
|
|
197
|
-
element.style.textDecorationColor =
|
|
202
|
+
element.style.textDecorationColor = strokeColor;
|
|
198
203
|
element.classList.add("docx-insertion");
|
|
199
204
|
element.dataset["tcAuthorIdx"] = String(authorIdx);
|
|
205
|
+
if (run.isSuggestion) {
|
|
206
|
+
element.classList.add("docx-insertion--suggested");
|
|
207
|
+
element.style.textDecorationStyle = "dotted";
|
|
208
|
+
element.style.backgroundImage = SUGGESTION_TINT_LAYER_CSS;
|
|
209
|
+
element.dataset["provenance"] = "suggested";
|
|
210
|
+
if (run.suggestionId) element.dataset["suggestionId"] = run.suggestionId;
|
|
211
|
+
}
|
|
200
212
|
const insertionParts = [run.changeAuthor, run.changeDate ? new Date(run.changeDate).toLocaleDateString() : ""].filter(Boolean);
|
|
201
|
-
if (insertionParts.length > 0) element.title =
|
|
213
|
+
if (insertionParts.length > 0) element.title = `${run.isSuggestion ? "Suggested" : "Inserted"}: ${insertionParts.join(", ")}`;
|
|
202
214
|
if (run.changeAuthor) element.dataset["changeAuthor"] = run.changeAuthor;
|
|
203
215
|
if (run.changeDate) element.dataset["changeDate"] = run.changeDate;
|
|
204
216
|
if (run.changeRevisionId !== void 0) element.dataset["revisionId"] = String(run.changeRevisionId);
|
|
@@ -206,13 +218,21 @@ function applyRunStyles(element, run) {
|
|
|
206
218
|
if (run.isDeletion) {
|
|
207
219
|
const authorIdx = getAuthorColorIdx(run.changeAuthor ?? "");
|
|
208
220
|
const authorColor = AUTHOR_COLORS[authorIdx];
|
|
209
|
-
|
|
221
|
+
const strokeColor = run.isSuggestion ? SUGGESTION_COLOR_CSS : authorColor;
|
|
222
|
+
element.style.color = strokeColor;
|
|
210
223
|
if (!decorations.includes("line-through")) decorations.push("line-through");
|
|
211
|
-
element.style.textDecorationColor =
|
|
224
|
+
element.style.textDecorationColor = strokeColor;
|
|
212
225
|
element.classList.add("docx-deletion");
|
|
213
226
|
element.dataset["tcAuthorIdx"] = String(authorIdx);
|
|
227
|
+
if (run.isSuggestion) {
|
|
228
|
+
element.classList.add("docx-deletion--suggested");
|
|
229
|
+
element.style.textDecorationStyle = "dotted";
|
|
230
|
+
element.style.backgroundImage = SUGGESTION_TINT_LAYER_CSS;
|
|
231
|
+
element.dataset["provenance"] = "suggested";
|
|
232
|
+
if (run.suggestionId) element.dataset["suggestionId"] = run.suggestionId;
|
|
233
|
+
}
|
|
214
234
|
const deletionParts = [run.changeAuthor, run.changeDate ? new Date(run.changeDate).toLocaleDateString() : ""].filter(Boolean);
|
|
215
|
-
if (deletionParts.length > 0) element.title =
|
|
235
|
+
if (deletionParts.length > 0) element.title = `${run.isSuggestion ? "Suggested deletion" : "Deleted"}: ${deletionParts.join(", ")}`;
|
|
216
236
|
if (run.changeAuthor) element.dataset["changeAuthor"] = run.changeAuthor;
|
|
217
237
|
if (run.changeDate) element.dataset["changeDate"] = run.changeDate;
|
|
218
238
|
if (run.changeRevisionId !== void 0) element.dataset["revisionId"] = String(run.changeRevisionId);
|
|
@@ -368,7 +388,7 @@ function getLeaderChar(leader) {
|
|
|
368
388
|
function renderInlineImageRun(run, doc) {
|
|
369
389
|
const img = doc.createElement("img");
|
|
370
390
|
img.className = `${PARAGRAPH_CLASS_NAMES.run} ${PARAGRAPH_CLASS_NAMES.image}`;
|
|
371
|
-
img
|
|
391
|
+
applySanitizedImageSrc(img, run.src);
|
|
372
392
|
img.width = run.width;
|
|
373
393
|
img.height = run.height;
|
|
374
394
|
img.style.width = `${run.width}px`;
|
|
@@ -378,6 +398,7 @@ function renderInlineImageRun(run, doc) {
|
|
|
378
398
|
img.style.transform = run.transform;
|
|
379
399
|
img.style.transformOrigin = "center center";
|
|
380
400
|
}
|
|
401
|
+
if (!hasImageCrop(run)) applyImageBorder(img, run);
|
|
381
402
|
const rotation = parseRotationDegrees(run.transform);
|
|
382
403
|
if (rotation !== 0) {
|
|
383
404
|
const bbox = rotatedBoundingBox(run.width, run.height, rotation);
|
|
@@ -407,6 +428,7 @@ function renderInlineImageRun(run, doc) {
|
|
|
407
428
|
wrapper.style.verticalAlign = "middle";
|
|
408
429
|
if (run.distTop) wrapper.style.marginTop = `${run.distTop}px`;
|
|
409
430
|
if (run.distBottom) wrapper.style.marginBottom = `${run.distBottom}px`;
|
|
431
|
+
if (hasImageCrop(run)) applyImageBorder(wrapper, run);
|
|
410
432
|
applyPmPositions(wrapper, run.pmStart, run.pmEnd);
|
|
411
433
|
return wrapper;
|
|
412
434
|
}
|
|
@@ -434,7 +456,7 @@ function renderBlockImage(run, doc) {
|
|
|
434
456
|
container.style.marginTop = `${run.distTop ?? 6}px`;
|
|
435
457
|
container.style.marginBottom = `${run.distBottom ?? 6}px`;
|
|
436
458
|
const img = doc.createElement("img");
|
|
437
|
-
img
|
|
459
|
+
applySanitizedImageSrc(img, run.src);
|
|
438
460
|
img.width = run.width;
|
|
439
461
|
img.height = run.height;
|
|
440
462
|
if (run.alt) img.alt = run.alt;
|
|
@@ -442,6 +464,7 @@ function renderBlockImage(run, doc) {
|
|
|
442
464
|
img.style.transform = run.transform;
|
|
443
465
|
img.style.transformOrigin = "center center";
|
|
444
466
|
}
|
|
467
|
+
if (!hasImageCrop(run)) applyImageBorder(img, run);
|
|
445
468
|
const rotation = parseRotationDegrees(run.transform);
|
|
446
469
|
if (rotation !== 0) {
|
|
447
470
|
const bbox = rotatedBoundingBox(run.width, run.height, rotation);
|
|
@@ -463,6 +486,7 @@ function renderBlockImage(run, doc) {
|
|
|
463
486
|
widthPx: run.width,
|
|
464
487
|
heightPx: run.height
|
|
465
488
|
});
|
|
489
|
+
if (hasImageCrop(run)) applyImageBorder(wrapper, run);
|
|
466
490
|
applyPmPositions(container, run.pmStart, run.pmEnd);
|
|
467
491
|
container.append(wrapper);
|
|
468
492
|
return container;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { emuToPixels } from "../utils/units.js";
|
|
2
|
+
import { applySanitizedImageSrc } from "../utils/sanitizeImageSrc.js";
|
|
2
3
|
import { getTableRowLeadingWidth, isFloatingImageRun, isFloatingTextBoxBlock, tableColumnsArePinned } from "../layout-engine/types.js";
|
|
3
4
|
import { measureParagraph } from "../layout-engine/measure/measureParagraph.js";
|
|
4
5
|
import { resolveAnchoredImagePosition } from "./anchoredImagePosition.js";
|
|
@@ -70,7 +71,7 @@ function renderCellContent({ cell, cellMeasure, context, doc, contentWidthOverri
|
|
|
70
71
|
if (img.pmStart !== void 0) imgContainer.dataset["pmStart"] = String(img.pmStart);
|
|
71
72
|
if (img.pmEnd !== void 0) imgContainer.dataset["pmEnd"] = String(img.pmEnd);
|
|
72
73
|
const imgEl = doc.createElement("img");
|
|
73
|
-
imgEl
|
|
74
|
+
applySanitizedImageSrc(imgEl, img.src);
|
|
74
75
|
imgEl.style.width = `${img.width}px`;
|
|
75
76
|
imgEl.style.height = `${img.height}px`;
|
|
76
77
|
imgEl.style.display = "block";
|
|
@@ -3,7 +3,7 @@ import { Page } from "../layout-engine/types.js";
|
|
|
3
3
|
|
|
4
4
|
//#region src/layout-painter/renderWatermark.d.ts
|
|
5
5
|
type RenderWatermarkOptions = {
|
|
6
|
-
/** Resolved image src for picture watermarks (data
|
|
6
|
+
/** Resolved image src for picture watermarks (`data:` / `blob:` only). */imageSrc?: string;
|
|
7
7
|
};
|
|
8
8
|
/**
|
|
9
9
|
* Build the watermark overlay element for a page. Returns `null` when
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { resolveFontFamily } from "../utils/fontResolver.js";
|
|
2
|
+
import { applySanitizedImageSrc } from "../utils/sanitizeImageSrc.js";
|
|
2
3
|
//#region src/layout-painter/renderWatermark.ts
|
|
3
4
|
const WATERMARK_CLASS = "layout-page-watermark";
|
|
4
5
|
/**
|
|
@@ -47,7 +48,7 @@ function renderTextWatermark(watermark, doc) {
|
|
|
47
48
|
}
|
|
48
49
|
function renderPictureWatermark(watermark, imageSrc, doc) {
|
|
49
50
|
const img = doc.createElement("img");
|
|
50
|
-
img
|
|
51
|
+
applySanitizedImageSrc(img, imageSrc);
|
|
51
52
|
img.alt = "";
|
|
52
53
|
img.setAttribute("aria-hidden", "true");
|
|
53
54
|
const scalePct = (watermark.scale ?? 1) * 100;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createEmptyDocument } from "../utils/createDocument.js";
|
|
2
1
|
import { sanitizeExternalUrl } from "../utils/urlSecurity.js";
|
|
2
|
+
import { createEmptyDocument } from "../utils/createDocument.js";
|
|
3
3
|
import { marked } from "marked";
|
|
4
4
|
//#region src/markdown/fromMarkdown.ts
|
|
5
5
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { BlockSdtAttrs, FieldAttrs, HardBreakAttrs, ImageAttrs, MathAttrs, ParagraphAttrs, SdtAttrs, ShapeAttrs, TableAttrs, TableCellAttrs, TableRowAttrs, TextBoxAttrs } from "../schema/nodes.js";
|
|
2
1
|
import { CharacterSpacingAttrs, CharacterStyleAttrs, CommentAttrs, EmphasisMarkAttrs, FontFamilyAttrs, FontSizeAttrs, FootnoteRefAttrs, HighlightAttrs, HyperlinkAttrs, LanguageAttrs, RunFormattingOverrideAttrs, RunPropertyChangeMarkAttrs, RunShadingAttrs, StrikeAttrs, TextColorAttrs, TextEffectAttrs, TrackedChangeMarkAttrs, UnderlineAttrs } from "../schema/marks.js";
|
|
2
|
+
import { BlockSdtAttrs, FieldAttrs, HardBreakAttrs, ImageAttrs, MathAttrs, ParagraphAttrs, SdtAttrs, ShapeAttrs, TableAttrs, TableCellAttrs, TableRowAttrs, TextBoxAttrs } from "../schema/nodes.js";
|
|
3
3
|
import { Mark, Node } from "prosemirror-model";
|
|
4
4
|
|
|
5
5
|
//#region src/prosemirror/attrs/index.d.ts
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FIELD_TYPE_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LINE_SPACING_RULE_VALUES, OUTLINE_STYLE_ATTR_VALUES, PARAGRAPH_ALIGNMENT_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES } from "../../types/documentEnumValues.js";
|
|
2
2
|
import { isParagraphDirection } from "../paragraphDirection.js";
|
|
3
|
+
import { TRACKED_CHANGE_PROVENANCE_VALUES } from "../schema/marks.js";
|
|
3
4
|
import { panic } from "better-result";
|
|
4
5
|
//#region src/prosemirror/attrs/index.ts
|
|
5
6
|
const SECTION_BREAK_TYPES = [
|
|
@@ -600,7 +601,10 @@ const readTrackedChangeMarkAttrs = (mark) => {
|
|
|
600
601
|
requiredNumber(attrs, "revisionId", `${mark.type.name}.attrs.revisionId`, issues);
|
|
601
602
|
requiredString(attrs, "author", `${mark.type.name}.attrs.author`, issues);
|
|
602
603
|
optionalString(attrs, "date", `${mark.type.name}.attrs.date`, issues);
|
|
604
|
+
optionalString(attrs, "initials", `${mark.type.name}.attrs.initials`, issues);
|
|
603
605
|
optionalOneOf(attrs, "moveKind", `${mark.type.name}.attrs.moveKind`, issues, TRACKED_CHANGE_MOVE_KINDS);
|
|
606
|
+
optionalOneOf(attrs, "provenance", `${mark.type.name}.attrs.provenance`, issues, TRACKED_CHANGE_PROVENANCE_VALUES);
|
|
607
|
+
optionalString(attrs, "suggestionId", `${mark.type.name}.attrs.suggestionId`, issues);
|
|
604
608
|
return attrsResult(attrs, issues);
|
|
605
609
|
};
|
|
606
610
|
const expectTrackedChangeMarkAttrs = (mark) => expectCachedMarkAttrs(mark, trackedChangeAttrsCache, readTrackedChangeMarkAttrs, "tracked change attrs");
|
|
@@ -609,6 +613,8 @@ const readRunPropertyChangeMarkAttrs = (mark) => {
|
|
|
609
613
|
const issues = [];
|
|
610
614
|
expectMarkType(mark, "runPropertyChange", issues);
|
|
611
615
|
optionalPropertyChanges(attrs, "changes", "runPropertyChange.attrs.changes", issues, ["runPropertyChange"]);
|
|
616
|
+
optionalOneOf(attrs, "provenance", "runPropertyChange.attrs.provenance", issues, TRACKED_CHANGE_PROVENANCE_VALUES);
|
|
617
|
+
optionalString(attrs, "suggestionId", "runPropertyChange.attrs.suggestionId", issues);
|
|
612
618
|
return attrsResult(attrs, issues);
|
|
613
619
|
};
|
|
614
620
|
const expectRunPropertyChangeMarkAttrs = (mark) => expectCachedMarkAttrs(mark, runPropertyChangeAttrsCache, readRunPropertyChangeMarkAttrs, "run property change attrs");
|
|
@@ -934,6 +940,9 @@ const optionalTableRowRevision = (attrs, key, issues) => {
|
|
|
934
940
|
requiredNumber(value, "revisionId", `${path}.revisionId`, issues);
|
|
935
941
|
requiredString(value, "author", `${path}.author`, issues);
|
|
936
942
|
optionalString(value, "date", `${path}.date`, issues);
|
|
943
|
+
optionalString(value, "initials", `${path}.initials`, issues);
|
|
944
|
+
optionalOneOf(value, "provenance", `${path}.provenance`, issues, TRACKED_CHANGE_PROVENANCE_VALUES);
|
|
945
|
+
optionalString(value, "suggestionId", `${path}.suggestionId`, issues);
|
|
937
946
|
};
|
|
938
947
|
const optionalTableCellRevision = (attrs, issues) => {
|
|
939
948
|
const value = attrs["cellMarker"];
|
|
@@ -962,9 +971,21 @@ const optionalTableCellRevision = (attrs, issues) => {
|
|
|
962
971
|
requiredNumber(info, "revisionId", `${path}.info.revisionId`, issues);
|
|
963
972
|
requiredString(info, "author", `${path}.info.author`, issues);
|
|
964
973
|
optionalString(info, "date", `${path}.info.date`, issues);
|
|
974
|
+
optionalString(info, "initials", `${path}.info.initials`, issues);
|
|
965
975
|
if (value["kind"] === "merge") {
|
|
976
|
+
if (info["provenance"] !== void 0) issues.push({
|
|
977
|
+
path: `${path}.info.provenance`,
|
|
978
|
+
message: "Not allowed on a merge marker."
|
|
979
|
+
});
|
|
980
|
+
if (info["suggestionId"] !== void 0) issues.push({
|
|
981
|
+
path: `${path}.info.suggestionId`,
|
|
982
|
+
message: "Not allowed on a merge marker."
|
|
983
|
+
});
|
|
966
984
|
optionalOneOf(value, "verticalMerge", `${path}.verticalMerge`, issues, ["continue", "rest"]);
|
|
967
985
|
optionalOneOf(value, "verticalMergeOriginal", `${path}.verticalMergeOriginal`, issues, ["continue", "rest"]);
|
|
986
|
+
} else {
|
|
987
|
+
optionalOneOf(info, "provenance", `${path}.info.provenance`, issues, TRACKED_CHANGE_PROVENANCE_VALUES);
|
|
988
|
+
optionalString(info, "suggestionId", `${path}.info.suggestionId`, issues);
|
|
968
989
|
}
|
|
969
990
|
};
|
|
970
991
|
const optionalTextBoxTrackedChange = (attrs, issues) => {
|
|
@@ -62,6 +62,81 @@ declare function acceptAIEditRevision(revisionIds: number | readonly number[]):
|
|
|
62
62
|
* See {@link acceptAIEditRevision} for the id semantics.
|
|
63
63
|
*/
|
|
64
64
|
declare function rejectAIEditRevision(revisionIds: number | readonly number[]): Command;
|
|
65
|
+
type SuggestionKind = "insertion" | "deletion" | "formatting" | "insertBlock" | "insertTable" | "insertRow" | "deleteRow" | "insertColumn" | "deleteColumn";
|
|
66
|
+
/**
|
|
67
|
+
* How a suggestion is applied when accepted:
|
|
68
|
+
* - `"tracked"` — converts to a normal OOXML tracked change (`w:ins`/`w:del`,
|
|
69
|
+
* paragraph-mark `w:ins`, row/cell `w:ins`/`w:del`);
|
|
70
|
+
* - `"direct"` — no OOXML tracked representation exists (a whole inserted
|
|
71
|
+
* table), so accepting applies it directly;
|
|
72
|
+
* - `"mixed"` — a heterogeneous group (one `suggestionId` spanning a whole
|
|
73
|
+
* inserted table AND other edits) whose parts apply both ways. Accept still
|
|
74
|
+
* resolves the whole group in one transaction; this flag lets the host
|
|
75
|
+
* message that some parts landed directly.
|
|
76
|
+
*/
|
|
77
|
+
type SuggestionAppliedAs = "tracked" | "direct" | "mixed";
|
|
78
|
+
type FolioSuggestion = {
|
|
79
|
+
suggestionId: string; /** Contiguous document ranges the suggestion covers, in document order. */
|
|
80
|
+
ranges: readonly {
|
|
81
|
+
from: number;
|
|
82
|
+
to: number;
|
|
83
|
+
}[]; /** Which kinds of change the suggestion contains (deduped, in a stable order). */
|
|
84
|
+
kinds: readonly SuggestionKind[]; /** How accepting this suggestion applies it (see {@link SuggestionAppliedAs}). */
|
|
85
|
+
appliedAs: SuggestionAppliedAs;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* List every suggestion in the document for host consumption: its id, the
|
|
89
|
+
* contiguous ranges it covers, which kinds of change it contains, and how
|
|
90
|
+
* accepting it applies (tracked vs direct).
|
|
91
|
+
*/
|
|
92
|
+
declare function getSuggestions(state: EditorState): FolioSuggestion[];
|
|
93
|
+
/**
|
|
94
|
+
* The document range covering every mark belonging to `suggestionId`, plus the
|
|
95
|
+
* revision ids those marks carry. Returns null when the suggestion is absent
|
|
96
|
+
* (already accepted/rejected, or never existed).
|
|
97
|
+
*/
|
|
98
|
+
declare function findSuggestionRange(state: EditorState, suggestionId: string): {
|
|
99
|
+
from: number;
|
|
100
|
+
to: number;
|
|
101
|
+
revisionIds: number[];
|
|
102
|
+
} | null;
|
|
103
|
+
type AcceptSuggestionOptions = {
|
|
104
|
+
author: string;
|
|
105
|
+
/**
|
|
106
|
+
* Date stamped on the resulting user tracked change (serialized as `w:date`);
|
|
107
|
+
* defaults to now. A malformed / non-parseable value is normalized to now, and
|
|
108
|
+
* a valid value is canonicalized to ISO 8601, so an invalid date can never be
|
|
109
|
+
* written into the document.
|
|
110
|
+
*/
|
|
111
|
+
date?: string;
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Accept one suggestion: convert its inline marks and block/table node
|
|
115
|
+
* revisions into normal tracked changes authored by `author`, keeping revision
|
|
116
|
+
* ids. A whole inserted table (which OOXML cannot track) is applied directly;
|
|
117
|
+
* everything else becomes a tracked change. See {@link getSuggestions} for the
|
|
118
|
+
* per-suggestion `appliedAs`.
|
|
119
|
+
*/
|
|
120
|
+
declare function acceptSuggestion(suggestionId: string, options: AcceptSuggestionOptions): Command;
|
|
121
|
+
/** Accept every suggestion in the document. */
|
|
122
|
+
declare function acceptAllSuggestions(options: AcceptSuggestionOptions): Command;
|
|
123
|
+
/**
|
|
124
|
+
* Reject one suggestion: inverse-apply it in a single transaction. Runs BOTH
|
|
125
|
+
* phases so a heterogeneous group (one `suggestionId` spanning whole-node
|
|
126
|
+
* inserts AND other edits) is fully resolved:
|
|
127
|
+
* 1. inline marks and suggested `trIns`/`trDel`/`cellMarker` revisions are
|
|
128
|
+
* inverse-applied through {@link resolveChange} (delete suggested-inserted
|
|
129
|
+
* text/rows/cells, drop suggested deletions/formatting);
|
|
130
|
+
* 2. any remaining whole-node inserts (paragraph/table) are then deleted,
|
|
131
|
+
* mapped through the accumulated transaction so positions stay valid.
|
|
132
|
+
*
|
|
133
|
+
* A paragraph whole-node insert carries inline marks with the same revision id,
|
|
134
|
+
* so phase 1 empties its text and phase 2 removes the now-empty node; a whole
|
|
135
|
+
* inserted table has no matching revision, so only phase 2 removes it.
|
|
136
|
+
*/
|
|
137
|
+
declare function rejectSuggestion(suggestionId: string): Command;
|
|
138
|
+
/** Reject every suggestion in the document. */
|
|
139
|
+
declare function rejectAllSuggestions(): Command;
|
|
65
140
|
type ChangeRange = {
|
|
66
141
|
from: number;
|
|
67
142
|
to: number;
|
|
@@ -90,4 +165,4 @@ declare function findNextChange(state: EditorState, startPos: number): ChangeRan
|
|
|
90
165
|
*/
|
|
91
166
|
declare function findPreviousChange(state: EditorState, startPos: number): ChangeRange | null;
|
|
92
167
|
//#endregion
|
|
93
|
-
export { ParagraphBoundaryChange, acceptAIEditRevision, acceptAllChanges, acceptChange, addCommentMark, findAIEditRevisionRange, findChangeAtPosition, findNextChange, findParagraphBoundaryChangeAtPosition, findPreviousChange, rejectAIEditRevision, rejectAllChanges, rejectChange, removeCommentMark };
|
|
168
|
+
export { AcceptSuggestionOptions, FolioSuggestion, ParagraphBoundaryChange, SuggestionAppliedAs, SuggestionKind, acceptAIEditRevision, acceptAllChanges, acceptAllSuggestions, acceptChange, acceptSuggestion, addCommentMark, findAIEditRevisionRange, findChangeAtPosition, findNextChange, findParagraphBoundaryChangeAtPosition, findPreviousChange, findSuggestionRange, getSuggestions, rejectAIEditRevision, rejectAllChanges, rejectAllSuggestions, rejectChange, rejectSuggestion, removeCommentMark };
|