Versions
A version comparison of a document with charts and diagrams compares what the document stores, never the picture. When any stored attribute differs between two versions, the chart or the diagram has changed.
What is compared
| Node | Its state |
|---|---|
| A chart | Its attributes: its data, spec, Renderer, Data Source and when that source was last read |
| A diagram | Its source text, format, title and options |
With Tiptap's Compare
@tiptap-pro/compare compares the JSON of two documents. A chart or a diagram whose attributes
differ is reported as a changed block. Leave out the attributes that only serve showing or
editing, so they do not show up as changes:
import { compareDocuments } from '@tiptap-pro/compare'
const changeset = compareDocuments({
schema: editor.schema,
docA: olderVersion,
docB: newerVersion,
diffOptions: {
// Compare's defaults, plus a chart's uploaded preview image and a table's Quick Input view
ignoreAttributes: ['id', 'data-thread-id', '_hash', 'previewUrl', 'diagramInput'],
},
})| Attribute | Changes when | In a comparison |
|---|---|---|
data | values are edited, or a synchronization brings different data | a change |
spec | the type, title, colors, axes or references change | a change |
renderer | another Renderer is chosen; the data stays the same | a change |
source | the Data Source is linked, detached, or its address changes | a change |
syncedAt | the chart reads its Data Source, also when the data is the same | a change; add 'syncedAt' to ignoreAttributes to leave it out |
previewUrl | a preview image is uploaded after a change | leave out |
diagramInput (on a table) | the table is used as the Quick Input's table view | leave out |
- A synchronization that brings the same data still records when the data was last checked.
- Whether that is a change worth showing is yours to decide with
ignoreAttributes.
Saying what changed in a chart
A comparison shows a changed chart as a whole. describeChartChange from
@tiptap-pro/extension-diagrams/core says what changed inside it, for a line such as
"February: 4 → 5, type: bar → line" next to the change:
import { describeChartChange } from '@tiptap-pro/extension-diagrams/core'
const change = describeChartChange({ before: olderChart.attrs, after: newerChart.attrs })
if (change.changed) {
const cells =
change.data?.cells.map(
(cell) => `${cell.row} ${cell.column}: ${cell.before} → ${cell.after}`,
) ?? []
const fields = change.spec.map(
(field) => `${field.path}: ${String(field.before)} → ${String(field.after)}`,
)
console.log([...cells, ...fields].join(', '))
}It returns:
| Field | What it holds |
|---|---|
changed | Whether anything below differs |
data | { columnsAdded, columnsRemoved, rowsAdded, rowsRemoved, cells }, or null |
spec | { path, before, after } for every spec field that differs, such as axes.y.min |
renderer, source, syncedAt | { before, after }, or null when unchanged |
- Rows are named by their label when every row has a distinct one, otherwise by their position.
- Cells are named by row and column header.
- Attributes from any document are accepted, also from before
syncedAtwas an attribute of its own. - What it cannot read counts as an empty chart.