smartrte-react 0.3.5 → 1.0.0-beta.2
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/CHANGELOG.md +14 -0
- package/README.md +106 -14
- package/dist/adapters/domChecklistCommandBridge.js +1 -1
- package/dist/adapters/domCommandBridge.d.ts +2 -2
- package/dist/adapters/domCommandBridge.js +2 -2
- package/dist/adapters/domInlineAtomCommandBridge.d.ts +10 -9
- package/dist/adapters/domInlineAtomCommandBridge.js +154 -50
- package/dist/adapters/domInlineImageCommandBridge.d.ts +7 -7
- package/dist/adapters/domInlineImageCommandBridge.js +6 -72
- package/dist/adapters/domMoveCommandBridge.js +1 -1
- package/dist/adapters/domSelectionBridge.d.ts +3 -3
- package/dist/adapters/domSmartDocument.d.ts +4 -4
- package/dist/adapters/domSmartDocument.js +2 -2
- package/dist/adapters/domTableCommandBridge.d.ts +42 -16
- package/dist/adapters/domTableCommandBridge.js +203 -173
- package/dist/adapters/internalFlags.d.ts +0 -8
- package/dist/adapters/internalFlags.js +0 -24
- package/dist/adapters/legacyListShadowComparator.d.ts +1 -1
- package/dist/adapters/legacyListShadowComparator.js +1 -1
- package/dist/adapters/pdfPrint.d.ts +8 -0
- package/dist/adapters/pdfPrint.js +22 -0
- package/dist/adapters/shadowMode.d.ts +3 -3
- package/dist/adapters/shadowMode.js +1 -1
- package/dist/canonicalEditorRuntime.d.ts +53 -1
- package/dist/canonicalEditorRuntime.js +61 -4
- package/dist/capabilityPresets.d.ts +27 -0
- package/dist/capabilityPresets.js +21 -0
- package/dist/collabTransport.d.ts +66 -0
- package/dist/collabTransport.js +1 -0
- package/dist/commentProvider.d.ts +24 -0
- package/dist/commentProvider.js +1 -0
- package/dist/components/CanonicalAuthorityEditor.d.ts +35 -1
- package/dist/components/CanonicalAuthorityEditor.js +1086 -112
- package/dist/components/ClassicEditorAuthority.d.ts +93 -22
- package/dist/components/ClassicEditorAuthority.js +11 -43
- package/dist/components/ColorPickerPopover.d.ts +39 -0
- package/dist/components/ColorPickerPopover.js +285 -0
- package/dist/components/CommentMarkers.d.ts +25 -0
- package/dist/components/CommentMarkers.js +105 -0
- package/dist/components/CommentThreadPanel.d.ts +26 -0
- package/dist/components/CommentThreadPanel.js +47 -0
- package/dist/components/ContextMenu.d.ts +23 -0
- package/dist/components/ContextMenu.js +141 -0
- package/dist/components/FormulaLibraryPopover.d.ts +16 -0
- package/dist/components/FormulaLibraryPopover.js +107 -0
- package/dist/components/LinkEditorPopover.d.ts +3 -1
- package/dist/components/LinkEditorPopover.js +22 -6
- package/dist/components/MediaManager.d.ts +4 -20
- package/dist/components/MediaManager.js +35 -6
- package/dist/components/MediaOverlay.d.ts +36 -0
- package/dist/components/MediaOverlay.js +163 -0
- package/dist/components/SpecialCharacterPopover.d.ts +18 -0
- package/dist/components/SpecialCharacterPopover.js +99 -0
- package/dist/components/StructuralSuggestionMarkers.d.ts +20 -0
- package/dist/components/StructuralSuggestionMarkers.js +56 -0
- package/dist/components/SuggestionPanel.d.ts +26 -0
- package/dist/components/SuggestionPanel.js +33 -0
- package/dist/components/TableBorderPopover.d.ts +59 -0
- package/dist/components/TableBorderPopover.js +147 -0
- package/dist/components/TableResizeHandles.d.ts +25 -0
- package/dist/components/TableResizeHandles.js +301 -0
- package/dist/components/TableSizePickerPopover.d.ts +16 -0
- package/dist/components/TableSizePickerPopover.js +126 -0
- package/dist/components/ToolbarPrimitives.d.ts +129 -0
- package/dist/components/ToolbarPrimitives.js +146 -0
- package/dist/components/VersionHistoryPanel.d.ts +9 -0
- package/dist/components/VersionHistoryPanel.js +157 -0
- package/dist/formulaLibrary.d.ts +31 -0
- package/dist/formulaLibrary.js +90 -0
- package/dist/index.d.ts +22 -24
- package/dist/index.js +14 -11
- package/dist/mediaManagerAdapter.d.ts +12 -0
- package/dist/mediaManagerAdapter.js +34 -0
- package/dist/mediaProvider.d.ts +21 -1
- package/dist/specialCharacters.d.ts +22 -0
- package/dist/specialCharacters.js +86 -0
- package/dist/standalone/classic-editor-embed.js +19 -12
- package/dist/suggestionProvider.d.ts +17 -0
- package/dist/suggestionProvider.js +1 -0
- package/dist/theme.d.ts +1 -1
- package/dist/theme.js +150 -20
- package/dist/versionProvider.d.ts +29 -0
- package/dist/versionProvider.js +1 -0
- package/package.json +28 -14
- package/dist/adapters/canonicalInlineCommandBridge.d.ts +0 -15
- package/dist/adapters/canonicalInlineCommandBridge.js +0 -269
- package/dist/adapters/canonicalListCommandBridge.d.ts +0 -26
- package/dist/adapters/canonicalListCommandBridge.js +0 -430
- package/dist/adapters/coreBold.d.ts +0 -5
- package/dist/adapters/coreBold.js +0 -3
- package/dist/adapters/documentFormats.d.ts +0 -26
- package/dist/adapters/documentFormats.js +0 -49
- package/dist/adapters/docxFormat.d.ts +0 -5
- package/dist/adapters/docxFormat.js +0 -272
- package/dist/adapters/domBlockCommandBridge.d.ts +0 -19
- package/dist/adapters/domBlockCommandBridge.js +0 -79
- package/dist/adapters/inlineMarkCoreExecution.d.ts +0 -9
- package/dist/adapters/inlineMarkCoreExecution.js +0 -25
- package/dist/adapters/pdfFormat.d.ts +0 -23
- package/dist/adapters/pdfFormat.js +0 -204
- package/dist/adapters/portableDocxAtoms.d.ts +0 -4
- package/dist/adapters/portableDocxAtoms.js +0 -58
- package/dist/adapters/styledDocxFormat.d.ts +0 -8
- package/dist/adapters/styledDocxFormat.js +0 -190
- package/dist/builtInFormatDefinitions.d.ts +0 -5
- package/dist/builtInFormatDefinitions.js +0 -82
- package/dist/canonicalAuthorityFlag.d.ts +0 -32
- package/dist/canonicalAuthorityFlag.js +0 -49
- package/dist/canonicalClipboardRuntime.d.ts +0 -15
- package/dist/canonicalClipboardRuntime.js +0 -76
- package/dist/components/ClassicEditor.d.ts +0 -76
- package/dist/components/ClassicEditor.js +0 -6729
- package/dist/editorController.d.ts +0 -78
- package/dist/editorController.js +0 -298
- package/dist/formatFidelity.d.ts +0 -14
- package/dist/formatFidelity.js +0 -107
- package/dist/formatRuntime.d.ts +0 -50
- package/dist/formatRuntime.js +0 -20
- package/dist/pluginRuntime.d.ts +0 -68
- package/dist/pluginRuntime.js +0 -78
- package/dist/standalone/editor.js +0 -1068
- package/dist/test-harness/atomShadowComparator.d.ts +0 -14
- package/dist/test-harness/atomShadowComparator.js +0 -63
- package/dist/test-harness/blockShadowComparator.d.ts +0 -30
- package/dist/test-harness/blockShadowComparator.js +0 -140
- package/dist/test-harness/clipboardShadowComparator.d.ts +0 -12
- package/dist/test-harness/clipboardShadowComparator.js +0 -46
- package/dist/test-harness/inlineShadowComparator.d.ts +0 -32
- package/dist/test-harness/inlineShadowComparator.js +0 -152
- package/dist/test-harness/legacyAtomEngine.d.ts +0 -10
- package/dist/test-harness/legacyAtomEngine.js +0 -15
- package/dist/test-harness/legacyBlockEngine.d.ts +0 -31
- package/dist/test-harness/legacyBlockEngine.js +0 -31
- package/dist/test-harness/legacyClipboardEngine.d.ts +0 -14
- package/dist/test-harness/legacyClipboardEngine.js +0 -67
- package/dist/test-harness/legacyInlineEngine.d.ts +0 -19
- package/dist/test-harness/legacyInlineEngine.js +0 -49
- package/dist/test-harness/legacyTableEngine.d.ts +0 -12
- package/dist/test-harness/legacyTableEngine.js +0 -25
- package/dist/test-harness/tableShadowComparator.d.ts +0 -29
- package/dist/test-harness/tableShadowComparator.js +0 -101
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
export function legacyCleanPastedHtml(html, options = {}, ownerDocument = document) {
|
|
2
|
-
const shouldPreserveColors = options.preserveColors ?? false;
|
|
3
|
-
const shouldPreserveDocumentLayout = options.preserveDocumentLayout ?? false;
|
|
4
|
-
const template = ownerDocument.createElement("template");
|
|
5
|
-
template.innerHTML = html
|
|
6
|
-
.replace(/ /gi, " ")
|
|
7
|
-
.replace(/\u00a0/g, " ")
|
|
8
|
-
.replace(/[\u200b\u200c\u200d]/g, "");
|
|
9
|
-
template.content.querySelectorAll("meta, link, style, script").forEach((node) => node.remove());
|
|
10
|
-
const allowedStyleNames = new Set([
|
|
11
|
-
"font-weight", "font-style", "text-decoration", "text-align", "vertical-align",
|
|
12
|
-
"border", "border-top", "border-right", "border-bottom", "border-left",
|
|
13
|
-
"border-collapse", "padding", "padding-top", "padding-right", "padding-bottom",
|
|
14
|
-
"padding-left", "list-style-type", "white-space",
|
|
15
|
-
]);
|
|
16
|
-
if (options.preserveFontFamily)
|
|
17
|
-
allowedStyleNames.add("font-family");
|
|
18
|
-
if (shouldPreserveColors) {
|
|
19
|
-
allowedStyleNames.add("color");
|
|
20
|
-
allowedStyleNames.add("background");
|
|
21
|
-
allowedStyleNames.add("background-color");
|
|
22
|
-
}
|
|
23
|
-
if (shouldPreserveDocumentLayout) {
|
|
24
|
-
[
|
|
25
|
-
"font-size", "line-height", "margin", "margin-top", "margin-right", "margin-bottom",
|
|
26
|
-
"margin-left", "text-indent", "width", "min-width",
|
|
27
|
-
].forEach((name) => allowedStyleNames.add(name));
|
|
28
|
-
}
|
|
29
|
-
template.content.querySelectorAll("*").forEach((node) => {
|
|
30
|
-
const className = node.getAttribute("class");
|
|
31
|
-
if (className !== "srte-preserve-colors")
|
|
32
|
-
node.removeAttribute("class");
|
|
33
|
-
node.removeAttribute("id");
|
|
34
|
-
if (!shouldPreserveDocumentLayout) {
|
|
35
|
-
node.removeAttribute("width");
|
|
36
|
-
node.removeAttribute("height");
|
|
37
|
-
}
|
|
38
|
-
const style = node.getAttribute("style");
|
|
39
|
-
if (!style)
|
|
40
|
-
return;
|
|
41
|
-
const safeRules = style
|
|
42
|
-
.split(";")
|
|
43
|
-
.map((rule) => rule.trim())
|
|
44
|
-
.filter(Boolean)
|
|
45
|
-
.filter((rule) => {
|
|
46
|
-
const separator = rule.indexOf(":");
|
|
47
|
-
if (separator === -1)
|
|
48
|
-
return false;
|
|
49
|
-
const name = rule.slice(0, separator).trim().toLowerCase();
|
|
50
|
-
const value = rule.slice(separator + 1).trim().toLowerCase();
|
|
51
|
-
if (!allowedStyleNames.has(name))
|
|
52
|
-
return false;
|
|
53
|
-
if (value.includes("position") || value.includes("expression") || value.includes("javascript:"))
|
|
54
|
-
return false;
|
|
55
|
-
if (name === "white-space" && value !== "pre-wrap")
|
|
56
|
-
return false;
|
|
57
|
-
if ((name === "width" || name === "min-width") && !/^[\d.]+(px|pt|em|rem|%)$/.test(value))
|
|
58
|
-
return false;
|
|
59
|
-
return true;
|
|
60
|
-
});
|
|
61
|
-
if (safeRules.length)
|
|
62
|
-
node.setAttribute("style", safeRules.join("; "));
|
|
63
|
-
else
|
|
64
|
-
node.removeAttribute("style");
|
|
65
|
-
});
|
|
66
|
-
return template.innerHTML;
|
|
67
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Test-only Phase 4 snapshot of the legacy inline command engine.
|
|
3
|
-
*
|
|
4
|
-
* This file was created before production inline handlers are removed. It must
|
|
5
|
-
* never be imported by product code. The shadow corpus keeps it so comparison
|
|
6
|
-
* remains possible after ClassicEditor routes exclusively to foundation marks.
|
|
7
|
-
*/
|
|
8
|
-
import { type SmartEditorState } from "smartrte-core/legacy";
|
|
9
|
-
export type LegacyInlineToolId = "bold" | "italic" | "underline" | "strike" | "code" | "superscript" | "subscript" | "textColor" | "backgroundColor" | "fontSize" | "fontFamily" | "link";
|
|
10
|
-
export declare const legacyInlineToolIds: readonly LegacyInlineToolId[];
|
|
11
|
-
export interface LegacyInlineResult {
|
|
12
|
-
readonly html: string;
|
|
13
|
-
readonly selection: SmartEditorState["selection"];
|
|
14
|
-
}
|
|
15
|
-
export declare const runLegacyInlineTool: (root: HTMLElement, tool: LegacyInlineToolId, input?: unknown) => LegacyInlineResult | null;
|
|
16
|
-
export declare const runLegacyLinkAction: (root: HTMLElement, action: "apply" | "edit" | "remove", input?: {
|
|
17
|
-
href: string;
|
|
18
|
-
target?: string;
|
|
19
|
-
}) => LegacyInlineResult | null;
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Test-only Phase 4 snapshot of the legacy inline command engine.
|
|
3
|
-
*
|
|
4
|
-
* This file was created before production inline handlers are removed. It must
|
|
5
|
-
* never be imported by product code. The shadow corpus keeps it so comparison
|
|
6
|
-
* remains possible after ClassicEditor routes exclusively to foundation marks.
|
|
7
|
-
*/
|
|
8
|
-
import { applyBackgroundColor, applyFontFamily, applyFontSize, applyLink, applyTextColor, applyTransaction, removeLink, toggleBold, toggleInlineCode, toggleItalic, toggleStrike, toggleSubscript, toggleSuperscript, toggleUnderline, updateLink, } from "smartrte-core/legacy";
|
|
9
|
-
import { selectionFromDom } from "../adapters/domSelectionBridge.js";
|
|
10
|
-
import { serializeSmartDocument, smartDocumentFromEditorRoot } from "../adapters/domSmartDocument.js";
|
|
11
|
-
const commands = Object.freeze({
|
|
12
|
-
bold: toggleBold,
|
|
13
|
-
italic: toggleItalic,
|
|
14
|
-
underline: toggleUnderline,
|
|
15
|
-
strike: toggleStrike,
|
|
16
|
-
code: toggleInlineCode,
|
|
17
|
-
superscript: toggleSuperscript,
|
|
18
|
-
subscript: toggleSubscript,
|
|
19
|
-
textColor: applyTextColor,
|
|
20
|
-
backgroundColor: applyBackgroundColor,
|
|
21
|
-
fontSize: applyFontSize,
|
|
22
|
-
fontFamily: applyFontFamily,
|
|
23
|
-
link: applyLink,
|
|
24
|
-
});
|
|
25
|
-
export const legacyInlineToolIds = Object.freeze(Object.keys(commands));
|
|
26
|
-
export const runLegacyInlineTool = (root, tool, input) => {
|
|
27
|
-
const selection = selectionFromDom(root, root.ownerDocument.getSelection());
|
|
28
|
-
if (!selection)
|
|
29
|
-
return null;
|
|
30
|
-
const { document } = smartDocumentFromEditorRoot(root);
|
|
31
|
-
const state = { document, selection };
|
|
32
|
-
const command = commands[tool];
|
|
33
|
-
if (!command.isEnabled(state, input))
|
|
34
|
-
return null;
|
|
35
|
-
const next = applyTransaction(state, command.execute(state, input));
|
|
36
|
-
return { html: serializeSmartDocument(next.document), selection: next.selection };
|
|
37
|
-
};
|
|
38
|
-
export const runLegacyLinkAction = (root, action, input) => {
|
|
39
|
-
const selection = selectionFromDom(root, root.ownerDocument.getSelection());
|
|
40
|
-
if (!selection)
|
|
41
|
-
return null;
|
|
42
|
-
const { document } = smartDocumentFromEditorRoot(root);
|
|
43
|
-
const state = { document, selection };
|
|
44
|
-
const command = action === "remove" ? removeLink : action === "edit" ? updateLink : applyLink;
|
|
45
|
-
if (!command.isEnabled(state, input))
|
|
46
|
-
return null;
|
|
47
|
-
const next = applyTransaction(state, command.execute(state, input));
|
|
48
|
-
return { html: serializeSmartDocument(next.document), selection: next.selection };
|
|
49
|
-
};
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Test-only snapshot of the pre-Phase-6 table engine entry point. Keep this
|
|
3
|
-
* isolated from product imports so shadow comparison remains possible after
|
|
4
|
-
* ClassicEditor switches to the foundation table commands.
|
|
5
|
-
*/
|
|
6
|
-
export interface LegacyTableIntent {
|
|
7
|
-
readonly id: string;
|
|
8
|
-
readonly input?: Readonly<Record<string, unknown>>;
|
|
9
|
-
}
|
|
10
|
-
export declare const executeRetainedLegacyTable: (html: string, intent: LegacyTableIntent, ownerDocument?: Document) => string | null;
|
|
11
|
-
/** Retained snapshot for the block-level table insertion command. */
|
|
12
|
-
export declare const executeRetainedLegacyTableInsert: (html: string, rows: number, columns: number, headerRow?: boolean, ownerDocument?: Document) => string | null;
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { createSmartEditor, tablePlugin } from "smartrte-core/legacy";
|
|
2
|
-
import { serializeSmartDocument, smartDocumentFromHtml } from "../adapters/domSmartDocument.js";
|
|
3
|
-
export const executeRetainedLegacyTable = (html, intent, ownerDocument = document) => {
|
|
4
|
-
const model = smartDocumentFromHtml(html, ownerDocument);
|
|
5
|
-
if (model.children.length !== 1 || model.children[0].type !== "table")
|
|
6
|
-
return null;
|
|
7
|
-
const editor = createSmartEditor({
|
|
8
|
-
state: { document: model, selection: { type: "node", path: [0] } },
|
|
9
|
-
plugins: [tablePlugin],
|
|
10
|
-
});
|
|
11
|
-
if (!editor.execute(intent.id, { ...(intent.input || {}), tablePath: [0] }))
|
|
12
|
-
return null;
|
|
13
|
-
return serializeSmartDocument(editor.state.document);
|
|
14
|
-
};
|
|
15
|
-
/** Retained snapshot for the block-level table insertion command. */
|
|
16
|
-
export const executeRetainedLegacyTableInsert = (html, rows, columns, headerRow = false, ownerDocument = document) => {
|
|
17
|
-
const model = smartDocumentFromHtml(html, ownerDocument);
|
|
18
|
-
const editor = createSmartEditor({
|
|
19
|
-
state: { document: model, selection: { type: "text", anchor: { path: [0, 0], offset: 0 }, focus: { path: [0, 0], offset: 0 } } },
|
|
20
|
-
plugins: [tablePlugin],
|
|
21
|
-
});
|
|
22
|
-
if (!editor.execute("table.insert", { path: [1], rows, columns, headerRow }))
|
|
23
|
-
return null;
|
|
24
|
-
return serializeSmartDocument(editor.state.document);
|
|
25
|
-
};
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { type DomTableCommand } from "../adapters/domTableCommandBridge.js";
|
|
2
|
-
export type TableShadowDivergence = "expected-normalization" | "equivalent-serialization" | "selection-only" | "visual-only" | "semantic" | "data-loss" | "unknown";
|
|
3
|
-
export interface TableShadowResult {
|
|
4
|
-
readonly equivalent: boolean;
|
|
5
|
-
readonly classification?: TableShadowDivergence;
|
|
6
|
-
readonly legacyStructureHash: string;
|
|
7
|
-
readonly canonicalStructureHash: string;
|
|
8
|
-
readonly selectionCompared?: boolean;
|
|
9
|
-
readonly selectionEquivalent?: boolean;
|
|
10
|
-
readonly legacySelectionHash?: string;
|
|
11
|
-
readonly canonicalSelectionHash?: string;
|
|
12
|
-
}
|
|
13
|
-
export declare const compareRetainedAndCanonicalTable: (html: string, command: DomTableCommand) => TableShadowResult;
|
|
14
|
-
/**
|
|
15
|
-
* Compares the retained block-level table insertion command with the
|
|
16
|
-
* canonical insertion path. The insertion caret is a stable semantic point:
|
|
17
|
-
* the first paragraph in the first inserted cell. This is intentionally
|
|
18
|
-
* separate from the cell-editing comparator above, whose old command surface
|
|
19
|
-
* did not expose a selection result.
|
|
20
|
-
*/
|
|
21
|
-
export declare const compareRetainedAndCanonicalTableInsert: (html: string, rows?: number, columns?: number, headerRow?: boolean) => TableShadowResult;
|
|
22
|
-
/** Hash-only comparator record. Document text and HTML are deliberately excluded. */
|
|
23
|
-
export declare const tableShadowLogRecord: (scenarioId: string, result: TableShadowResult) => {
|
|
24
|
-
classification?: TableShadowDivergence;
|
|
25
|
-
scenarioId: string;
|
|
26
|
-
equivalent: boolean;
|
|
27
|
-
legacyStructureHash: string;
|
|
28
|
-
canonicalStructureHash: string;
|
|
29
|
-
};
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { compareShadowDocuments, foundationSchema, isTextNode, normalizedStructureWithoutIds, parseCanonicalTableHtml } from "smartrte-core/foundation";
|
|
2
|
-
import { executeDomTableCommand, executeDomTableInsert, executeDomTableRemoval } from "../adapters/domTableCommandBridge.js";
|
|
3
|
-
import { executeRetainedLegacyTable, executeRetainedLegacyTableInsert } from "./legacyTableEngine.js";
|
|
4
|
-
const hash = (value) => {
|
|
5
|
-
const input = typeof value === "string" ? value : JSON.stringify(value) ?? String(value);
|
|
6
|
-
let state = 2166136261;
|
|
7
|
-
for (let index = 0; index < input.length; index += 1) {
|
|
8
|
-
state ^= input.charCodeAt(index);
|
|
9
|
-
state = Math.imul(state, 16777619);
|
|
10
|
-
}
|
|
11
|
-
return (state >>> 0).toString(16).padStart(8, "0");
|
|
12
|
-
};
|
|
13
|
-
const documentText = (node) => isTextNode(node) ? node.text : (node.children || []).map(documentText).join("");
|
|
14
|
-
export const compareRetainedAndCanonicalTable = (html, command) => {
|
|
15
|
-
const legacyHtml = executeRetainedLegacyTable(html, command);
|
|
16
|
-
const host = document.createElement("div");
|
|
17
|
-
host.innerHTML = html;
|
|
18
|
-
const canonicalTable = host.querySelector("table");
|
|
19
|
-
if (command.id === "table.remove") {
|
|
20
|
-
const legacyDocument = parseCanonicalTableHtml(legacyHtml || "");
|
|
21
|
-
const removed = canonicalTable instanceof HTMLTableElement && executeDomTableRemoval(canonicalTable);
|
|
22
|
-
const canonicalDocument = parseCanonicalTableHtml(host.innerHTML);
|
|
23
|
-
const legacy = normalizedStructureWithoutIds(legacyDocument, foundationSchema);
|
|
24
|
-
const current = normalizedStructureWithoutIds(canonicalDocument, foundationSchema);
|
|
25
|
-
const equivalent = removed && JSON.stringify(legacy) === JSON.stringify(current);
|
|
26
|
-
return {
|
|
27
|
-
equivalent,
|
|
28
|
-
legacyStructureHash: hash(legacy), canonicalStructureHash: hash(current),
|
|
29
|
-
...(!equivalent ? { classification: "semantic" } : {}),
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
const canonical = canonicalTable instanceof HTMLTableElement ? executeDomTableCommand(canonicalTable, command) : null;
|
|
33
|
-
if (!legacyHtml || !canonical)
|
|
34
|
-
return { equivalent: false, classification: "semantic", legacyStructureHash: hash(legacyHtml), canonicalStructureHash: hash(canonical?.outerHTML) };
|
|
35
|
-
const legacyDocument = parseCanonicalTableHtml(legacyHtml);
|
|
36
|
-
const canonicalDocument = parseCanonicalTableHtml(canonical.outerHTML);
|
|
37
|
-
const legacy = normalizedStructureWithoutIds(legacyDocument, foundationSchema);
|
|
38
|
-
const current = normalizedStructureWithoutIds(canonicalDocument, foundationSchema);
|
|
39
|
-
const equivalent = JSON.stringify(legacy) === JSON.stringify(current);
|
|
40
|
-
const dataLoss = documentText(canonicalDocument) !== documentText(legacyDocument);
|
|
41
|
-
const intentional = command.id === "table.header.row.toggle" || command.id === "table.header.column.toggle" || command.id === "table.header.cell.toggle"
|
|
42
|
-
? "visual-only" : "expected-normalization";
|
|
43
|
-
return {
|
|
44
|
-
equivalent, legacyStructureHash: hash(legacy), canonicalStructureHash: hash(current),
|
|
45
|
-
...(!equivalent ? { classification: dataLoss ? "data-loss" : intentional } : {}),
|
|
46
|
-
};
|
|
47
|
-
};
|
|
48
|
-
/**
|
|
49
|
-
* Compares the retained block-level table insertion command with the
|
|
50
|
-
* canonical insertion path. The insertion caret is a stable semantic point:
|
|
51
|
-
* the first paragraph in the first inserted cell. This is intentionally
|
|
52
|
-
* separate from the cell-editing comparator above, whose old command surface
|
|
53
|
-
* did not expose a selection result.
|
|
54
|
-
*/
|
|
55
|
-
export const compareRetainedAndCanonicalTableInsert = (html, rows = 2, columns = 2, headerRow = false) => {
|
|
56
|
-
const legacyHtml = executeRetainedLegacyTableInsert(html, rows, columns, headerRow);
|
|
57
|
-
const host = document.createElement("div");
|
|
58
|
-
host.innerHTML = html;
|
|
59
|
-
const canonicalTable = executeDomTableInsert(host, 0, rows, columns, headerRow);
|
|
60
|
-
if (!legacyHtml || !canonicalTable)
|
|
61
|
-
return {
|
|
62
|
-
equivalent: false,
|
|
63
|
-
classification: "semantic",
|
|
64
|
-
legacyStructureHash: hash(legacyHtml),
|
|
65
|
-
canonicalStructureHash: hash(host.innerHTML),
|
|
66
|
-
selectionCompared: true,
|
|
67
|
-
selectionEquivalent: false,
|
|
68
|
-
};
|
|
69
|
-
const legacyDocument = parseCanonicalTableHtml(legacyHtml);
|
|
70
|
-
const canonicalDocument = parseCanonicalTableHtml(host.innerHTML);
|
|
71
|
-
const selection = {
|
|
72
|
-
type: "text",
|
|
73
|
-
anchor: { path: [1, 0, 0, 0], offset: 0 },
|
|
74
|
-
head: { path: [1, 0, 0, 0], offset: 0 },
|
|
75
|
-
};
|
|
76
|
-
const comparison = compareShadowDocuments({
|
|
77
|
-
legacyDocument,
|
|
78
|
-
legacySelection: selection,
|
|
79
|
-
canonicalDocument,
|
|
80
|
-
canonicalSelection: selection,
|
|
81
|
-
schema: foundationSchema,
|
|
82
|
-
});
|
|
83
|
-
const insertionDataLoss = documentText(legacyDocument) !== documentText(canonicalDocument);
|
|
84
|
-
return {
|
|
85
|
-
equivalent: comparison.equivalent,
|
|
86
|
-
...(!comparison.documentEquivalent
|
|
87
|
-
? { classification: insertionDataLoss ? "data-loss" : "expected-normalization" }
|
|
88
|
-
: comparison.classification ? { classification: comparison.classification } : {}),
|
|
89
|
-
legacyStructureHash: comparison.legacyStructureHash,
|
|
90
|
-
canonicalStructureHash: comparison.canonicalStructureHash,
|
|
91
|
-
selectionCompared: true,
|
|
92
|
-
selectionEquivalent: comparison.selectionEquivalent,
|
|
93
|
-
legacySelectionHash: comparison.legacySelectionHash,
|
|
94
|
-
canonicalSelectionHash: comparison.canonicalSelectionHash,
|
|
95
|
-
};
|
|
96
|
-
};
|
|
97
|
-
/** Hash-only comparator record. Document text and HTML are deliberately excluded. */
|
|
98
|
-
export const tableShadowLogRecord = (scenarioId, result) => ({
|
|
99
|
-
scenarioId, equivalent: result.equivalent, legacyStructureHash: result.legacyStructureHash,
|
|
100
|
-
canonicalStructureHash: result.canonicalStructureHash, ...(result.classification ? { classification: result.classification } : {}),
|
|
101
|
-
});
|