"Overlap" handling of findDiffStart() and findDiffEnd()

This subtle detail confused me a good bit as well.

I ended up writing the function below for our application to get a more or less guaranteed-to-be-correct diff range for the updated document (latest state), for example in an appendTransaction context.

/**
 * Get start and end diff position values for two states (old, new).
 * @param {EditorState} oldState - last PM state
 * @param {EditorState} newState - current PM state
 * @returns {object} - { start, end }
 */
function getDiffRange (oldState, newState) {
  // https://prosemirror.net/docs/ref/#model.Fragment.findDiffStart
  const start = oldState.doc.content.findDiffStart(newState.doc.content)
  // Important: diffEnd value is {a,b} object since end pos will differ.
  // https://prosemirror.net/docs/ref/#model.Fragment.findDiffEnd
  let { a, b } = oldState.doc.content.findDiffEnd(newState.doc.content)
  // WARNING: diffEnd may be lower than diffStart.
  // If so, add overlap to get correct range.
  // https://discuss.prosemirror.net/t/overlap-handling-of-finddiffstart-and-finddiffend/2856
  const overlap = start - Math.min(a, b)
  if (overlap > 0) b += overlap
  return { start, end: b }
}

I think this is the correct approach, please let me know if I misunderstood anything.

Hopefully this is useful to future readers too.

:vulcan_salute:

3 Likes