Plugin for Lix that tracks changes in ProseMirror documents.
Try out the example app → • See the example directory for a local setup.
npm install @lix-js/sdk @lix-js/plugin-prosemirrorimport { openLix } from "@lix-js/sdk";
import { plugin as prosemirrorPlugin } from "@lix-js/plugin-prosemirror";
export const lix = await openLix({ providePlugins: [prosemirrorPlugin] });const file = await lix.db
.insertInto("file")
.values({
path: "/doc.json",
data: new TextEncoder().encode(
JSON.stringify({ type: "doc", content: [] }),
),
})
.returningAll()
.executeTakeFirstOrThrow();import { EditorState } from "prosemirror-state";
import { EditorView } from "prosemirror-view";
import { lixProsemirror, idPlugin } from "@lix-js/plugin-prosemirror";
const state = EditorState.create({
schema,
doc: schema.nodeFromJSON({ type: "doc", content: [] }),
plugins: [
idPlugin(), // add stable ids if your schema doesn't provide them
lixProsemirror({ lix, fileId: file.id }),
],
});
const view = new EditorView(document.querySelector("#editor"), { state });attrs.id becomes a stored entity. The document entity keeps the ordered list of child IDs.applyChanges rebuilds the ProseMirror JSON by merging stored node snapshots and the document’s children_order.attrs.id. Use idPlugin() if your schema does not supply IDs.id attribute on the node types you want to track.children_order. Inserting in the middle or reparenting nodes will appear as moves plus any node-level edits.If your nodes don’t already have IDs, add the bundled idPlugin() so the ProseMirror plugin can track them:
{
"type": "doc",
"content": [
{
"attrs": {
+ "id": "unique-id-1"
},
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Hello World"
}
]
}
]
}You can render review-friendly diffs with HTML Diff. Serialize the before/after ProseMirror JSON to HTML using your schema, then feed the two HTML strings to HTML Diff:
import { renderHtmlDiff } from "@lix-js/html-diff";
import { DOMSerializer, Schema } from "prosemirror-model";
// Convert ProseMirror JSON to HTML
const toHtml = (schema: Schema, json: any) => {
const doc = schema.nodeFromJSON(json);
const div = document.createElement("div");
const fragment = DOMSerializer.fromSchema(schema).serializeFragment(doc.content);
div.appendChild(fragment);
return div.innerHTML;
};
const beforeHtml = toHtml(schema, beforeJson);
const afterHtml = toHtml(schema, afterJson);
const diffHtml = await renderHtmlDiff({
beforeHtml,
afterHtml,
diffAttribute: "data-diff-key",
});
// Render it wherever you show reviews
document.querySelector("#diff")!.innerHTML = diffHtml;