Merge pull request #332 from yjs/types-as-embeds
Allow types as Y.Text embeds
This commit is contained in:
		
						commit
						ca0fb4b15d
					
				@ -26,6 +26,7 @@ import {
 | 
				
			|||||||
  typeMapGet,
 | 
					  typeMapGet,
 | 
				
			||||||
  typeMapGetAll,
 | 
					  typeMapGetAll,
 | 
				
			||||||
  updateMarkerChanges,
 | 
					  updateMarkerChanges,
 | 
				
			||||||
 | 
					  ContentType,
 | 
				
			||||||
  ArraySearchMarker, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, ID, Doc, Item, Snapshot, Transaction // eslint-disable-line
 | 
					  ArraySearchMarker, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, ID, Doc, Item, Snapshot, Transaction // eslint-disable-line
 | 
				
			||||||
} from '../internals.js'
 | 
					} from '../internals.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -62,17 +63,16 @@ export class ItemTextListPosition {
 | 
				
			|||||||
      error.unexpectedCase()
 | 
					      error.unexpectedCase()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    switch (this.right.content.constructor) {
 | 
					    switch (this.right.content.constructor) {
 | 
				
			||||||
      case ContentEmbed:
 | 
					 | 
				
			||||||
      case ContentString:
 | 
					 | 
				
			||||||
        if (!this.right.deleted) {
 | 
					 | 
				
			||||||
          this.index += this.right.length
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        break
 | 
					 | 
				
			||||||
      case ContentFormat:
 | 
					      case ContentFormat:
 | 
				
			||||||
        if (!this.right.deleted) {
 | 
					        if (!this.right.deleted) {
 | 
				
			||||||
          updateCurrentAttributes(this.currentAttributes, /** @type {ContentFormat} */ (this.right.content))
 | 
					          updateCurrentAttributes(this.currentAttributes, /** @type {ContentFormat} */ (this.right.content))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break
 | 
					        break
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        if (!this.right.deleted) {
 | 
				
			||||||
 | 
					          this.index += this.right.length
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        break
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    this.left = this.right
 | 
					    this.left = this.right
 | 
				
			||||||
    this.right = this.right.right
 | 
					    this.right = this.right.right
 | 
				
			||||||
@ -91,8 +91,12 @@ export class ItemTextListPosition {
 | 
				
			|||||||
const findNextPosition = (transaction, pos, count) => {
 | 
					const findNextPosition = (transaction, pos, count) => {
 | 
				
			||||||
  while (pos.right !== null && count > 0) {
 | 
					  while (pos.right !== null && count > 0) {
 | 
				
			||||||
    switch (pos.right.content.constructor) {
 | 
					    switch (pos.right.content.constructor) {
 | 
				
			||||||
      case ContentEmbed:
 | 
					      case ContentFormat:
 | 
				
			||||||
      case ContentString:
 | 
					        if (!pos.right.deleted) {
 | 
				
			||||||
 | 
					          updateCurrentAttributes(pos.currentAttributes, /** @type {ContentFormat} */ (pos.right.content))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        break
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
        if (!pos.right.deleted) {
 | 
					        if (!pos.right.deleted) {
 | 
				
			||||||
          if (count < pos.right.length) {
 | 
					          if (count < pos.right.length) {
 | 
				
			||||||
            // split right
 | 
					            // split right
 | 
				
			||||||
@ -102,11 +106,6 @@ const findNextPosition = (transaction, pos, count) => {
 | 
				
			|||||||
          count -= pos.right.length
 | 
					          count -= pos.right.length
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break
 | 
					        break
 | 
				
			||||||
      case ContentFormat:
 | 
					 | 
				
			||||||
        if (!pos.right.deleted) {
 | 
					 | 
				
			||||||
          updateCurrentAttributes(pos.currentAttributes, /** @type {ContentFormat} */ (pos.right.content))
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        break
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    pos.left = pos.right
 | 
					    pos.left = pos.right
 | 
				
			||||||
    pos.right = pos.right.right
 | 
					    pos.right = pos.right.right
 | 
				
			||||||
@ -245,7 +244,7 @@ const insertAttributes = (transaction, parent, currPos, attributes) => {
 | 
				
			|||||||
 * @param {Transaction} transaction
 | 
					 * @param {Transaction} transaction
 | 
				
			||||||
 * @param {AbstractType<any>} parent
 | 
					 * @param {AbstractType<any>} parent
 | 
				
			||||||
 * @param {ItemTextListPosition} currPos
 | 
					 * @param {ItemTextListPosition} currPos
 | 
				
			||||||
 * @param {string|object} text
 | 
					 * @param {string|object|AbstractType<any>} text
 | 
				
			||||||
 * @param {Object<string,any>} attributes
 | 
					 * @param {Object<string,any>} attributes
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @private
 | 
					 * @private
 | 
				
			||||||
@ -262,7 +261,7 @@ const insertText = (transaction, parent, currPos, text, attributes) => {
 | 
				
			|||||||
  minimizeAttributeChanges(currPos, attributes)
 | 
					  minimizeAttributeChanges(currPos, attributes)
 | 
				
			||||||
  const negatedAttributes = insertAttributes(transaction, parent, currPos, attributes)
 | 
					  const negatedAttributes = insertAttributes(transaction, parent, currPos, attributes)
 | 
				
			||||||
  // insert content
 | 
					  // insert content
 | 
				
			||||||
  const content = text.constructor === String ? new ContentString(/** @type {string} */ (text)) : new ContentEmbed(text)
 | 
					  const content = text.constructor === String ? new ContentString(/** @type {string} */ (text)) : (text instanceof AbstractType ? new ContentType(text) : new ContentEmbed(text))
 | 
				
			||||||
  let { left, right, index } = currPos
 | 
					  let { left, right, index } = currPos
 | 
				
			||||||
  if (parent._searchMarker) {
 | 
					  if (parent._searchMarker) {
 | 
				
			||||||
    updateMarkerChanges(parent._searchMarker, currPos.index, content.getLength())
 | 
					    updateMarkerChanges(parent._searchMarker, currPos.index, content.getLength())
 | 
				
			||||||
@ -308,8 +307,7 @@ const formatText = (transaction, parent, currPos, length, attributes) => {
 | 
				
			|||||||
          }
 | 
					          }
 | 
				
			||||||
          break
 | 
					          break
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        case ContentEmbed:
 | 
					        default:
 | 
				
			||||||
        case ContentString:
 | 
					 | 
				
			||||||
          if (length < currPos.right.length) {
 | 
					          if (length < currPos.right.length) {
 | 
				
			||||||
            getItemCleanStart(transaction, createID(currPos.right.id.client, currPos.right.id.clock + length))
 | 
					            getItemCleanStart(transaction, createID(currPos.right.id.client, currPos.right.id.clock + length))
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
@ -348,7 +346,7 @@ const formatText = (transaction, parent, currPos, length, attributes) => {
 | 
				
			|||||||
 * @function
 | 
					 * @function
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
const cleanupFormattingGap = (transaction, start, end, startAttributes, endAttributes) => {
 | 
					const cleanupFormattingGap = (transaction, start, end, startAttributes, endAttributes) => {
 | 
				
			||||||
  while (end && end.content.constructor !== ContentString && end.content.constructor !== ContentEmbed) {
 | 
					  while (end && (!end.countable || end.deleted)) {
 | 
				
			||||||
    if (!end.deleted && end.content.constructor === ContentFormat) {
 | 
					    if (!end.deleted && end.content.constructor === ContentFormat) {
 | 
				
			||||||
      updateCurrentAttributes(endAttributes, /** @type {ContentFormat} */ (end.content))
 | 
					      updateCurrentAttributes(endAttributes, /** @type {ContentFormat} */ (end.content))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -381,12 +379,12 @@ const cleanupFormattingGap = (transaction, start, end, startAttributes, endAttri
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
const cleanupContextlessFormattingGap = (transaction, item) => {
 | 
					const cleanupContextlessFormattingGap = (transaction, item) => {
 | 
				
			||||||
  // iterate until item.right is null or content
 | 
					  // iterate until item.right is null or content
 | 
				
			||||||
  while (item && item.right && (item.right.deleted || (item.right.content.constructor !== ContentString && item.right.content.constructor !== ContentEmbed))) {
 | 
					  while (item && item.right && (item.right.deleted || !item.right.countable)) {
 | 
				
			||||||
    item = item.right
 | 
					    item = item.right
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  const attrs = new Set()
 | 
					  const attrs = new Set()
 | 
				
			||||||
  // iterate back until a content item is found
 | 
					  // iterate back until a content item is found
 | 
				
			||||||
  while (item && (item.deleted || (item.content.constructor !== ContentString && item.content.constructor !== ContentEmbed))) {
 | 
					  while (item && (item.deleted || !item.countable)) {
 | 
				
			||||||
    if (!item.deleted && item.content.constructor === ContentFormat) {
 | 
					    if (!item.deleted && item.content.constructor === ContentFormat) {
 | 
				
			||||||
      const key = /** @type {ContentFormat} */ (item.content).key
 | 
					      const key = /** @type {ContentFormat} */ (item.content).key
 | 
				
			||||||
      if (attrs.has(key)) {
 | 
					      if (attrs.has(key)) {
 | 
				
			||||||
@ -424,8 +422,7 @@ export const cleanupYTextFormatting = type => {
 | 
				
			|||||||
          case ContentFormat:
 | 
					          case ContentFormat:
 | 
				
			||||||
            updateCurrentAttributes(currentAttributes, /** @type {ContentFormat} */ (end.content))
 | 
					            updateCurrentAttributes(currentAttributes, /** @type {ContentFormat} */ (end.content))
 | 
				
			||||||
            break
 | 
					            break
 | 
				
			||||||
          case ContentEmbed:
 | 
					          default:
 | 
				
			||||||
          case ContentString:
 | 
					 | 
				
			||||||
            res += cleanupFormattingGap(transaction, start, end, startAttributes, currentAttributes)
 | 
					            res += cleanupFormattingGap(transaction, start, end, startAttributes, currentAttributes)
 | 
				
			||||||
            startAttributes = map.copy(currentAttributes)
 | 
					            startAttributes = map.copy(currentAttributes)
 | 
				
			||||||
            start = end
 | 
					            start = end
 | 
				
			||||||
@ -454,6 +451,7 @@ const deleteText = (transaction, currPos, length) => {
 | 
				
			|||||||
  while (length > 0 && currPos.right !== null) {
 | 
					  while (length > 0 && currPos.right !== null) {
 | 
				
			||||||
    if (currPos.right.deleted === false) {
 | 
					    if (currPos.right.deleted === false) {
 | 
				
			||||||
      switch (currPos.right.content.constructor) {
 | 
					      switch (currPos.right.content.constructor) {
 | 
				
			||||||
 | 
					        case ContentType:
 | 
				
			||||||
        case ContentEmbed:
 | 
					        case ContentEmbed:
 | 
				
			||||||
        case ContentString:
 | 
					        case ContentString:
 | 
				
			||||||
          if (length < currPos.right.length) {
 | 
					          if (length < currPos.right.length) {
 | 
				
			||||||
@ -540,7 +538,7 @@ export class YTextEvent extends YEvent {
 | 
				
			|||||||
  get changes () {
 | 
					  get changes () {
 | 
				
			||||||
    if (this._changes === null) {
 | 
					    if (this._changes === null) {
 | 
				
			||||||
      /**
 | 
					      /**
 | 
				
			||||||
       * @type {{added:Set<Item>,deleted:Set<Item>,keys:Map<string,{action:'add'|'update'|'delete',oldValue:any}>,delta:Array<{insert?:Array<any>|string, delete?:number, retain?:number}>}}
 | 
					       * @type {{added:Set<Item>,deleted:Set<Item>,keys:Map<string,{action:'add'|'update'|'delete',oldValue:any}>,delta:Array<{insert?:Array<any>|string|AbstractType<any>|object, delete?:number, retain?:number}>}}
 | 
				
			||||||
       */
 | 
					       */
 | 
				
			||||||
      const changes = {
 | 
					      const changes = {
 | 
				
			||||||
        keys: this.keys,
 | 
					        keys: this.keys,
 | 
				
			||||||
@ -557,7 +555,7 @@ export class YTextEvent extends YEvent {
 | 
				
			|||||||
   * Compute the changes in the delta format.
 | 
					   * Compute the changes in the delta format.
 | 
				
			||||||
   * A {@link https://quilljs.com/docs/delta/|Quill Delta}) that represents the changes on the document.
 | 
					   * A {@link https://quilljs.com/docs/delta/|Quill Delta}) that represents the changes on the document.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * @type {Array<{insert?:string, delete?:number, retain?:number, attributes?: Object<string,any>}>}
 | 
					   * @type {Array<{insert?:string|object|AbstractType<any>, delete?:number, retain?:number, attributes?: Object<string,any>}>}
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * @public
 | 
					   * @public
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
@ -565,7 +563,7 @@ export class YTextEvent extends YEvent {
 | 
				
			|||||||
    if (this._delta === null) {
 | 
					    if (this._delta === null) {
 | 
				
			||||||
      const y = /** @type {Doc} */ (this.target.doc)
 | 
					      const y = /** @type {Doc} */ (this.target.doc)
 | 
				
			||||||
      /**
 | 
					      /**
 | 
				
			||||||
       * @type {Array<{insert?:string, delete?:number, retain?:number, attributes?: Object<string,any>}>}
 | 
					       * @type {Array<{insert?:string|object|AbstractType<any>, delete?:number, retain?:number, attributes?: Object<string,any>}>}
 | 
				
			||||||
       */
 | 
					       */
 | 
				
			||||||
      const delta = []
 | 
					      const delta = []
 | 
				
			||||||
      transact(y, transaction => {
 | 
					      transact(y, transaction => {
 | 
				
			||||||
@ -626,12 +624,13 @@ export class YTextEvent extends YEvent {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        while (item !== null) {
 | 
					        while (item !== null) {
 | 
				
			||||||
          switch (item.content.constructor) {
 | 
					          switch (item.content.constructor) {
 | 
				
			||||||
 | 
					            case ContentType:
 | 
				
			||||||
            case ContentEmbed:
 | 
					            case ContentEmbed:
 | 
				
			||||||
              if (this.adds(item)) {
 | 
					              if (this.adds(item)) {
 | 
				
			||||||
                if (!this.deletes(item)) {
 | 
					                if (!this.deletes(item)) {
 | 
				
			||||||
                  addOp()
 | 
					                  addOp()
 | 
				
			||||||
                  action = 'insert'
 | 
					                  action = 'insert'
 | 
				
			||||||
                  insert = /** @type {ContentEmbed} */ (item.content).embed
 | 
					                  insert = item.content.getContent()[0]
 | 
				
			||||||
                  addOp()
 | 
					                  addOp()
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
              } else if (this.deletes(item)) {
 | 
					              } else if (this.deletes(item)) {
 | 
				
			||||||
@ -1008,13 +1007,14 @@ export class YText extends AbstractType {
 | 
				
			|||||||
              str += /** @type {ContentString} */ (n.content).str
 | 
					              str += /** @type {ContentString} */ (n.content).str
 | 
				
			||||||
              break
 | 
					              break
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            case ContentType:
 | 
				
			||||||
            case ContentEmbed: {
 | 
					            case ContentEmbed: {
 | 
				
			||||||
              packStr()
 | 
					              packStr()
 | 
				
			||||||
              /**
 | 
					              /**
 | 
				
			||||||
               * @type {Object<string,any>}
 | 
					               * @type {Object<string,any>}
 | 
				
			||||||
               */
 | 
					               */
 | 
				
			||||||
              const op = {
 | 
					              const op = {
 | 
				
			||||||
                insert: /** @type {ContentEmbed} */ (n.content).embed
 | 
					                insert: n.content.getContent()[0]
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
              if (currentAttributes.size > 0) {
 | 
					              if (currentAttributes.size > 0) {
 | 
				
			||||||
                const attrs = /** @type {Object<string,any>} */ ({})
 | 
					                const attrs = /** @type {Object<string,any>} */ ({})
 | 
				
			||||||
@ -1075,16 +1075,13 @@ export class YText extends AbstractType {
 | 
				
			|||||||
   * Inserts an embed at a index.
 | 
					   * Inserts an embed at a index.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * @param {number} index The index to insert the embed at.
 | 
					   * @param {number} index The index to insert the embed at.
 | 
				
			||||||
   * @param {Object} embed The Object that represents the embed.
 | 
					   * @param {Object | AbstractType<any>} embed The Object that represents the embed.
 | 
				
			||||||
   * @param {TextAttributes} attributes Attribute information to apply on the
 | 
					   * @param {TextAttributes} attributes Attribute information to apply on the
 | 
				
			||||||
   *                                    embed
 | 
					   *                                    embed
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * @public
 | 
					   * @public
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  insertEmbed (index, embed, attributes = {}) {
 | 
					  insertEmbed (index, embed, attributes = {}) {
 | 
				
			||||||
    if (embed.constructor !== Object) {
 | 
					 | 
				
			||||||
      throw new Error('Embed must be an Object')
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    const y = this.doc
 | 
					    const y = this.doc
 | 
				
			||||||
    if (y !== null) {
 | 
					    if (y !== null) {
 | 
				
			||||||
      transact(y, transaction => {
 | 
					      transact(y, transaction => {
 | 
				
			||||||
 | 
				
			|||||||
@ -40,7 +40,7 @@ export class YEvent {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    this._keys = null
 | 
					    this._keys = null
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @type {null | Array<{ insert?: string | Array<any>, retain?: number, delete?: number, attributes?: Object<string, any> }>}
 | 
					     * @type {null | Array<{ insert?: string | Array<any> | object | AbstractType<any>, retain?: number, delete?: number, attributes?: Object<string, any> }>}
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    this._delta = null
 | 
					    this._delta = null
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -129,7 +129,7 @@ export class YEvent {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * @type {Array<{insert?: string | Array<any>, retain?: number, delete?: number, attributes?: Object<string, any>}>}
 | 
					   * @type {Array<{insert?: string | Array<any> | object | AbstractType<any>, retain?: number, delete?: number, attributes?: Object<string, any>}>}
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  get delta () {
 | 
					  get delta () {
 | 
				
			||||||
    return this.changes.delta
 | 
					    return this.changes.delta
 | 
				
			||||||
 | 
				
			|||||||
@ -362,7 +362,14 @@ export const compare = users => {
 | 
				
			|||||||
    t.compare(userMapValues[i], userMapValues[i + 1])
 | 
					    t.compare(userMapValues[i], userMapValues[i + 1])
 | 
				
			||||||
    t.compare(userXmlValues[i], userXmlValues[i + 1])
 | 
					    t.compare(userXmlValues[i], userXmlValues[i + 1])
 | 
				
			||||||
    t.compare(userTextValues[i].map(/** @param {any} a */ a => typeof a.insert === 'string' ? a.insert : ' ').join('').length, users[i].getText('text').length)
 | 
					    t.compare(userTextValues[i].map(/** @param {any} a */ a => typeof a.insert === 'string' ? a.insert : ' ').join('').length, users[i].getText('text').length)
 | 
				
			||||||
    t.compare(userTextValues[i], userTextValues[i + 1])
 | 
					    t.compare(userTextValues[i], userTextValues[i + 1], '', (constructor, a, b) => {
 | 
				
			||||||
 | 
					      if (a instanceof Y.AbstractType) {
 | 
				
			||||||
 | 
					        t.compare(a.toJSON(), b.toJSON())
 | 
				
			||||||
 | 
					      } else if (a !== b) {
 | 
				
			||||||
 | 
					        t.fail('Deltas dont match')
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return true
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
    t.compare(Y.getStateVector(users[i].store), Y.getStateVector(users[i + 1].store))
 | 
					    t.compare(Y.getStateVector(users[i].store), Y.getStateVector(users[i + 1].store))
 | 
				
			||||||
    compareDS(Y.createDeleteSetFromStructStore(users[i].store), Y.createDeleteSetFromStructStore(users[i + 1].store))
 | 
					    compareDS(Y.createDeleteSetFromStructStore(users[i].store), Y.createDeleteSetFromStructStore(users[i + 1].store))
 | 
				
			||||||
    compareStructStores(users[i].store, users[i + 1].store)
 | 
					    compareStructStores(users[i].store, users[i + 1].store)
 | 
				
			||||||
 | 
				
			|||||||
@ -151,6 +151,29 @@ export const testGetDeltaWithEmbeds = tc => {
 | 
				
			|||||||
  }])
 | 
					  }])
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @param {t.TestCase} tc
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const testTypesAsEmbed = tc => {
 | 
				
			||||||
 | 
					  const { text0, text1, testConnector } = init(tc, { users: 2 })
 | 
				
			||||||
 | 
					  text0.applyDelta([{
 | 
				
			||||||
 | 
					    insert: new Y.YMap([['key', 'val']])
 | 
				
			||||||
 | 
					  }])
 | 
				
			||||||
 | 
					  t.compare(text0.toDelta()[0].insert.toJSON(), { key: 'val' })
 | 
				
			||||||
 | 
					  let firedEvent = false
 | 
				
			||||||
 | 
					  text1.observe(event => {
 | 
				
			||||||
 | 
					    const d = event.delta
 | 
				
			||||||
 | 
					    t.assert(d.length === 1)
 | 
				
			||||||
 | 
					    t.compare(d.map(x => /** @type {Y.AbstractType<any>} */ (x.insert).toJSON()), [{ key: 'val' }])
 | 
				
			||||||
 | 
					    firedEvent = true
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					  testConnector.flushAllMessages()
 | 
				
			||||||
 | 
					  const delta = text1.toDelta()
 | 
				
			||||||
 | 
					  t.assert(delta.length === 1)
 | 
				
			||||||
 | 
					  t.compare(delta[0].insert.toJSON(), { key: 'val' })
 | 
				
			||||||
 | 
					  t.assert(firedEvent, 'fired the event observer containing a Type-Embed')
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @param {t.TestCase} tc
 | 
					 * @param {t.TestCase} tc
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -628,7 +651,11 @@ const qChanges = [
 | 
				
			|||||||
  (y, gen) => { // insert embed
 | 
					  (y, gen) => { // insert embed
 | 
				
			||||||
    const ytext = y.getText('text')
 | 
					    const ytext = y.getText('text')
 | 
				
			||||||
    const insertPos = prng.int32(gen, 0, ytext.length)
 | 
					    const insertPos = prng.int32(gen, 0, ytext.length)
 | 
				
			||||||
 | 
					    if (prng.bool(gen)) {
 | 
				
			||||||
      ytext.insertEmbed(insertPos, { image: 'https://user-images.githubusercontent.com/5553757/48975307-61efb100-f06d-11e8-9177-ee895e5916e5.png' })
 | 
					      ytext.insertEmbed(insertPos, { image: 'https://user-images.githubusercontent.com/5553757/48975307-61efb100-f06d-11e8-9177-ee895e5916e5.png' })
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      ytext.insertEmbed(insertPos, new Y.YMap([[prng.word(gen), prng.word(gen)]]))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * @param {Y.Doc} y
 | 
					   * @param {Y.Doc} y
 | 
				
			||||||
@ -675,8 +702,12 @@ const qChanges = [
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
const checkResult = result => {
 | 
					const checkResult = result => {
 | 
				
			||||||
  for (let i = 1; i < result.testObjects.length; i++) {
 | 
					  for (let i = 1; i < result.testObjects.length; i++) {
 | 
				
			||||||
    const p1 = result.users[i].getText('text').toDelta()
 | 
					    /**
 | 
				
			||||||
    const p2 = result.users[i].getText('text').toDelta()
 | 
					     * @param {any} d
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    const typeToObject = d => d.insert instanceof Y.AbstractType ? d.insert.toJSON() : d
 | 
				
			||||||
 | 
					    const p1 = result.users[i].getText('text').toDelta().map(typeToObject)
 | 
				
			||||||
 | 
					    const p2 = result.users[i].getText('text').toDelta().map(typeToObject)
 | 
				
			||||||
    t.compare(p1, p2)
 | 
					    t.compare(p1, p2)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  // Uncomment this to find formatting-cleanup issues
 | 
					  // Uncomment this to find formatting-cleanup issues
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user