# src/Util/defragmentItemContent.js

    import ID from '../Util/ID/ID.js'
    import ItemJSON from '../Struct/ItemJSON.js'
    import ItemString from '../Struct/ItemString.js'

    /**
     * Try to merge all items in os with their successors.
     *
     * Some transformations (like delete) fragment items.
     * Item(c: 'ab') + Delete(1,1) + Delete(0, 1) -> Item(c: 'a',deleted);Item(c: 'b',deleted)
     *
     * This functions merges the fragmented nodes together:
     * Item(c: 'a',deleted);Item(c: 'b',deleted) -> Item(c: 'ab', deleted)
     *
     * TODO: The Tree implementation does not support deletions in-spot.
     *       This is why all deletions must be performed after the traversal.
     *
     */
    export function defragmentItemContent (y) {
      const os = y.os
      if (os.length < 2) {
        return
      }
      let deletes = []
      let node = os.findSmallestNode()
      let next = node.next()
      while (next !== null) {
        let a = node.val
        let b = next.val
        if (
          (a instanceof ItemJSON || a instanceof ItemString) &&
          a.constructor === b.constructor &&
          a._deleted === b._deleted &&
          a._right === b &&
          (new ID(a._id.user, a._id.clock + a._length)).equals(b._id)
        ) {
          a._right = b._right
          if (a instanceof ItemJSON) {
            a._content = a._content.concat(b._content)
          } else if (a instanceof ItemString) {
            a._content += b._content
          }
          // delete b later
          deletes.push(b._id)
          // do not iterate node!
          // !(node = next)
        } else {
          // not able to merge node, get next node
          node = next
        }
        // update next
        next = next.next()
      }
      for (let i = deletes.length - 1; i >= 0; i--) {
        os.delete(deletes[i])
      }
    }