# Changed part of document

**URL:** <https://discuss.prosemirror.net/t/changed-part-of-document/992>\
**Category:** Uncategorized\
**Created:** [October 10, 2017, 8:58am UTC](https://discuss.prosemirror.net/t/changed-part-of-document/992 "2017-10-10T08:58:25Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![mirrec](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/mirrec/32/409_2.png) [@mirrec](https://discuss.prosemirror.net/u/mirrec)\
**Post date:** [October 10, 2017, 8:58am UTC](https://discuss.prosemirror.net/t/changed-part-of-document/992/1 "2017-10-10T08:58:25Z")

</div>

Hello,

Imagine you are [highlighting words](https://prosemirror.net/examples/lint/). If there is any change in document, example rescans hole document every time.

This might by inefficient for large documents. It would make much more sense to scan only changed part (or something around changed part).

Is there a easy / proper way to know which part of document was changed by transaction? Maybe some `from`, `to` positions for transactions. So we can directly call highlighting on only changed part of document.

Thanks a lot.

---

<div class="post-metadata">

**Author:** ![marijn](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/marijn/32/15_2.png) [@marijn](https://discuss.prosemirror.net/u/marijn)\
**Post date:** [October 10, 2017, 9:15am UTC](https://discuss.prosemirror.net/t/changed-part-of-document/992/2 "2017-10-10T09:15:31Z")

</div>

The recommended way to do this is to compare the old document to the new one and only process changed nodes. You can see an example of that [here](https://github.com/ProseMirror/prosemirror-tables/blob/master/src/fixtables.js#L10).

An alternative is to inspect the maps for the steps in the transaction, calling `forEach` on each to get the range that they touched, computing a minimum/maximum from those. You’ll have to take care to map positions from previous steps forward as you process subsequent steps (in transactions that contain multiple steps).

---

<div class="post-metadata">

**Author:** ![mirrec](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/mirrec/32/409_2.png) [@mirrec](https://discuss.prosemirror.net/u/mirrec)\
**Post date:** [October 11, 2017, 8:59am UTC](https://discuss.prosemirror.net/t/changed-part-of-document/992/3 "2017-10-11T08:59:44Z")

</div>

Thanks a lot!

Comparing documents sounds good. Thanks to document is persisted immutable data structure, it is not as had to implement. I used Map as a diff checker. Because nodes that does not change has the same hash key.

This is how solved the problem with changed nodes (deleted, added). Maybe this might be useful for someone else so I am putting my code here.

```auto
// returns removed nodes from old documents and added nodes in new documents
const compareDocuments = (oldDocument, newDocument) => {
  let diff = new Map()
  let removed = []

  newDocument.content.forEach((child, position) => {
    diff.set(child, position)
  })

  oldDocument.content.forEach((child, position) => {
    if (diff.has(child)) {
      diff.delete(child)
    }
    else {
      removed.push({ child: child, position: position})
    }
  })

  let added = Array.from(diff.entries()).map((value) => {
      return {child: value[0], position: value[1]}
    }
  )

  return {removed, added}
}

// calling in plugin
apply(tr, oldValue, oldState, newState) {
  let changed = compareDocuments(oldState.doc, newState.doc)
  // do something with results
}

```

Because my document schema is very trivial (similar to example in document guide). Therefore I do not need to call function recursive:

```auto
const trivialSchema = new Schema({
  nodes: {
    doc: {content: "paragraph+"},
    paragraph: {content: "text*"},
    text: {inline: true},
    /* ... and so on */
  }
})

```

---

<div class="post-metadata">

**Author:** ![tuanalumi](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/tuanalumi/32/2371_2.png) [@tuanalumi](https://discuss.prosemirror.net/u/tuanalumi)\
**Post date:** [October 15, 2021, 4:47am UTC](https://discuss.prosemirror.net/t/changed-part-of-document/992/4 "2021-10-15T04:47:05Z")

</div>

Hi.

Sorry to bring up this old topic.

I am currently in this situation. I could see that you came up with a solution, but it seems to be scanning the whole document in every update (newState.doc & oldState.doc both contain full document). Am I missing something?

---

<div class="post-metadata">

**Author:** ![TeemuKoivisto](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/teemukoivisto/32/1185_2.png) [@TeemuKoivisto](https://discuss.prosemirror.net/u/TeemuKoivisto)\
**Post date:** [October 15, 2021, 1:15pm UTC](https://discuss.prosemirror.net/t/changed-part-of-document/992/5 "2021-10-15T13:15:06Z")

</div>

If you want to implement track changes you are in a bit of trouble as detecting inserted/deleted content is very difficult. You can try using prosemirror-changeset for that, I made some example repo in github. To just iterate over inserted/replaced content per transaction you can use stepMap’s fromB, toB with `newDoc.nodesBetween`. If you want to know what was deleted you can use `oldDoc.nodesBetween(fromA, toA, ...`. Maybe that helps you in optimizing your scanning.

---

<div class="post-metadata">

**Author:** ![philippkuehn](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/philippkuehn/32/1820_2.png) [@philippkuehn](https://discuss.prosemirror.net/u/philippkuehn)\
**Post date:** [October 15, 2021, 6:35pm UTC](https://discuss.prosemirror.net/t/changed-part-of-document/992/6 "2021-10-15T18:35:39Z")

</div>

A very rudimentary solution is to use `findDiffStart` and `findDiffEnd` to find the changed start and end of two documents. This can be enough for _most_ cases.

```auto
const from = oldState.doc.content.findDiffStart(newState.doc.content)
const to = oldState.doc.content.findDiffEnd(newState.doc.content)

if (!from || !to || from === to.b) {
  return
}

newState.doc.nodesBetween(from, to.b, (node, pos) => {
  // ..
})

```

An edge case for this solution is a change at the start and end of a document within a single transaction for example. To calculate exact changes you have to map over transaction steps [like this](https://discuss.prosemirror.net/t/how-to-calculate-the-changed-ranges-for-transactions/3771/4).
