alinea
Version:
[](https://npmjs.org/package/alinea) [](https://packagephobia.com/result?p=alinea)
102 lines (100 loc) • 3.52 kB
JavaScript
import "../../../chunks/chunk-U5RRZUYZ.js";
// src/dashboard/view/diff/RichTextDiff.tsx
import { Sink } from "alinea/ui/Sink";
import { useMemo } from "react";
import { ChangeBox } from "./ChangeBox.js";
import { diffList, diffRecord } from "./DiffUtils.js";
import { FieldsDiff } from "./FieldsDiff.js";
import { ScalarDiff } from "./ScalarDiff.js";
import { jsx } from "react/jsx-runtime";
var blockTypes = /* @__PURE__ */ new Set(["heading", "paragraph", "listItem"]);
function contentToString({ type, content }) {
const withNewLine = blockTypes.has(type);
if (!content || !Array.isArray(content))
return "";
return content.map((block) => {
if ("text" in 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) {
switch (block.type) {
case "text":
text += block.text + " ";
default:
const firstChar = block.type[0];
if (!firstChar)
continue;
const isCustomBlock = firstChar === firstChar.toUpperCase();
if (isCustomBlock) {
if (text) {
parts.push({ type: "text", text });
text = "";
}
parts.push({ type: "block", block });
} else {
text += contentToString(block);
}
}
}
if (text)
parts.push({ type: "text", text });
return parts;
}
function RichTextDiff({ 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.id === partB.block.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.type;
const kind = shape.values?.[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
};