@stll/folio-core 0.12.0 → 0.13.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/extractDocxText.js +55 -8
- package/dist/docx/settingsParser.js +15 -2
- package/dist/docx/tableParser.d.ts +8 -1
- package/dist/docx/tableParser.js +13 -3
- 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 +16 -3
- package/dist/layout-engine/measure/cache.js +2 -0
- package/dist/layout-engine/measure/effectiveLineBreakPolicy.js +8 -2
- 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 +9 -1
- 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 +3 -2
- 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/render-dom/RemoteSelectionOverlay.js +2 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.js +3 -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
|
@@ -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 };
|