commit
						1a0d4aa797
					
				@ -60,7 +60,7 @@ characters have either been deleted or all characters are not deleted. The item
 | 
				
			|||||||
will be split if the run is interrupted for any reason (eg a character in the
 | 
					will be split if the run is interrupted for any reason (eg a character in the
 | 
				
			||||||
middle of the run is deleted).
 | 
					middle of the run is deleted).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
When an item is created, it stores a reference to the IDs of the preceeding and
 | 
					When an item is created, it stores a reference to the IDs of the preceding and
 | 
				
			||||||
succeeding item. These are stored in the item's `origin` and `originRight`
 | 
					succeeding item. These are stored in the item's `origin` and `originRight`
 | 
				
			||||||
fields, respectively. These are used when peers concurrently insert at the same
 | 
					fields, respectively. These are used when peers concurrently insert at the same
 | 
				
			||||||
location in a document. Though quite rare in practice, Yjs needs to make sure
 | 
					location in a document. Though quite rare in practice, Yjs needs to make sure
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										10
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								README.md
									
									
									
									
									
								
							@ -110,7 +110,7 @@ Showcase](https://yjs-diagram.synergy.codes/).
 | 
				
			|||||||
* [Synthesia](https://www.synthesia.io) - Collaborative Video Editor
 | 
					* [Synthesia](https://www.synthesia.io) - Collaborative Video Editor
 | 
				
			||||||
* [thinkdeli](https://thinkdeli.com) - A fast and simple notes app powered by AI
 | 
					* [thinkdeli](https://thinkdeli.com) - A fast and simple notes app powered by AI
 | 
				
			||||||
* [ourboard](https://github.com/raimohanska/ourboard) - A collaborative whiteboard
 | 
					* [ourboard](https://github.com/raimohanska/ourboard) - A collaborative whiteboard
 | 
				
			||||||
  applicaiton
 | 
					  application
 | 
				
			||||||
* [Ellie.ai](https://ellie.ai) - Data Product Design and Collaboration
 | 
					* [Ellie.ai](https://ellie.ai) - Data Product Design and Collaboration
 | 
				
			||||||
* [GoPeer](https://gopeer.org/) - Collaborative tutoring
 | 
					* [GoPeer](https://gopeer.org/) - Collaborative tutoring
 | 
				
			||||||
* [screen.garden](https://screen.garden) - Collaborative backend for PKM apps.
 | 
					* [screen.garden](https://screen.garden) - Collaborative backend for PKM apps.
 | 
				
			||||||
@ -189,7 +189,7 @@ backends to y-websocket.
 | 
				
			|||||||
  <dt><a href="https://github.com/yjs/y-webrtc">y-webrtc</a></dt>
 | 
					  <dt><a href="https://github.com/yjs/y-webrtc">y-webrtc</a></dt>
 | 
				
			||||||
  <dd>
 | 
					  <dd>
 | 
				
			||||||
Propagates document updates peer-to-peer using WebRTC. The peers exchange
 | 
					Propagates document updates peer-to-peer using WebRTC. The peers exchange
 | 
				
			||||||
signaling data over signaling servers. Publically available signaling servers
 | 
					signaling data over signaling servers. Publicly available signaling servers
 | 
				
			||||||
are available. Communication over the signaling servers can be encrypted by
 | 
					are available. Communication over the signaling servers can be encrypted by
 | 
				
			||||||
providing a shared secret, keeping the connection information and the shared
 | 
					providing a shared secret, keeping the connection information and the shared
 | 
				
			||||||
document private.
 | 
					document private.
 | 
				
			||||||
@ -1097,7 +1097,7 @@ encoding format for document updates. If you prefer JSON encoding, you can
 | 
				
			|||||||
simply JSON.stringify / JSON.parse the relative position instead.
 | 
					simply JSON.stringify / JSON.parse the relative position instead.
 | 
				
			||||||
  </dd>
 | 
					  </dd>
 | 
				
			||||||
  <b><code>Y.decodeRelativePosition(Uint8Array):RelativePosition</code></b>
 | 
					  <b><code>Y.decodeRelativePosition(Uint8Array):RelativePosition</code></b>
 | 
				
			||||||
  <dd>Decode a binary-encoded relative position to a RelativePositon object.</dd>
 | 
					  <dd>Decode a binary-encoded relative position to a RelativePosition object.</dd>
 | 
				
			||||||
</dl>
 | 
					</dl>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Y.UndoManager
 | 
					### Y.UndoManager
 | 
				
			||||||
@ -1277,11 +1277,11 @@ More information about the specific implementation is available in
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
CRDTs that are suitable for shared text editing suffer from the fact that they
 | 
					CRDTs that are suitable for shared text editing suffer from the fact that they
 | 
				
			||||||
only grow in size. There are CRDTs that do not grow in size, but they do not
 | 
					only grow in size. There are CRDTs that do not grow in size, but they do not
 | 
				
			||||||
have the characteristics that are benificial for shared text editing (like
 | 
					have the characteristics that are beneficial for shared text editing (like
 | 
				
			||||||
intention preservation). Yjs implements many improvements to the original
 | 
					intention preservation). Yjs implements many improvements to the original
 | 
				
			||||||
algorithm that diminish the trade-off that the document only grows in size. We
 | 
					algorithm that diminish the trade-off that the document only grows in size. We
 | 
				
			||||||
can't garbage collect deleted structs (tombstones) while ensuring a unique
 | 
					can't garbage collect deleted structs (tombstones) while ensuring a unique
 | 
				
			||||||
order of the structs. But we can 1. merge preceeding structs into a single
 | 
					order of the structs. But we can 1. merge preceding structs into a single
 | 
				
			||||||
struct to reduce the amount of meta information, 2. we can delete content from
 | 
					struct to reduce the amount of meta information, 2. we can delete content from
 | 
				
			||||||
the struct if it is deleted, and 3. we can garbage collect tombstones if we
 | 
					the struct if it is deleted, and 3. we can garbage collect tombstones if we
 | 
				
			||||||
don't care about the order of the structs anymore (e.g. if the parent was
 | 
					don't care about the order of the structs anymore (e.g. if the parent was
 | 
				
			||||||
 | 
				
			|||||||
@ -26,7 +26,7 @@ export class AbstractStruct {
 | 
				
			|||||||
   * This method is already assuming that `this.id.clock + this.length === this.id.clock`.
 | 
					   * This method is already assuming that `this.id.clock + this.length === this.id.clock`.
 | 
				
			||||||
   * Also this method does *not* remove right from StructStore!
 | 
					   * Also this method does *not* remove right from StructStore!
 | 
				
			||||||
   * @param {AbstractStruct} right
 | 
					   * @param {AbstractStruct} right
 | 
				
			||||||
   * @return {boolean} wether this merged with right
 | 
					   * @return {boolean} whether this merged with right
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  mergeWith (right) {
 | 
					  mergeWith (right) {
 | 
				
			||||||
    return false
 | 
					    return false
 | 
				
			||||||
 | 
				
			|||||||
@ -155,11 +155,11 @@ export const findMarker = (yarray, index) => {
 | 
				
			|||||||
  //   }
 | 
					  //   }
 | 
				
			||||||
  // }
 | 
					  // }
 | 
				
			||||||
  // if (marker) {
 | 
					  // if (marker) {
 | 
				
			||||||
  //   if (window.lengthes == null) {
 | 
					  //   if (window.lengths == null) {
 | 
				
			||||||
  //     window.lengthes = []
 | 
					  //     window.lengths = []
 | 
				
			||||||
  //     window.getLengthes = () => window.lengthes.sort((a, b) => a - b)
 | 
					  //     window.getLengths = () => window.lengths.sort((a, b) => a - b)
 | 
				
			||||||
  //   }
 | 
					  //   }
 | 
				
			||||||
  //   window.lengthes.push(marker.index - pindex)
 | 
					  //   window.lengths.push(marker.index - pindex)
 | 
				
			||||||
  //   console.log('distance', marker.index - pindex, 'len', p && p.parent.length)
 | 
					  //   console.log('distance', marker.index - pindex, 'len', p && p.parent.length)
 | 
				
			||||||
  // }
 | 
					  // }
 | 
				
			||||||
  if (marker !== null && math.abs(marker.index - pindex) < /** @type {YText|YArray<any>} */ (p.parent).length / maxSearchMarker) {
 | 
					  if (marker !== null && math.abs(marker.index - pindex) < /** @type {YText|YArray<any>} */ (p.parent).length / maxSearchMarker) {
 | 
				
			||||||
@ -751,7 +751,7 @@ export const typeListInsertGenerics = (transaction, parent, index, content) => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Pushing content is special as we generally want to push after the last item. So we don't have to update
 | 
					 * Pushing content is special as we generally want to push after the last item. So we don't have to update
 | 
				
			||||||
 * the serach marker.
 | 
					 * the search marker.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param {Transaction} transaction
 | 
					 * @param {Transaction} transaction
 | 
				
			||||||
 * @param {AbstractType<any>} parent
 | 
					 * @param {AbstractType<any>} parent
 | 
				
			||||||
 | 
				
			|||||||
@ -478,7 +478,7 @@ export const cleanupYTextFormatting = type => {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * This will be called by the transction once the event handlers are called to potentially cleanup
 | 
					 * This will be called by the transaction once the event handlers are called to potentially cleanup
 | 
				
			||||||
 * formatting attributes.
 | 
					 * formatting attributes.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param {Transaction} transaction
 | 
					 * @param {Transaction} transaction
 | 
				
			||||||
@ -568,7 +568,7 @@ const deleteText = (transaction, currPos, length) => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * The Quill Delta format represents changes on a text document with
 | 
					 * The Quill Delta format represents changes on a text document with
 | 
				
			||||||
 * formatting information. For mor information visit {@link https://quilljs.com/docs/delta/|Quill Delta}
 | 
					 * formatting information. For more information visit {@link https://quilljs.com/docs/delta/|Quill Delta}
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @example
 | 
					 * @example
 | 
				
			||||||
 *   {
 | 
					 *   {
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@ export class YXmlEvent extends YEvent {
 | 
				
			|||||||
   * @param {YXmlElement|YXmlText|YXmlFragment} target The target on which the event is created.
 | 
					   * @param {YXmlElement|YXmlText|YXmlFragment} target The target on which the event is created.
 | 
				
			||||||
   * @param {Set<string|null>} subs The set of changed attributes. `null` is included if the
 | 
					   * @param {Set<string|null>} subs The set of changed attributes. `null` is included if the
 | 
				
			||||||
   *                   child list changed.
 | 
					   *                   child list changed.
 | 
				
			||||||
   * @param {Transaction} transaction The transaction instance with wich the
 | 
					   * @param {Transaction} transaction The transaction instance with which the
 | 
				
			||||||
   *                                  change was created.
 | 
					   *                                  change was created.
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  constructor (target, subs, transaction) {
 | 
					  constructor (target, subs, transaction) {
 | 
				
			||||||
 | 
				
			|||||||
@ -106,7 +106,7 @@ export class Doc extends ObservableV2 {
 | 
				
			|||||||
    this.isSynced = false
 | 
					    this.isSynced = false
 | 
				
			||||||
    this.isDestroyed = false
 | 
					    this.isDestroyed = false
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Promise that resolves once the document has been loaded from a presistence provider.
 | 
					     * Promise that resolves once the document has been loaded from a persistence provider.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    this.whenLoaded = promise.create(resolve => {
 | 
					    this.whenLoaded = promise.create(resolve => {
 | 
				
			||||||
      this.on('load', () => {
 | 
					      this.on('load', () => {
 | 
				
			||||||
 | 
				
			|||||||
@ -62,7 +62,7 @@ export class PermanentUserData {
 | 
				
			|||||||
        initUser(storeType.get(userDescription), userDescription)
 | 
					        initUser(storeType.get(userDescription), userDescription)
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    // add intial data
 | 
					    // add initial data
 | 
				
			||||||
    storeType.forEach(initUser)
 | 
					    storeType.forEach(initUser)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -66,7 +66,7 @@ export class RelativePosition {
 | 
				
			|||||||
     * after the meant position.
 | 
					     * after the meant position.
 | 
				
			||||||
     * I.e. position 1 in 'ab' is associated to character 'b'.
 | 
					     * I.e. position 1 in 'ab' is associated to character 'b'.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * If assoc < 0, then the relative position is associated to the caharacter
 | 
					     * If assoc < 0, then the relative position is associated to the character
 | 
				
			||||||
     * before the meant position.
 | 
					     * before the meant position.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @type {number}
 | 
					     * @type {number}
 | 
				
			||||||
 | 
				
			|||||||
@ -66,13 +66,13 @@ export const getState = (store, client) => {
 | 
				
			|||||||
 * @private
 | 
					 * @private
 | 
				
			||||||
 * @function
 | 
					 * @function
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const integretyCheck = store => {
 | 
					export const integrityCheck = store => {
 | 
				
			||||||
  store.clients.forEach(structs => {
 | 
					  store.clients.forEach(structs => {
 | 
				
			||||||
    for (let i = 1; i < structs.length; i++) {
 | 
					    for (let i = 1; i < structs.length; i++) {
 | 
				
			||||||
      const l = structs[i - 1]
 | 
					      const l = structs[i - 1]
 | 
				
			||||||
      const r = structs[i]
 | 
					      const r = structs[i]
 | 
				
			||||||
      if (l.id.clock + l.length !== r.id.clock) {
 | 
					      if (l.id.clock + l.length !== r.id.clock) {
 | 
				
			||||||
        throw new Error('StructStore failed integrety check')
 | 
					        throw new Error('StructStore failed integrity check')
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
				
			|||||||
@ -167,7 +167,7 @@ export class UpdateEncoderV2 extends DSEncoderV2 {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    this.keyMap = new Map()
 | 
					    this.keyMap = new Map()
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Refers to the next uniqe key-identifier to me used.
 | 
					     * Refers to the next unique key-identifier to me used.
 | 
				
			||||||
     * See writeKey method for more information.
 | 
					     * See writeKey method for more information.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @type {number}
 | 
					     * @type {number}
 | 
				
			||||||
 | 
				
			|||||||
@ -211,7 +211,7 @@ export const readClientsStructRefs = (decoder, doc) => {
 | 
				
			|||||||
 * then we start emptying the stack.
 | 
					 * then we start emptying the stack.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * It is not possible to have circles: i.e. struct1 (from client1) depends on struct2 (from client2)
 | 
					 * It is not possible to have circles: i.e. struct1 (from client1) depends on struct2 (from client2)
 | 
				
			||||||
 * depends on struct3 (from client1). Therefore the max stack size is eqaul to `structReaders.length`.
 | 
					 * depends on struct3 (from client1). Therefore the max stack size is equal to `structReaders.length`.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This method is implemented in a way so that we can resume computation if this update
 | 
					 * This method is implemented in a way so that we can resume computation if this update
 | 
				
			||||||
 * causally depends on another update.
 | 
					 * causally depends on another update.
 | 
				
			||||||
@ -279,14 +279,14 @@ const integrateStructs = (transaction, store, clientsStructRefs) => {
 | 
				
			|||||||
  const addStackToRestSS = () => {
 | 
					  const addStackToRestSS = () => {
 | 
				
			||||||
    for (const item of stack) {
 | 
					    for (const item of stack) {
 | 
				
			||||||
      const client = item.id.client
 | 
					      const client = item.id.client
 | 
				
			||||||
      const unapplicableItems = clientsStructRefs.get(client)
 | 
					      const inapplicableItems = clientsStructRefs.get(client)
 | 
				
			||||||
      if (unapplicableItems) {
 | 
					      if (inapplicableItems) {
 | 
				
			||||||
        // decrement because we weren't able to apply previous operation
 | 
					        // decrement because we weren't able to apply previous operation
 | 
				
			||||||
        unapplicableItems.i--
 | 
					        inapplicableItems.i--
 | 
				
			||||||
        restStructs.clients.set(client, unapplicableItems.refs.slice(unapplicableItems.i))
 | 
					        restStructs.clients.set(client, inapplicableItems.refs.slice(inapplicableItems.i))
 | 
				
			||||||
        clientsStructRefs.delete(client)
 | 
					        clientsStructRefs.delete(client)
 | 
				
			||||||
        unapplicableItems.i = 0
 | 
					        inapplicableItems.i = 0
 | 
				
			||||||
        unapplicableItems.refs = []
 | 
					        inapplicableItems.refs = []
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        // item was the last item on clientsStructRefs and the field was already cleared. Add item to restStructs and continue
 | 
					        // item was the last item on clientsStructRefs and the field was already cleared. Add item to restStructs and continue
 | 
				
			||||||
        restStructs.clients.set(client, [item])
 | 
					        restStructs.clients.set(client, [item])
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Testing if encoding/decoding compatibility and integration compatiblity is given.
 | 
					 * Testing if encoding/decoding compatibility and integration compatibility is given.
 | 
				
			||||||
 * We expect that the document always looks the same, even if we upgrade the integration algorithm, or add additional encoding approaches.
 | 
					 * We expect that the document always looks the same, even if we upgrade the integration algorithm, or add additional encoding approaches.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * The v1 documents were generated with Yjs v13.2.0 based on the randomisized tests.
 | 
					 * The v1 documents were generated with Yjs v13.2.0 based on the randomisized tests.
 | 
				
			||||||
 | 
				
			|||||||
@ -58,7 +58,7 @@ export const testEmptyRestoreSnapshot = _tc => {
 | 
				
			|||||||
  t.compare(docRestored.getArray().toArray(), [])
 | 
					  t.compare(docRestored.getArray().toArray(), [])
 | 
				
			||||||
  t.compare(doc.getArray().toArray(), ['world'])
 | 
					  t.compare(doc.getArray().toArray(), ['world'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // now this snapshot reflects the latest state. It shoult still work.
 | 
					  // now this snapshot reflects the latest state. It should still work.
 | 
				
			||||||
  const snap2 = Y.snapshot(doc)
 | 
					  const snap2 = Y.snapshot(doc)
 | 
				
			||||||
  const docRestored2 = Y.createDocFromSnapshot(doc, snap2)
 | 
					  const docRestored2 = Y.createDocFromSnapshot(doc, snap2)
 | 
				
			||||||
  t.compare(docRestored2.getArray().toArray(), ['world'])
 | 
					  t.compare(docRestored2.getArray().toArray(), ['world'])
 | 
				
			||||||
 | 
				
			|||||||
@ -369,11 +369,11 @@ export const testObserversUsingObservedeep = tc => {
 | 
				
			|||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * @type {Array<Array<string|number>>}
 | 
					   * @type {Array<Array<string|number>>}
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  const pathes = []
 | 
					  const paths = []
 | 
				
			||||||
  let calls = 0
 | 
					  let calls = 0
 | 
				
			||||||
  map0.observeDeep(events => {
 | 
					  map0.observeDeep(events => {
 | 
				
			||||||
    events.forEach(event => {
 | 
					    events.forEach(event => {
 | 
				
			||||||
      pathes.push(event.path)
 | 
					      paths.push(event.path)
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    calls++
 | 
					    calls++
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
@ -381,7 +381,7 @@ export const testObserversUsingObservedeep = tc => {
 | 
				
			|||||||
  map0.get('map').set('array', new Y.Array())
 | 
					  map0.get('map').set('array', new Y.Array())
 | 
				
			||||||
  map0.get('map').get('array').insert(0, ['content'])
 | 
					  map0.get('map').get('array').insert(0, ['content'])
 | 
				
			||||||
  t.assert(calls === 3)
 | 
					  t.assert(calls === 3)
 | 
				
			||||||
  t.compare(pathes, [[], ['map'], ['map', 'array']])
 | 
					  t.compare(paths, [[], ['map'], ['map', 'array']])
 | 
				
			||||||
  compare(users)
 | 
					  compare(users)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -393,14 +393,14 @@ export const testPathsOfSiblingEvents = tc => {
 | 
				
			|||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * @type {Array<Array<string|number>>}
 | 
					   * @type {Array<Array<string|number>>}
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  const pathes = []
 | 
					  const paths = []
 | 
				
			||||||
  let calls = 0
 | 
					  let calls = 0
 | 
				
			||||||
  const doc = users[0]
 | 
					  const doc = users[0]
 | 
				
			||||||
  map0.set('map', new Y.Map())
 | 
					  map0.set('map', new Y.Map())
 | 
				
			||||||
  map0.get('map').set('text1', new Y.Text('initial'))
 | 
					  map0.get('map').set('text1', new Y.Text('initial'))
 | 
				
			||||||
  map0.observeDeep(events => {
 | 
					  map0.observeDeep(events => {
 | 
				
			||||||
    events.forEach(event => {
 | 
					    events.forEach(event => {
 | 
				
			||||||
      pathes.push(event.path)
 | 
					      paths.push(event.path)
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    calls++
 | 
					    calls++
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
@ -409,7 +409,7 @@ export const testPathsOfSiblingEvents = tc => {
 | 
				
			|||||||
    map0.get('map').set('text2', new Y.Text('new'))
 | 
					    map0.get('map').set('text2', new Y.Text('new'))
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
  t.assert(calls === 1)
 | 
					  t.assert(calls === 1)
 | 
				
			||||||
  t.compare(pathes, [['map'], ['map', 'text1']])
 | 
					  t.compare(paths, [['map'], ['map', 'text1']])
 | 
				
			||||||
  compare(users)
 | 
					  compare(users)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -376,7 +376,7 @@ export const testDeltaBug = _tc => {
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      insert: '\n',
 | 
					      insert: '\n',
 | 
				
			||||||
      // This attibutes has only list and no table-cell-line
 | 
					      // This attributes has only list and no table-cell-line
 | 
				
			||||||
      attributes: {
 | 
					      attributes: {
 | 
				
			||||||
        list: {
 | 
					        list: {
 | 
				
			||||||
          rowspan: '1',
 | 
					          rowspan: '1',
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user