alinea
Version:
Headless git-based CMS
95 lines (93 loc) • 3.38 kB
JavaScript
import "../../../chunks/chunk-NZLE2WMY.js";
// src/dashboard/view/diff/RichTextDiff.tsx
import { BlockNode, Node } from "alinea/core/TextDoc";
import { Sink } from "alinea/ui/Sink";
import { useMemo } from "react";
import { ChangeBox } from "./ChangeBox.js";
import { diffList, diffRecord } from "./DiffUtils.js";
import { ScalarDiff } from "./ScalarDiff.js";
import { jsx } from "react/jsx-runtime";
var blockTypes = /* @__PURE__ */ new Set(["heading", "paragraph", "listItem"]);
function contentToString({ _type: type, content }) {
const withNewLine = blockTypes.has(type);
if (!content || !Array.isArray(content)) return "";
return content.map((block) => {
if (Node.isText(block)) return `${block.text} `;
return contentToString(block);
}).join("") + (withNewLine ? "\n\n" : "");
}
function textDocParts(textDoc) {
const parts = [];
let text = "";
if (!Array.isArray(textDoc)) return parts;
for (const block of textDoc) {
if (Node.isText(block)) {
text += `${block.text} `;
} else if (Node.isElement(block)) {
text += contentToString(block);
} else if (Node.isBlock(block)) {
if (text) {
parts.push({ type: "text", text });
text = "";
}
parts.push({ type: "block", block });
}
}
if (text) parts.push({ type: "text", text });
return parts;
}
function RichTextDiff({
FieldsDiff,
shape,
valueA,
valueB
}) {
const parts = useMemo(() => {
return { a: textDocParts(valueA), b: textDocParts(valueB) };
}, [valueA, valueB]);
const length = Math.max(parts.a.length, parts.b.length);
const res = [];
const equals = (partA, partB) => {
if (partA.type !== partA.type) return false;
if (partA.type === "block" && partB.type === "block")
return partA.block[BlockNode.id] === partB.block[BlockNode.id];
return true;
};
const changes = diffList(parts.a, parts.b, equals);
return /* @__PURE__ */ jsx(Sink.Root, { children: changes.map((change, i) => {
switch (change.value.type) {
case "block": {
const name = change.value.block[Node.type];
const kind = shape.blocks?.[name];
const compare = change.type === "keep" ? [
"block" in change.old && change.old.block || {},
change.value.block
] : change.type === "removal" ? [change.value.block, {}] : [{}, change.value.block];
const changes2 = diffRecord(
kind,
compare[0],
compare[1]
);
if (changes2.length === 0)
return /* @__PURE__ */ jsx(ChangeBox, { change: "equal" }, i);
return /* @__PURE__ */ jsx(ChangeBox, { change: change.type, children: /* @__PURE__ */ jsx(
FieldsDiff,
{
changes: changes2,
targetA: compare[0],
targetB: compare[1]
}
) }, i);
}
case "text": {
const compare = change.type === "keep" ? ["text" in change.old && change.old.text, change.value.text] : change.type === "removal" ? [change.value.text, ""] : ["", change.value.text];
if (compare[0] === compare[1])
return /* @__PURE__ */ jsx(ChangeBox, { change: "equal" }, i);
return /* @__PURE__ */ jsx(ChangeBox, { change: change.type, children: /* @__PURE__ */ jsx(ScalarDiff, { valueA: compare[0], valueB: compare[1] }) }, i);
}
}
}) });
}
export {
RichTextDiff
};