Versions

When you compare two versions of a document, charts and diagrams are compared by what the document stores, never by how they look. A chart or a diagram has changed when any of its stored attributes differs, except the ones you tell the comparison to ignore.

What is compared

A chart is compared by its data, spec, Renderer, Data Source, delimiter and when that source was last read. The table under With Tiptap's Compare says when each changes. A diagram is compared by its source text, format, title, description, view and options. Add 'view' to ignoreAttributes if switching to the code view should not count as a change.

With Tiptap's Compare

@tiptap-pro/compare compares the JSON of two documents. It reports a chart or a diagram whose attributes differ as a changed block. Leave out the attributes that only matter for 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'],
  },
})
AttributeChanges whenIn a comparison
datavalues are edited, or a synchronization brings different dataa change
specthe type, title, colors, axes or references changea change
rendereranother Renderer is chosen. The data stays the samea change
sourcethe Data Source is linked or detached, or its address changesa change
delimiterthe rows are changed as text with another delimitera change. Add 'delimiter' to ignoreAttributes to leave it out
syncedAtthe chart reads its Data Source, also when the data is the samea change. Add 'syncedAt' to ignoreAttributes to leave it out
previewUrla preview image is uploaded after a changeleave out
diagramInput (on a table)the table is used as the Quick Input's table viewleave out

Saying what changed in a chart

describeChartChange from @tiptap-pro/extension-diagrams/core tells you what changed inside a chart, 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:

FieldWhat it holds
changedWhether 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 different label. Otherwise they are named by their position.
  • Cells are named by their row and their column header.
  • Attributes from any document work, also from documents made before syncedAt was an attribute of its own.
  • Attributes it cannot read count as an empty chart.