large scale refactoring
This commit is contained in:
		
							parent
							
								
									ade3e1949d
								
							
						
					
					
						commit
						9c0da271eb
					
				@ -1,6 +1,7 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "source": "./src",
 | 
					  "source": ".",
 | 
				
			||||||
  "destination": "./docs",
 | 
					  "destination": "./docs",
 | 
				
			||||||
 | 
					  "excludes": ["build", "node_modules", "tests-lib", "test"],
 | 
				
			||||||
  "plugins": [{
 | 
					  "plugins": [{
 | 
				
			||||||
    "name": "esdoc-standard-plugin",
 | 
					    "name": "esdoc-standard-plugin",
 | 
				
			||||||
    "option": {
 | 
					    "option": {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										51
									
								
								.jsdoc.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								.jsdoc.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "sourceType": "module",
 | 
				
			||||||
 | 
					  "tags": {
 | 
				
			||||||
 | 
					    "allowUnknownTags": true,
 | 
				
			||||||
 | 
					    "dictionaries": ["jsdoc"]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "source": {
 | 
				
			||||||
 | 
					    "include": ["types", "utils/UndoManager.js", "utils/Y.js", "provider", "bindings"],
 | 
				
			||||||
 | 
					    "includePattern": ".js$",
 | 
				
			||||||
 | 
					    "excludePattern": "(node_modules/|docs|build|examples)"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "plugins": [
 | 
				
			||||||
 | 
					    "plugins/markdown"
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  "templates": {
 | 
				
			||||||
 | 
					    "referenceTitle": "Yjs",
 | 
				
			||||||
 | 
					    "disableSort": false,
 | 
				
			||||||
 | 
					    "useCollapsibles": true,
 | 
				
			||||||
 | 
					    "collapse": true,
 | 
				
			||||||
 | 
					    "resources": {
 | 
				
			||||||
 | 
					      "y-js.org": "y-js.org"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "logo": {
 | 
				
			||||||
 | 
					      "url": "http://y-js.org/images/yjs.png",
 | 
				
			||||||
 | 
					      "width": "162px",
 | 
				
			||||||
 | 
					      "height": "162px",
 | 
				
			||||||
 | 
					      "link": "/"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "tabNames": {
 | 
				
			||||||
 | 
					      "api": "API",
 | 
				
			||||||
 | 
					      "tutorials": "Examples"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "footerText": "Shared Editing",
 | 
				
			||||||
 | 
					    "css": [
 | 
				
			||||||
 | 
					      "./style.css"
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    "default": {
 | 
				
			||||||
 | 
					      "staticFiles": {
 | 
				
			||||||
 | 
					          "include": ["examples/"]
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "opts": {
 | 
				
			||||||
 | 
					    "destination": "./docs/",
 | 
				
			||||||
 | 
					    "encoding": "utf8",
 | 
				
			||||||
 | 
					    "private": false,
 | 
				
			||||||
 | 
					    "recurse": true,
 | 
				
			||||||
 | 
					    "template": "./node_modules/tui-jsdoc-template",
 | 
				
			||||||
 | 
					    "tutorials": "./examples"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,47 +0,0 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import { createMutex } from '../lib/mutex.js'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Abstract class for bindings.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * A binding handles data binding from a Yjs type to a data object. For example,
 | 
					 | 
				
			||||||
 * you can bind a Quill editor instance to a YText instance with the `QuillBinding` class.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * It is expected that a concrete implementation accepts two parameters
 | 
					 | 
				
			||||||
 * (type and binding target).
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @example
 | 
					 | 
				
			||||||
 *   const quill = new Quill(document.createElement('div'))
 | 
					 | 
				
			||||||
 *   const type = y.define('quill', Y.Text)
 | 
					 | 
				
			||||||
 *   const binding = new Y.QuillBinding(quill, type)
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
export default class Binding {
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * @param {YType} type Yjs type.
 | 
					 | 
				
			||||||
   * @param {any} target Binding Target.
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  constructor (type, target) {
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * The Yjs type that is bound to `target`
 | 
					 | 
				
			||||||
     * @type {YType}
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    this.type = type
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * The target that `type` is bound to.
 | 
					 | 
				
			||||||
     * @type {*}
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    this.target = target
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * @private
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    this._mutualExclude = createMutex()
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * Remove all data observers (both from the type and the target).
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  destroy () {
 | 
					 | 
				
			||||||
    this.type = null
 | 
					 | 
				
			||||||
    this.target = null
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										1
									
								
								bindings/dom.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								bindings/dom.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					export * from './dom/DomBinding.js'
 | 
				
			||||||
@ -1,15 +1,23 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module bindings/dom
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* global MutationObserver, getSelection */
 | 
					/* global MutationObserver, getSelection */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { fromRelativePosition } from '../../src/Util/relativePosition.js'
 | 
					import { fromRelativePosition } from '../../utils/relativePosition.js'
 | 
				
			||||||
import Binding from '../Binding.js'
 | 
					import { createMutex } from '../../lib/mutex.js'
 | 
				
			||||||
import { createAssociation, removeAssociation } from './util.js'
 | 
					import { createAssociation, removeAssociation } from './util.js'
 | 
				
			||||||
import { beforeTransactionSelectionFixer, afterTransactionSelectionFixer, getCurrentRelativeSelection } from './selection.js'
 | 
					import { beforeTransactionSelectionFixer, afterTransactionSelectionFixer, getCurrentRelativeSelection } from './selection.js'
 | 
				
			||||||
import { defaultFilter, applyFilterOnType } from './filter.js'
 | 
					import { defaultFilter, applyFilterOnType } from './filter.js'
 | 
				
			||||||
import typeObserver from './typeObserver.js'
 | 
					import { typeObserver } from './typeObserver.js'
 | 
				
			||||||
import domObserver from './domObserver.js'
 | 
					import { domObserver } from './domObserver.js'
 | 
				
			||||||
 | 
					import { YXmlFragment } from '../../types/YXmlElement.js' // eslint-disable-line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @typedef {import('./filter.js').DomFilter} DomFilter
 | 
					 * @callback DomFilter
 | 
				
			||||||
 | 
					 * @param {string} nodeName
 | 
				
			||||||
 | 
					 * @param {Map<string, string>} attrs
 | 
				
			||||||
 | 
					 * @return {Map | null}
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -22,8 +30,9 @@ import domObserver from './domObserver.js'
 | 
				
			|||||||
 * const type = y.define('xml', Y.XmlFragment)
 | 
					 * const type = y.define('xml', Y.XmlFragment)
 | 
				
			||||||
 * const binding = new Y.QuillBinding(type, div)
 | 
					 * const binding = new Y.QuillBinding(type, div)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @class
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export default class DomBinding extends Binding {
 | 
					export class DomBinding {
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * @param {YXmlFragment} type The bind source. This is the ultimate source of
 | 
					   * @param {YXmlFragment} type The bind source. This is the ultimate source of
 | 
				
			||||||
   *                            truth.
 | 
					   *                            truth.
 | 
				
			||||||
@ -31,10 +40,26 @@ export default class DomBinding extends Binding {
 | 
				
			|||||||
   * @param {Object} [opts] Optional configurations
 | 
					   * @param {Object} [opts] Optional configurations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   * @param {DomFilter} [opts.filter=defaultFilter] The filter function to use.
 | 
					   * @param {DomFilter} [opts.filter=defaultFilter] The filter function to use.
 | 
				
			||||||
 | 
					   * @param {Document} [opts.document=document] The filter function to use.
 | 
				
			||||||
 | 
					   * @param {Object} [opts.hooks] The filter function to use.
 | 
				
			||||||
 | 
					   * @param {Element} [opts.scrollingElement=null] The filter function to use.
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  constructor (type, target, opts = {}) {
 | 
					  constructor (type, target, opts = {}) {
 | 
				
			||||||
    // Binding handles textType as this.type and domTextarea as this.target
 | 
					    // Binding handles textType as this.type and domTextarea as this.target
 | 
				
			||||||
    super(type, target)
 | 
					    /**
 | 
				
			||||||
 | 
					     * The Yjs type that is bound to `target`
 | 
				
			||||||
 | 
					     * @type {YXmlFragment}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    this.type = type
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The target that `type` is bound to.
 | 
				
			||||||
 | 
					     * @type {Element}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    this.target = target
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @private
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    this._mutualExclude = createMutex()
 | 
				
			||||||
    this.opts = opts
 | 
					    this.opts = opts
 | 
				
			||||||
    opts.document = opts.document || document
 | 
					    opts.document = opts.document || document
 | 
				
			||||||
    opts.hooks = opts.hooks || {}
 | 
					    opts.hooks = opts.hooks || {}
 | 
				
			||||||
@ -81,16 +106,16 @@ export default class DomBinding extends Binding {
 | 
				
			|||||||
    this.y = y
 | 
					    this.y = y
 | 
				
			||||||
    // Force flush dom changes before Type changes are applied (they might
 | 
					    // Force flush dom changes before Type changes are applied (they might
 | 
				
			||||||
    // modify the dom)
 | 
					    // modify the dom)
 | 
				
			||||||
    this._beforeTransactionHandler = (y, transaction, remote) => {
 | 
					    this._beforeTransactionHandler = y => {
 | 
				
			||||||
      this._domObserver(this._mutationObserver.takeRecords())
 | 
					      this._domObserver(this._mutationObserver.takeRecords())
 | 
				
			||||||
      this._mutualExclude(() => {
 | 
					      this._mutualExclude(() => {
 | 
				
			||||||
        beforeTransactionSelectionFixer(this, remote)
 | 
					        beforeTransactionSelectionFixer(this)
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    y.on('beforeTransaction', this._beforeTransactionHandler)
 | 
					    y.on('beforeTransaction', this._beforeTransactionHandler)
 | 
				
			||||||
    this._afterTransactionHandler = (y, transaction, remote) => {
 | 
					    this._afterTransactionHandler = (y, transaction) => {
 | 
				
			||||||
      this._mutualExclude(() => {
 | 
					      this._mutualExclude(() => {
 | 
				
			||||||
        afterTransactionSelectionFixer(this, remote)
 | 
					        afterTransactionSelectionFixer(this)
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
      // remove associations
 | 
					      // remove associations
 | 
				
			||||||
      // TODO: this could be done more efficiently
 | 
					      // TODO: this could be done more efficiently
 | 
				
			||||||
@ -206,13 +231,18 @@ export default class DomBinding extends Binding {
 | 
				
			|||||||
    y.off('beforeObserverCalls', this._beforeObserverCallsHandler)
 | 
					    y.off('beforeObserverCalls', this._beforeObserverCallsHandler)
 | 
				
			||||||
    y.off('afterTransaction', this._afterTransactionHandler)
 | 
					    y.off('afterTransaction', this._afterTransactionHandler)
 | 
				
			||||||
    document.removeEventListener('selectionchange', this._selectionchange)
 | 
					    document.removeEventListener('selectionchange', this._selectionchange)
 | 
				
			||||||
    super.destroy()
 | 
					    this.type = null
 | 
				
			||||||
 | 
					    this.target = null
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * A filter defines which elements and attributes to share.
 | 
					 * A filter defines which elements and attributes to share.
 | 
				
			||||||
 * Return null if the node should be filtered. Otherwise return the Map of
 | 
					 * Return null if the node should be filtered. Otherwise return the Map of
 | 
				
			||||||
 * accepted attributes.
 | 
					 * accepted attributes.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @typedef {function(nodeName: String, attrs: Map): Map|null} FilterFunction
 | 
					 * @callback FilterFunction
 | 
				
			||||||
 | 
					 * @param {string} nodeName
 | 
				
			||||||
 | 
					 * @param {Map} attrs
 | 
				
			||||||
 | 
					 * @return {Map|null}
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -1,11 +1,14 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module bindings/dom
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import YXmlHook from '../../src/Types/YXml/YXmlHook.js'
 | 
					import { YXmlHook } from '../../types/YXmlHook.js'
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  iterateUntilUndeleted,
 | 
					  iterateUntilUndeleted,
 | 
				
			||||||
  removeAssociation,
 | 
					  removeAssociation,
 | 
				
			||||||
  insertNodeHelper } from './util.js'
 | 
					  insertNodeHelper } from './util.js'
 | 
				
			||||||
import diff from '../../lib/simpleDiff.js'
 | 
					import { simpleDiff } from '../../lib/diff.js'
 | 
				
			||||||
import YXmlFragment from '../../src/Types/YXml/YXmlFragment.js'
 | 
					import { YXmlFragment } from '../../types/YXmlElement.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * 1. Check if any of the nodes was deleted
 | 
					 * 1. Check if any of the nodes was deleted
 | 
				
			||||||
@ -19,7 +22,7 @@ import YXmlFragment from '../../src/Types/YXml/YXmlFragment.js'
 | 
				
			|||||||
 *       !== actualId in the list
 | 
					 *       !== actualId in the list
 | 
				
			||||||
 * @private
 | 
					 * @private
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function applyChangesFromDom (binding, dom, yxml, _document) {
 | 
					const applyChangesFromDom = (binding, dom, yxml, _document) => {
 | 
				
			||||||
  if (yxml == null || yxml === false || yxml.constructor === YXmlHook) {
 | 
					  if (yxml == null || yxml === false || yxml.constructor === YXmlHook) {
 | 
				
			||||||
    return
 | 
					    return
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -32,7 +35,7 @@ function applyChangesFromDom (binding, dom, yxml, _document) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  // 1. Check if any of the nodes was deleted
 | 
					  // 1. Check if any of the nodes was deleted
 | 
				
			||||||
  yxml.forEach(function (childType) {
 | 
					  yxml.forEach(childType => {
 | 
				
			||||||
    if (knownChildren.has(childType) === false) {
 | 
					    if (knownChildren.has(childType) === false) {
 | 
				
			||||||
      childType._delete(y)
 | 
					      childType._delete(y)
 | 
				
			||||||
      removeAssociation(binding, binding.typeToDom.get(childType), childType)
 | 
					      removeAssociation(binding, binding.typeToDom.get(childType), childType)
 | 
				
			||||||
@ -83,7 +86,7 @@ function applyChangesFromDom (binding, dom, yxml, _document) {
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * @private
 | 
					 * @private
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export default function domObserver (mutations, _document) {
 | 
					export function domObserver (mutations, _document) {
 | 
				
			||||||
  this._mutualExclude(() => {
 | 
					  this._mutualExclude(() => {
 | 
				
			||||||
    this.type._y.transact(() => {
 | 
					    this.type._y.transact(() => {
 | 
				
			||||||
      let diffChildren = new Set()
 | 
					      let diffChildren = new Set()
 | 
				
			||||||
@ -107,7 +110,7 @@ export default function domObserver (mutations, _document) {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        switch (mutation.type) {
 | 
					        switch (mutation.type) {
 | 
				
			||||||
          case 'characterData':
 | 
					          case 'characterData':
 | 
				
			||||||
            var change = diff(yxml.toString(), dom.nodeValue)
 | 
					            var change = simpleDiff(yxml.toString(), dom.nodeValue)
 | 
				
			||||||
            yxml.delete(change.pos, change.remove)
 | 
					            yxml.delete(change.pos, change.remove)
 | 
				
			||||||
            yxml.insert(change.pos, change.insert)
 | 
					            yxml.insert(change.pos, change.insert)
 | 
				
			||||||
            break
 | 
					            break
 | 
				
			||||||
@ -1,13 +1,20 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module bindings/dom
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* eslint-env browser */
 | 
					/* eslint-env browser */
 | 
				
			||||||
import YXmlText from '../../src/Types/YXml/YXmlText.js'
 | 
					import { YXmlText } from '../../types/YXmlText.js'
 | 
				
			||||||
import YXmlHook from '../../src/Types/YXml/YXmlHook.js'
 | 
					import { YXmlHook } from '../../types/YXmlHook.js'
 | 
				
			||||||
import YXmlElement from '../../src/Types/YXml/YXmlElement.js'
 | 
					import { YXmlElement } from '../../types/YXmlElement.js'
 | 
				
			||||||
import { createAssociation, domsToTypes } from './util.js'
 | 
					import { createAssociation, domsToTypes } from './util.js'
 | 
				
			||||||
import { filterDomAttributes, defaultFilter } from './filter.js'
 | 
					import { filterDomAttributes, defaultFilter } from './filter.js'
 | 
				
			||||||
 | 
					import { DomBinding } from './DomBinding.js' // eslint-disable-line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @typedef {import('./filter.js').DomFilter} DomFilter
 | 
					 * @callback DomFilter
 | 
				
			||||||
 * @typedef {import('./DomBinding.js').default} DomBinding
 | 
					 * @param {string} nodeName
 | 
				
			||||||
 | 
					 * @param {Map<string, string>} attrs
 | 
				
			||||||
 | 
					 * @return {Map | null}
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -20,7 +27,7 @@ import { filterDomAttributes, defaultFilter } from './filter.js'
 | 
				
			|||||||
 * @param {?DomBinding} binding Warning: This property is for internal use only!
 | 
					 * @param {?DomBinding} binding Warning: This property is for internal use only!
 | 
				
			||||||
 * @return {YXmlElement | YXmlText | false}
 | 
					 * @return {YXmlElement | YXmlText | false}
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export default function domToType (element, _document = document, hooks = {}, filter = defaultFilter, binding) {
 | 
					export const domToType = (element, _document = document, hooks = {}, filter = defaultFilter, binding) => {
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * @type {any}
 | 
					   * @type {any}
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
@ -1,12 +1,11 @@
 | 
				
			|||||||
import isParentOf from '../../src/Util/isParentOf.js'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @callback DomFilter
 | 
					 * @module bindings/dom
 | 
				
			||||||
 * @param {string} nodeName
 | 
					 | 
				
			||||||
 * @param {Map<string, string>} attrs
 | 
					 | 
				
			||||||
 * @return {Map | null}
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { isParentOf } from '../../utils/isParentOf.js'
 | 
				
			||||||
 | 
					import * as Y from '../../index.js'
 | 
				
			||||||
 | 
					import { DomBinding } from './DomBinding.js' // eslint-disable-line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Default filter method (does nothing).
 | 
					 * Default filter method (does nothing).
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@ -15,7 +14,7 @@ import isParentOf from '../../src/Util/isParentOf.js'
 | 
				
			|||||||
 * @return {Map | null} The allowed attributes or null, if the element should be
 | 
					 * @return {Map | null} The allowed attributes or null, if the element should be
 | 
				
			||||||
 *                      filtered.
 | 
					 *                      filtered.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function defaultFilter (nodeName, attrs) {
 | 
					export const defaultFilter = (nodeName, attrs) => {
 | 
				
			||||||
  // TODO: implement basic filter that filters out dangerous properties!
 | 
					  // TODO: implement basic filter that filters out dangerous properties!
 | 
				
			||||||
  return attrs
 | 
					  return attrs
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -23,7 +22,7 @@ export function defaultFilter (nodeName, attrs) {
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function filterDomAttributes (dom, filter) {
 | 
					export const filterDomAttributes = (dom, filter) => {
 | 
				
			||||||
  const attrs = new Map()
 | 
					  const attrs = new Map()
 | 
				
			||||||
  for (let i = dom.attributes.length - 1; i >= 0; i--) {
 | 
					  for (let i = dom.attributes.length - 1; i >= 0; i--) {
 | 
				
			||||||
    const attr = dom.attributes[i]
 | 
					    const attr = dom.attributes[i]
 | 
				
			||||||
@ -35,14 +34,14 @@ export function filterDomAttributes (dom, filter) {
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Applies a filter on a type.
 | 
					 * Applies a filter on a type.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param {Y} y The Yjs instance.
 | 
					 * @param {Y.Y} y The Yjs instance.
 | 
				
			||||||
 * @param {DomBinding} binding The DOM binding instance that has the dom filter.
 | 
					 * @param {DomBinding} binding The DOM binding instance that has the dom filter.
 | 
				
			||||||
 * @param {YXmlElement | YXmlFragment } type The type to apply the filter to.
 | 
					 * @param {Y.XmlElement | Y.XmlFragment } type The type to apply the filter to.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @private
 | 
					 * @private
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function applyFilterOnType (y, binding, type) {
 | 
					export const applyFilterOnType = (y, binding, type) => {
 | 
				
			||||||
  if (isParentOf(binding.type, type)) {
 | 
					  if (isParentOf(binding.type, type) && type instanceof Y.XmlElement) {
 | 
				
			||||||
    const nodeName = type.nodeName
 | 
					    const nodeName = type.nodeName
 | 
				
			||||||
    let attributes = new Map()
 | 
					    let attributes = new Map()
 | 
				
			||||||
    if (type.getAttributes !== undefined) {
 | 
					    if (type.getAttributes !== undefined) {
 | 
				
			||||||
@ -53,7 +52,7 @@ export function applyFilterOnType (y, binding, type) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    const filteredAttributes = binding.filter(nodeName, new Map(attributes))
 | 
					    const filteredAttributes = binding.filter(nodeName, new Map(attributes))
 | 
				
			||||||
    if (filteredAttributes === null) {
 | 
					    if (filteredAttributes === null) {
 | 
				
			||||||
      type._delete(y)
 | 
					      type._delete(y, true)
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      // iterate original attributes
 | 
					      // iterate original attributes
 | 
				
			||||||
      attributes.forEach((value, key) => {
 | 
					      attributes.forEach((value, key) => {
 | 
				
			||||||
@ -1,10 +1,14 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module bindings/dom
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* globals getSelection */
 | 
					/* globals getSelection */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { getRelativePosition } from '../../src/Util/relativePosition.js'
 | 
					import { getRelativePosition } from '../../utils/relativePosition.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let relativeSelection = null
 | 
					let relativeSelection = null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function _getCurrentRelativeSelection (domBinding) {
 | 
					const _getCurrentRelativeSelection = domBinding => {
 | 
				
			||||||
  const { baseNode, baseOffset, extentNode, extentOffset } = getSelection()
 | 
					  const { baseNode, baseOffset, extentNode, extentOffset } = getSelection()
 | 
				
			||||||
  const baseNodeType = domBinding.domToType.get(baseNode)
 | 
					  const baseNodeType = domBinding.domToType.get(baseNode)
 | 
				
			||||||
  const extentNodeType = domBinding.domToType.get(extentNode)
 | 
					  const extentNodeType = domBinding.domToType.get(extentNode)
 | 
				
			||||||
@ -19,7 +23,7 @@ function _getCurrentRelativeSelection (domBinding) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export const getCurrentRelativeSelection = typeof getSelection !== 'undefined' ? _getCurrentRelativeSelection : domBinding => null
 | 
					export const getCurrentRelativeSelection = typeof getSelection !== 'undefined' ? _getCurrentRelativeSelection : domBinding => null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function beforeTransactionSelectionFixer (domBinding) {
 | 
					export const beforeTransactionSelectionFixer = domBinding => {
 | 
				
			||||||
  relativeSelection = getCurrentRelativeSelection(domBinding)
 | 
					  relativeSelection = getCurrentRelativeSelection(domBinding)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -28,7 +32,7 @@ export function beforeTransactionSelectionFixer (domBinding) {
 | 
				
			|||||||
 * This prevents any collapsing issues with the local selection.
 | 
					 * This prevents any collapsing issues with the local selection.
 | 
				
			||||||
 * @private
 | 
					 * @private
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function afterTransactionSelectionFixer (domBinding) {
 | 
					export const afterTransactionSelectionFixer = domBinding => {
 | 
				
			||||||
  if (relativeSelection !== null) {
 | 
					  if (relativeSelection !== null) {
 | 
				
			||||||
    domBinding.restoreSelection(relativeSelection)
 | 
					    domBinding.restoreSelection(relativeSelection)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -1,11 +1,15 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module bindings/dom
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* eslint-env browser */
 | 
					/* eslint-env browser */
 | 
				
			||||||
/* global getSelection */
 | 
					/* global getSelection */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import YXmlText from '../../src/Types/YXml/YXmlText.js'
 | 
					import { YXmlText } from '../../types/YXmlText.js'
 | 
				
			||||||
import YXmlHook from '../../src/Types/YXml/YXmlHook.js'
 | 
					import { YXmlHook } from '../../types/YXmlHook.js'
 | 
				
			||||||
import { removeDomChildrenUntilElementFound } from './util.js'
 | 
					import { removeDomChildrenUntilElementFound } from './util.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function findScrollReference (scrollingElement) {
 | 
					const findScrollReference = scrollingElement => {
 | 
				
			||||||
  if (scrollingElement !== null) {
 | 
					  if (scrollingElement !== null) {
 | 
				
			||||||
    let anchor = getSelection().anchorNode
 | 
					    let anchor = getSelection().anchorNode
 | 
				
			||||||
    if (anchor == null) {
 | 
					    if (anchor == null) {
 | 
				
			||||||
@ -34,7 +38,7 @@ function findScrollReference (scrollingElement) {
 | 
				
			|||||||
  return null
 | 
					  return null
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function fixScroll (scrollingElement, ref) {
 | 
					const fixScroll = (scrollingElement, ref) => {
 | 
				
			||||||
  if (ref !== null) {
 | 
					  if (ref !== null) {
 | 
				
			||||||
    const { elem, top } = ref
 | 
					    const { elem, top } = ref
 | 
				
			||||||
    const currentTop = elem.getBoundingClientRect().top
 | 
					    const currentTop = elem.getBoundingClientRect().top
 | 
				
			||||||
@ -48,7 +52,7 @@ function fixScroll (scrollingElement, ref) {
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * @private
 | 
					 * @private
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export default function typeObserver (events) {
 | 
					export const typeObserver = function (events) {
 | 
				
			||||||
  this._mutualExclude(() => {
 | 
					  this._mutualExclude(() => {
 | 
				
			||||||
    const scrollRef = findScrollReference(this.scrollingElement)
 | 
					    const scrollRef = findScrollReference(this.scrollingElement)
 | 
				
			||||||
    events.forEach(event => {
 | 
					    events.forEach(event => {
 | 
				
			||||||
@ -1,19 +1,19 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import domToType from './domToType.js'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @typedef {import('../../src/Types/YXml/YXmlText.js').default} YXmlText
 | 
					 * @module bindings/dom
 | 
				
			||||||
 * @typedef {import('../../src/Types/YXml/YXmlElement.js').default} YXmlElement
 | 
					 | 
				
			||||||
 * @typedef {import('../../src/Types/YXml/YXmlHook.js').default} YXmlHook
 | 
					 | 
				
			||||||
 * @typedef {import('./DomBinding.js').default} DomBinding
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { domToType } from './domToType.js'
 | 
				
			||||||
 | 
					import { DomBinding } from './DomBinding.js' // eslint-disable-line
 | 
				
			||||||
 | 
					import { YXmlHook } from '../../types/YXmlHook.js' // eslint-disable-line
 | 
				
			||||||
 | 
					import { YXmlText } from '../../types/YXmlText.js' // eslint-disable-line
 | 
				
			||||||
 | 
					import { YXmlElement, YXmlFragment } from '../../types/YXmlElement.js' // eslint-disable-line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Iterates items until an undeleted item is found.
 | 
					 * Iterates items until an undeleted item is found.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @private
 | 
					 * @private
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function iterateUntilUndeleted (item) {
 | 
					export const iterateUntilUndeleted = item => {
 | 
				
			||||||
  while (item !== null && item._deleted) {
 | 
					  while (item !== null && item._deleted) {
 | 
				
			||||||
    item = item._right
 | 
					    item = item._right
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -24,12 +24,13 @@ export function iterateUntilUndeleted (item) {
 | 
				
			|||||||
 * Removes an association (the information that a DOM element belongs to a
 | 
					 * Removes an association (the information that a DOM element belongs to a
 | 
				
			||||||
 * type).
 | 
					 * type).
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @private
 | 
				
			||||||
 * @param {DomBinding} domBinding The binding object
 | 
					 * @param {DomBinding} domBinding The binding object
 | 
				
			||||||
 * @param {Element} dom The dom that is to be associated with type
 | 
					 * @param {Element} dom The dom that is to be associated with type
 | 
				
			||||||
 * @param {YXmlElement|YXmlHook} type The type that is to be associated with dom
 | 
					 * @param {YXmlElement|YXmlHook} type The type that is to be associated with dom
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function removeAssociation (domBinding, dom, type) {
 | 
					export const removeAssociation = (domBinding, dom, type) => {
 | 
				
			||||||
  domBinding.domToType.delete(dom)
 | 
					  domBinding.domToType.delete(dom)
 | 
				
			||||||
  domBinding.typeToDom.delete(type)
 | 
					  domBinding.typeToDom.delete(type)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -38,12 +39,13 @@ export function removeAssociation (domBinding, dom, type) {
 | 
				
			|||||||
 * Creates an association (the information that a DOM element belongs to a
 | 
					 * Creates an association (the information that a DOM element belongs to a
 | 
				
			||||||
 * type).
 | 
					 * type).
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @private
 | 
				
			||||||
 * @param {DomBinding} domBinding The binding object
 | 
					 * @param {DomBinding} domBinding The binding object
 | 
				
			||||||
 * @param {DocumentFragment|Element|Text} dom The dom that is to be associated with type
 | 
					 * @param {DocumentFragment|Element|Text} dom The dom that is to be associated with type
 | 
				
			||||||
 * @param {YXmlElement|YXmlHook|YXmlText} type The type that is to be associated with dom
 | 
					 * @param {YXmlFragment|YXmlElement|YXmlHook|YXmlText} type The type that is to be associated with dom
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function createAssociation (domBinding, dom, type) {
 | 
					export const createAssociation = (domBinding, dom, type) => {
 | 
				
			||||||
  if (domBinding !== undefined) {
 | 
					  if (domBinding !== undefined) {
 | 
				
			||||||
    domBinding.domToType.set(dom, type)
 | 
					    domBinding.domToType.set(dom, type)
 | 
				
			||||||
    domBinding.typeToDom.set(type, dom)
 | 
					    domBinding.typeToDom.set(type, dom)
 | 
				
			||||||
@ -54,11 +56,12 @@ export function createAssociation (domBinding, dom, type) {
 | 
				
			|||||||
 * If oldDom is associated with a type, associate newDom with the type and
 | 
					 * If oldDom is associated with a type, associate newDom with the type and
 | 
				
			||||||
 * forget about oldDom. If oldDom is not associated with any type, nothing happens.
 | 
					 * forget about oldDom. If oldDom is not associated with any type, nothing happens.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @private
 | 
				
			||||||
 * @param {DomBinding} domBinding The binding object
 | 
					 * @param {DomBinding} domBinding The binding object
 | 
				
			||||||
 * @param {Element} oldDom The existing dom
 | 
					 * @param {Element} oldDom The existing dom
 | 
				
			||||||
 * @param {Element} newDom The new dom object
 | 
					 * @param {Element} newDom The new dom object
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function switchAssociation (domBinding, oldDom, newDom) {
 | 
					export const switchAssociation = (domBinding, oldDom, newDom) => {
 | 
				
			||||||
  if (domBinding !== undefined) {
 | 
					  if (domBinding !== undefined) {
 | 
				
			||||||
    const type = domBinding.domToType.get(oldDom)
 | 
					    const type = domBinding.domToType.get(oldDom)
 | 
				
			||||||
    if (type !== undefined) {
 | 
					    if (type !== undefined) {
 | 
				
			||||||
@ -73,6 +76,7 @@ export function switchAssociation (domBinding, oldDom, newDom) {
 | 
				
			|||||||
 * The Dom elements will be bound to a new YXmlElement and inserted at the
 | 
					 * The Dom elements will be bound to a new YXmlElement and inserted at the
 | 
				
			||||||
 * specified position.
 | 
					 * specified position.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @private
 | 
				
			||||||
 * @param {YXmlElement} type The type in which to insert DOM elements.
 | 
					 * @param {YXmlElement} type The type in which to insert DOM elements.
 | 
				
			||||||
 * @param {YXmlElement|null} prev The reference node. New YxmlElements are
 | 
					 * @param {YXmlElement|null} prev The reference node. New YxmlElements are
 | 
				
			||||||
 *                           inserted after this node. Set null to insert at
 | 
					 *                           inserted after this node. Set null to insert at
 | 
				
			||||||
@ -81,15 +85,13 @@ export function switchAssociation (domBinding, oldDom, newDom) {
 | 
				
			|||||||
 * @param {?Document} _document Optional. Provide the global document object.
 | 
					 * @param {?Document} _document Optional. Provide the global document object.
 | 
				
			||||||
 * @param {DomBinding} binding The dom binding
 | 
					 * @param {DomBinding} binding The dom binding
 | 
				
			||||||
 * @return {Array<YXmlElement>} The YxmlElements that are inserted.
 | 
					 * @return {Array<YXmlElement>} The YxmlElements that are inserted.
 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @private
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function insertDomElementsAfter (type, prev, doms, _document, binding) {
 | 
					export const insertDomElementsAfter = (type, prev, doms, _document, binding) => {
 | 
				
			||||||
  const types = domsToTypes(doms, _document, binding.opts.hooks, binding.filter, binding)
 | 
					  const types = domsToTypes(doms, _document, binding.opts.hooks, binding.filter, binding)
 | 
				
			||||||
  return type.insertAfter(prev, types)
 | 
					  return type.insertAfter(prev, types)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function domsToTypes (doms, _document, hooks, filter, binding) {
 | 
					export const domsToTypes = (doms, _document, hooks, filter, binding) => {
 | 
				
			||||||
  const types = []
 | 
					  const types = []
 | 
				
			||||||
  for (let dom of doms) {
 | 
					  for (let dom of doms) {
 | 
				
			||||||
    const t = domToType(dom, _document, hooks, filter, binding)
 | 
					    const t = domToType(dom, _document, hooks, filter, binding)
 | 
				
			||||||
@ -103,7 +105,7 @@ export function domsToTypes (doms, _document, hooks, filter, binding) {
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * @private
 | 
					 * @private
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function insertNodeHelper (yxml, prevExpectedNode, child, _document, binding) {
 | 
					export const insertNodeHelper = (yxml, prevExpectedNode, child, _document, binding) => {
 | 
				
			||||||
  let insertedNodes = insertDomElementsAfter(yxml, prevExpectedNode, [child], _document, binding)
 | 
					  let insertedNodes = insertDomElementsAfter(yxml, prevExpectedNode, [child], _document, binding)
 | 
				
			||||||
  if (insertedNodes.length > 0) {
 | 
					  if (insertedNodes.length > 0) {
 | 
				
			||||||
    return insertedNodes[0]
 | 
					    return insertedNodes[0]
 | 
				
			||||||
@ -115,14 +117,13 @@ export function insertNodeHelper (yxml, prevExpectedNode, child, _document, bind
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Remove children until `elem` is found.
 | 
					 * Remove children until `elem` is found.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @private
 | 
				
			||||||
 * @param {Element} parent The parent of `elem` and `currentChild`.
 | 
					 * @param {Element} parent The parent of `elem` and `currentChild`.
 | 
				
			||||||
 * @param {Element} currentChild Start removing elements with `currentChild`. If
 | 
					 * @param {Node} currentChild Start removing elements with `currentChild`. If
 | 
				
			||||||
 *                               `currentChild` is `elem` it won't be removed.
 | 
					 *                               `currentChild` is `elem` it won't be removed.
 | 
				
			||||||
 * @param {Element|null} elem The elemnt to look for.
 | 
					 * @param {Element|null} elem The elemnt to look for.
 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @private
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function removeDomChildrenUntilElementFound (parent, currentChild, elem) {
 | 
					export const removeDomChildrenUntilElementFound = (parent, currentChild, elem) => {
 | 
				
			||||||
  while (currentChild !== elem) {
 | 
					  while (currentChild !== elem) {
 | 
				
			||||||
    const del = currentChild
 | 
					    const del = currentChild
 | 
				
			||||||
    currentChild = currentChild.nextSibling
 | 
					    currentChild = currentChild.nextSibling
 | 
				
			||||||
@ -1,7 +1,11 @@
 | 
				
			|||||||
import BindMapping from '../BindMapping.js'
 | 
					/**
 | 
				
			||||||
 | 
					 * @module bindings/prosemirror
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { BindMapping } from '../utils/BindMapping.js'
 | 
				
			||||||
 | 
					import * as Y from '../index.js'
 | 
				
			||||||
 | 
					import { createMutex } from '../lib/mutex.js'
 | 
				
			||||||
import * as PModel from 'prosemirror-model'
 | 
					import * as PModel from 'prosemirror-model'
 | 
				
			||||||
import * as Y from '../../src/index.js'
 | 
					 | 
				
			||||||
import { createMutex } from '../../lib/mutex.js'
 | 
					 | 
				
			||||||
import { Plugin, PluginKey } from 'prosemirror-state'
 | 
					import { Plugin, PluginKey } from 'prosemirror-state'
 | 
				
			||||||
import { Decoration, DecorationSet } from 'prosemirror-view'
 | 
					import { Decoration, DecorationSet } from 'prosemirror-view'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -11,6 +15,11 @@ import { Decoration, DecorationSet } from 'prosemirror-view'
 | 
				
			|||||||
 * @typedef {BindMapping<Y.Text | Y.XmlElement, PModel.Node>} ProsemirrorMapping
 | 
					 * @typedef {BindMapping<Y.Text | Y.XmlElement, PModel.Node>} ProsemirrorMapping
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * The unique prosemirror plugin key for prosemirrorPlugin.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @public
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
export const prosemirrorPluginKey = new PluginKey('yjs')
 | 
					export const prosemirrorPluginKey = new PluginKey('yjs')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -18,6 +27,7 @@ export const prosemirrorPluginKey = new PluginKey('yjs')
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * This plugin also keeps references to the type and the shared document so other plugins can access it.
 | 
					 * This plugin also keeps references to the type and the shared document so other plugins can access it.
 | 
				
			||||||
 * @param {Y.XmlFragment} yXmlFragment
 | 
					 * @param {Y.XmlFragment} yXmlFragment
 | 
				
			||||||
 | 
					 * @return {Plugin} Returns a prosemirror plugin that binds to this type
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const prosemirrorPlugin = yXmlFragment => {
 | 
					export const prosemirrorPlugin = yXmlFragment => {
 | 
				
			||||||
  const pluginState = {
 | 
					  const pluginState = {
 | 
				
			||||||
@ -51,8 +61,19 @@ export const prosemirrorPlugin = yXmlFragment => {
 | 
				
			|||||||
  return plugin
 | 
					  return plugin
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * The unique prosemirror plugin key for cursorPlugin.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @public
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
export const cursorPluginKey = new PluginKey('yjs-cursor')
 | 
					export const cursorPluginKey = new PluginKey('yjs-cursor')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A prosemirror plugin that listens to awareness information on Yjs.
 | 
				
			||||||
 | 
					 * This requires that a `prosemirrorPlugin` is also bound to the prosemirror.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @public
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
export const cursorPlugin = new Plugin({
 | 
					export const cursorPlugin = new Plugin({
 | 
				
			||||||
  key: cursorPluginKey,
 | 
					  key: cursorPluginKey,
 | 
				
			||||||
  props: {
 | 
					  props: {
 | 
				
			||||||
@ -104,7 +125,12 @@ export const cursorPlugin = new Plugin({
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class ProsemirrorBinding {
 | 
					/**
 | 
				
			||||||
 | 
					 * Binding for prosemirror.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @protected
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export class ProsemirrorBinding {
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * @param {Y.XmlFragment} yXmlFragment The bind source
 | 
					   * @param {Y.XmlFragment} yXmlFragment The bind source
 | 
				
			||||||
   * @param {EditorView} prosemirrorView The target binding
 | 
					   * @param {EditorView} prosemirrorView The target binding
 | 
				
			||||||
@ -154,6 +180,7 @@ export default class ProsemirrorBinding {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 | 
					 * @private
 | 
				
			||||||
 * @param {Y.XmlElement} el
 | 
					 * @param {Y.XmlElement} el
 | 
				
			||||||
 * @param {PModel.Schema} schema
 | 
					 * @param {PModel.Schema} schema
 | 
				
			||||||
 * @param {ProsemirrorMapping} mapping
 | 
					 * @param {ProsemirrorMapping} mapping
 | 
				
			||||||
@ -168,6 +195,7 @@ export const createNodeIfNotExists = (el, schema, mapping) => {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 | 
					 * @private
 | 
				
			||||||
 * @param {Y.XmlElement} el
 | 
					 * @param {Y.XmlElement} el
 | 
				
			||||||
 * @param {PModel.Schema} schema
 | 
					 * @param {PModel.Schema} schema
 | 
				
			||||||
 * @param {ProsemirrorMapping} mapping
 | 
					 * @param {ProsemirrorMapping} mapping
 | 
				
			||||||
@ -188,6 +216,7 @@ export const createNodeFromYElement = (el, schema, mapping) => {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 | 
					 * @private
 | 
				
			||||||
 * @param {Y.Text} text
 | 
					 * @param {Y.Text} text
 | 
				
			||||||
 * @param {PModel.Schema} schema
 | 
					 * @param {PModel.Schema} schema
 | 
				
			||||||
 * @param {ProsemirrorMapping} mapping
 | 
					 * @param {ProsemirrorMapping} mapping
 | 
				
			||||||
@ -211,6 +240,7 @@ export const createTextNodesFromYText = (text, schema, mapping) => {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 | 
					 * @private
 | 
				
			||||||
 * @param {PModel.Node} node
 | 
					 * @param {PModel.Node} node
 | 
				
			||||||
 * @param {ProsemirrorMapping} mapping
 | 
					 * @param {ProsemirrorMapping} mapping
 | 
				
			||||||
 * @return {Y.XmlElement | Y.Text}
 | 
					 * @return {Y.XmlElement | Y.Text}
 | 
				
			||||||
@ -234,6 +264,7 @@ export const createTypeFromNode = (node, mapping) => {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 | 
					 * @private
 | 
				
			||||||
 * @param {Y.XmlFragment} yDomFragment
 | 
					 * @param {Y.XmlFragment} yDomFragment
 | 
				
			||||||
 * @param {EditorState} state
 | 
					 * @param {EditorState} state
 | 
				
			||||||
 * @param {BindMapping} mapping
 | 
					 * @param {BindMapping} mapping
 | 
				
			||||||
@ -1,10 +1,14 @@
 | 
				
			|||||||
import Binding from '../Binding.js'
 | 
					/**
 | 
				
			||||||
 | 
					 * @module bindings/quill
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function typeObserver (event) {
 | 
					import { createMutex } from '../lib/mutex.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const typeObserver = function (event) {
 | 
				
			||||||
  const quill = this.target
 | 
					  const quill = this.target
 | 
				
			||||||
  // Force flush Quill changes.
 | 
					  // Force flush Quill changes.
 | 
				
			||||||
  quill.update('yjs')
 | 
					  quill.update('yjs')
 | 
				
			||||||
  this._mutualExclude(function () {
 | 
					  this._mutualExclude(() => {
 | 
				
			||||||
    // Apply computed delta.
 | 
					    // Apply computed delta.
 | 
				
			||||||
    quill.updateContents(event.delta, 'yjs')
 | 
					    quill.updateContents(event.delta, 'yjs')
 | 
				
			||||||
    // Force flush Quill changes. Ignore applied changes.
 | 
					    // Force flush Quill changes. Ignore applied changes.
 | 
				
			||||||
@ -12,7 +16,7 @@ function typeObserver (event) {
 | 
				
			|||||||
  })
 | 
					  })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function quillObserver (delta) {
 | 
					const quillObserver = function (delta) {
 | 
				
			||||||
  this._mutualExclude(() => {
 | 
					  this._mutualExclude(() => {
 | 
				
			||||||
    this.type.applyDelta(delta.ops)
 | 
					    this.type.applyDelta(delta.ops)
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
@ -28,14 +32,28 @@ function quillObserver (delta) {
 | 
				
			|||||||
 * // Now modifications on the DOM will be reflected in the Type, and the other
 | 
					 * // Now modifications on the DOM will be reflected in the Type, and the other
 | 
				
			||||||
 * // way around!
 | 
					 * // way around!
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export default class QuillBinding extends Binding {
 | 
					export class QuillBinding {
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * @param {YText} textType
 | 
					   * @param {YText} textType
 | 
				
			||||||
   * @param {Quill} quill
 | 
					   * @param {Quill} quill
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  constructor (textType, quill) {
 | 
					  constructor (textType, quill) {
 | 
				
			||||||
    // Binding handles textType as this.type and quill as this.target.
 | 
					    // Binding handles textType as this.type and quill as this.target.
 | 
				
			||||||
    super(textType, quill)
 | 
					    /**
 | 
				
			||||||
 | 
					     * The Yjs type that is bound to `target`
 | 
				
			||||||
 | 
					     * @type {YText}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    this.type = textType
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The target that `type` is bound to.
 | 
				
			||||||
 | 
					     * @type {Quill}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    this.target = quill
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @private
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    this._mutualExclude = createMutex()
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    // Set initial value.
 | 
					    // Set initial value.
 | 
				
			||||||
    quill.setContents(textType.toDelta(), 'yjs')
 | 
					    quill.setContents(textType.toDelta(), 'yjs')
 | 
				
			||||||
    // Observers are handled by this class.
 | 
					    // Observers are handled by this class.
 | 
				
			||||||
@ -48,6 +66,7 @@ export default class QuillBinding extends Binding {
 | 
				
			|||||||
    // Remove everything that is handled by this class.
 | 
					    // Remove everything that is handled by this class.
 | 
				
			||||||
    this.type.unobserve(this._typeObserver)
 | 
					    this.type.unobserve(this._typeObserver)
 | 
				
			||||||
    this.target.off('text-change', this._quillObserver)
 | 
					    this.target.off('text-change', this._quillObserver)
 | 
				
			||||||
    super.destroy()
 | 
					    this.type = null
 | 
				
			||||||
 | 
					    this.target = null
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -1,7 +1,10 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module bindings/textarea
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Binding from '../Binding.js'
 | 
					import { simpleDiff } from '../lib/diff.js'
 | 
				
			||||||
import simpleDiff from '../../lib/simpleDiff.js'
 | 
					import { getRelativePosition, fromRelativePosition } from '../utils/relativePosition.js'
 | 
				
			||||||
import { getRelativePosition, fromRelativePosition } from '../../src/Util/relativePosition.js'
 | 
					import { createMutex } from '../lib/mutex.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function typeObserver () {
 | 
					function typeObserver () {
 | 
				
			||||||
  this._mutualExclude(() => {
 | 
					  this._mutualExclude(() => {
 | 
				
			||||||
@ -35,10 +38,22 @@ function domObserver () {
 | 
				
			|||||||
 *   const binding = new Y.QuillBinding(type, textarea)
 | 
					 *   const binding = new Y.QuillBinding(type, textarea)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export default class TextareaBinding extends Binding {
 | 
					export class TextareaBinding {
 | 
				
			||||||
  constructor (textType, domTextarea) {
 | 
					  constructor (textType, domTextarea) {
 | 
				
			||||||
    // Binding handles textType as this.type and domTextarea as this.target
 | 
					    /**
 | 
				
			||||||
    super(textType, domTextarea)
 | 
					     * The Yjs type that is bound to `target`
 | 
				
			||||||
 | 
					     * @type {Type}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    this.type = textType
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The target that `type` is bound to.
 | 
				
			||||||
 | 
					     * @type {*}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    this.target = domTextarea
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @private
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    this._mutualExclude = createMutex()
 | 
				
			||||||
    // set initial value
 | 
					    // set initial value
 | 
				
			||||||
    domTextarea.value = textType.toString()
 | 
					    domTextarea.value = textType.toString()
 | 
				
			||||||
    // Observers are handled by this class
 | 
					    // Observers are handled by this class
 | 
				
			||||||
@ -51,6 +66,7 @@ export default class TextareaBinding extends Binding {
 | 
				
			|||||||
    // Remove everything that is handled by this class
 | 
					    // Remove everything that is handled by this class
 | 
				
			||||||
    this.type.unobserve(this._typeObserver)
 | 
					    this.type.unobserve(this._typeObserver)
 | 
				
			||||||
    this.target.unobserve(this._domObserver)
 | 
					    this.target.unobserve(this._domObserver)
 | 
				
			||||||
    super.destroy()
 | 
					    this.type = null
 | 
				
			||||||
 | 
					    this.target = null
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										1
									
								
								examples/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								examples/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					build
 | 
				
			||||||
							
								
								
									
										11
									
								
								examples/examples.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								examples/examples.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "prosemirror": {
 | 
				
			||||||
 | 
					    "title": "Prosemirror Binding"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "textarea": {
 | 
				
			||||||
 | 
					    "title": "Textarea Binding"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "quill": {
 | 
				
			||||||
 | 
					    "title": "Quill Binding"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										75
									
								
								examples/prosemirror.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								examples/prosemirror.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,75 @@
 | 
				
			|||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html>
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					    <title>Yjs Prosemirror Example</title>
 | 
				
			||||||
 | 
					    <link rel=stylesheet href="https://prosemirror.net/css/editor.css">
 | 
				
			||||||
 | 
					    <style>
 | 
				
			||||||
 | 
					      placeholder {
 | 
				
			||||||
 | 
					        display: inline;
 | 
				
			||||||
 | 
					        border: 1px solid #ccc;
 | 
				
			||||||
 | 
					        color: #ccc;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      placeholder:after {
 | 
				
			||||||
 | 
					        content: "☁";
 | 
				
			||||||
 | 
					        font-size: 200%;
 | 
				
			||||||
 | 
					        line-height: 0.1;
 | 
				
			||||||
 | 
					        font-weight: bold;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      .ProseMirror img { max-width: 100px }
 | 
				
			||||||
 | 
					      .ProseMirror-yjs-cursor {
 | 
				
			||||||
 | 
					        position: absolute;
 | 
				
			||||||
 | 
					        border-left: black;
 | 
				
			||||||
 | 
					        border-left-style: solid;
 | 
				
			||||||
 | 
					        border-left-width: 2px;
 | 
				
			||||||
 | 
					        border-color: orange;
 | 
				
			||||||
 | 
					        height: 1em;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      .ProseMirror-yjs-cursor > div {
 | 
				
			||||||
 | 
					        position: relative;
 | 
				
			||||||
 | 
					        top: -1.05em;
 | 
				
			||||||
 | 
					        font-size: 13px;
 | 
				
			||||||
 | 
					        background-color: rgb(250, 129, 0);
 | 
				
			||||||
 | 
					        font-family: serif;
 | 
				
			||||||
 | 
					        font-style: normal;
 | 
				
			||||||
 | 
					        font-weight: normal;
 | 
				
			||||||
 | 
					        line-height: normal;
 | 
				
			||||||
 | 
					        user-select: none;
 | 
				
			||||||
 | 
					        color: white;
 | 
				
			||||||
 | 
					        padding-left: 2px;
 | 
				
			||||||
 | 
					        padding-right: 2px;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    </style>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					  <div class="code-html">
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    <div id="editor" style="margin-bottom: 23px"></div>
 | 
				
			||||||
 | 
					    <div style="display: none" id="content">
 | 
				
			||||||
 | 
					      <h3>Hello User</h3>
 | 
				
			||||||
 | 
					      <p>type here ...</p>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					  <script class="code-js" src="./build/prosemirror.js">
 | 
				
			||||||
 | 
					import * as Y from 'yjs'
 | 
				
			||||||
 | 
					import { prosemirrorPlugin, cursorPlugin } from 'yjs/bindings/prosemirror.js'
 | 
				
			||||||
 | 
					import { WebsocketProvider } from 'yjs/provider/websocket.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { EditorState } from 'prosemirror-state'
 | 
				
			||||||
 | 
					import { EditorView } from 'prosemirror-view'
 | 
				
			||||||
 | 
					import { DOMParser } from 'prosemirror-model'
 | 
				
			||||||
 | 
					import { schema } from 'prosemirror-schema-basic'
 | 
				
			||||||
 | 
					import { exampleSetup } from 'prosemirror-example-setup'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const provider = new WebsocketProvider('ws://localhost:1234/')
 | 
				
			||||||
 | 
					const ydocument = provider.get('prosemirror')
 | 
				
			||||||
 | 
					const type = ydocument.define('prosemirror', Y.XmlFragment)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					window.prosemirrorView = new EditorView(document.querySelector('#editor'), {
 | 
				
			||||||
 | 
					  state: EditorState.create({
 | 
				
			||||||
 | 
					    doc: DOMParser.fromSchema(schema).parse(document.querySelector('#content')),
 | 
				
			||||||
 | 
					    plugins: exampleSetup({schema}).concat([prosemirrorPlugin(type), cursorPlugin])
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					  </script>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										20
									
								
								examples/prosemirror.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								examples/prosemirror.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					import * as Y from '../index.js'
 | 
				
			||||||
 | 
					import { prosemirrorPlugin, cursorPlugin } from '../bindings/prosemirror.js'
 | 
				
			||||||
 | 
					import { WebsocketProvider } from '../provider/websocket.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { EditorState } from 'prosemirror-state'
 | 
				
			||||||
 | 
					import { EditorView } from 'prosemirror-view'
 | 
				
			||||||
 | 
					import { DOMParser } from 'prosemirror-model'
 | 
				
			||||||
 | 
					import { schema } from 'prosemirror-schema-basic'
 | 
				
			||||||
 | 
					import { exampleSetup } from 'prosemirror-example-setup'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const provider = new WebsocketProvider('ws://localhost:1234/')
 | 
				
			||||||
 | 
					const ydocument = provider.get('prosemirror')
 | 
				
			||||||
 | 
					const type = ydocument.define('prosemirror', Y.XmlFragment)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					window.prosemirrorView = new EditorView(document.querySelector('#editor'), {
 | 
				
			||||||
 | 
					  state: EditorState.create({
 | 
				
			||||||
 | 
					    doc: DOMParser.fromSchema(schema).parse(document.querySelector('#content')),
 | 
				
			||||||
 | 
					    plugins: exampleSetup({schema}).concat([prosemirrorPlugin(type), cursorPlugin])
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
@ -1,73 +0,0 @@
 | 
				
			|||||||
/* eslint-env browser */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import {Plugin} from 'prosemirror-state'
 | 
					 | 
				
			||||||
import {Decoration, DecorationSet} from 'prosemirror-view'
 | 
					 | 
				
			||||||
import {schema} from 'prosemirror-schema-basic'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const findPlaceholder = (state, id) => {
 | 
					 | 
				
			||||||
  let decos = PlaceholderPlugin.getState(state)
 | 
					 | 
				
			||||||
  let found = decos.find(null, null, spec => spec.id === id)
 | 
					 | 
				
			||||||
  return found.length ? found[0].from : null
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const startImageUpload = (view, file) => {
 | 
					 | 
				
			||||||
  // A fresh object to act as the ID for this upload
 | 
					 | 
				
			||||||
  let id = {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Replace the selection with a placeholder
 | 
					 | 
				
			||||||
  let tr = view.state.tr
 | 
					 | 
				
			||||||
  if (!tr.selection.empty) tr.deleteSelection()
 | 
					 | 
				
			||||||
  tr.setMeta(PlaceholderPlugin, {add: {id, pos: tr.selection.from}})
 | 
					 | 
				
			||||||
  view.dispatch(tr)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  uploadFile(file).then(url => {
 | 
					 | 
				
			||||||
    let pos = findPlaceholder(view.state, id)
 | 
					 | 
				
			||||||
    // If the content around the placeholder has been deleted, drop
 | 
					 | 
				
			||||||
    // the image
 | 
					 | 
				
			||||||
    if (pos == null) return
 | 
					 | 
				
			||||||
    // Otherwise, insert it at the placeholder's position, and remove
 | 
					 | 
				
			||||||
    // the placeholder
 | 
					 | 
				
			||||||
    view.dispatch(view.state.tr
 | 
					 | 
				
			||||||
      .replaceWith(pos, pos, schema.nodes.image.create({src: url}))
 | 
					 | 
				
			||||||
      .setMeta(PlaceholderPlugin, {remove: {id}}))
 | 
					 | 
				
			||||||
  }, () => {
 | 
					 | 
				
			||||||
    // On failure, just clean up the placeholder
 | 
					 | 
				
			||||||
    view.dispatch(tr.setMeta(PlaceholderPlugin, {remove: {id}}))
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// This is just a dummy that loads the file and creates a data URL.
 | 
					 | 
				
			||||||
// You could swap it out with a function that does an actual upload
 | 
					 | 
				
			||||||
// and returns a regular URL for the uploaded file.
 | 
					 | 
				
			||||||
function uploadFile (file) {
 | 
					 | 
				
			||||||
  let reader = new FileReader()
 | 
					 | 
				
			||||||
  return new Promise((resolve, reject) => {
 | 
					 | 
				
			||||||
    reader.onload = () => resolve(reader.result)
 | 
					 | 
				
			||||||
    reader.onerror = () => reject(reader.error)
 | 
					 | 
				
			||||||
    // Some extra delay to make the asynchronicity visible
 | 
					 | 
				
			||||||
    setTimeout(() => reader.readAsDataURL(file), 1500)
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const PlaceholderPlugin = new Plugin({
 | 
					 | 
				
			||||||
  state: {
 | 
					 | 
				
			||||||
    init () { return DecorationSet.empty },
 | 
					 | 
				
			||||||
    apply (tr, set) {
 | 
					 | 
				
			||||||
      // Adjust decoration positions to changes made by the transaction
 | 
					 | 
				
			||||||
      set = set.map(tr.mapping, tr.doc)
 | 
					 | 
				
			||||||
      // See if the transaction adds or removes any placeholders
 | 
					 | 
				
			||||||
      let action = tr.getMeta(this)
 | 
					 | 
				
			||||||
      if (action && action.add) {
 | 
					 | 
				
			||||||
        let widget = document.createElement('placeholder')
 | 
					 | 
				
			||||||
        let deco = Decoration.widget(action.add.pos, widget, {id: action.add.id})
 | 
					 | 
				
			||||||
        set = set.add(tr.doc, [deco])
 | 
					 | 
				
			||||||
      } else if (action && action.remove) {
 | 
					 | 
				
			||||||
        set = set.remove(set.find(null, null, spec => spec.id === action.remove.id))
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      return set
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  props: {
 | 
					 | 
				
			||||||
    decorations (state) { return this.getState(state) }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
@ -1,21 +0,0 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
# Prosemirror Example
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### Run basic websockets server
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```sh
 | 
					 | 
				
			||||||
node /provider/websocket/server.js
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### Bundle Prosemirror Example
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
This example requires external modules and needs to be bundled before shipping it to the browser.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```sh
 | 
					 | 
				
			||||||
cd /examples/prosemirror/
 | 
					 | 
				
			||||||
# bundle prosemirror example
 | 
					 | 
				
			||||||
npx rollup -wc
 | 
					 | 
				
			||||||
# serve example
 | 
					 | 
				
			||||||
npx serve .
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@ -1,51 +0,0 @@
 | 
				
			|||||||
<!DOCTYPE html>
 | 
					 | 
				
			||||||
<html>
 | 
					 | 
				
			||||||
  <head>
 | 
					 | 
				
			||||||
      <script type="module" src="./index.dist.js"></script>
 | 
					 | 
				
			||||||
      <link rel=stylesheet href="https://prosemirror.net/css/editor.css">
 | 
					 | 
				
			||||||
      <style>
 | 
					 | 
				
			||||||
        placeholder {
 | 
					 | 
				
			||||||
          display: inline;
 | 
					 | 
				
			||||||
          border: 1px solid #ccc;
 | 
					 | 
				
			||||||
          color: #ccc;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        placeholder:after {
 | 
					 | 
				
			||||||
          content: "☁";
 | 
					 | 
				
			||||||
          font-size: 200%;
 | 
					 | 
				
			||||||
          line-height: 0.1;
 | 
					 | 
				
			||||||
          font-weight: bold;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        .ProseMirror img { max-width: 100px }
 | 
					 | 
				
			||||||
        .ProseMirror-yjs-cursor {
 | 
					 | 
				
			||||||
          position: absolute;
 | 
					 | 
				
			||||||
          border-left: black;
 | 
					 | 
				
			||||||
          border-left-style: solid;
 | 
					 | 
				
			||||||
          border-left-width: 2px;
 | 
					 | 
				
			||||||
          border-color: orange;
 | 
					 | 
				
			||||||
          height: 1em;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        .ProseMirror-yjs-cursor > div {
 | 
					 | 
				
			||||||
          position: relative;
 | 
					 | 
				
			||||||
          top: -1.05em;
 | 
					 | 
				
			||||||
          font-size: 13px;
 | 
					 | 
				
			||||||
          background-color: rgb(250, 129, 0);
 | 
					 | 
				
			||||||
          font-family: serif;
 | 
					 | 
				
			||||||
          font-style: normal;
 | 
					 | 
				
			||||||
          font-weight: normal;
 | 
					 | 
				
			||||||
          line-height: normal;
 | 
					 | 
				
			||||||
          user-select: none;
 | 
					 | 
				
			||||||
          color: white;
 | 
					 | 
				
			||||||
          padding-left: 2px;
 | 
					 | 
				
			||||||
          padding-right: 2px;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      </style>
 | 
					 | 
				
			||||||
  </head>
 | 
					 | 
				
			||||||
<body>
 | 
					 | 
				
			||||||
  <div id="editor" style="margin-bottom: 23px"></div>
 | 
					 | 
				
			||||||
  <div style="display: none" id="content">
 | 
					 | 
				
			||||||
    <h3>Hello User</h3>
 | 
					 | 
				
			||||||
    <p>type something ...</p>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
  <div>Insert image: <input type=file id=image-upload></div>
 | 
					 | 
				
			||||||
</body>
 | 
					 | 
				
			||||||
</html>
 | 
					 | 
				
			||||||
@ -1,45 +0,0 @@
 | 
				
			|||||||
/* eslint-env browser */
 | 
					 | 
				
			||||||
import * as Y from '../../src/index.js'
 | 
					 | 
				
			||||||
import { prosemirrorPlugin, cursorPlugin } from '../../bindings/ProsemirrorBinding/ProsemirrorBinding.js'
 | 
					 | 
				
			||||||
import WebsocketProvider from '../../provider/websocket/WebSocketProvider.js'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import {EditorState} from 'prosemirror-state'
 | 
					 | 
				
			||||||
import {EditorView} from 'prosemirror-view'
 | 
					 | 
				
			||||||
import {Schema, DOMParser, Mark, Fragment, Node, Slice} from 'prosemirror-model'
 | 
					 | 
				
			||||||
import {schema} from 'prosemirror-schema-basic'
 | 
					 | 
				
			||||||
import {exampleSetup} from 'prosemirror-example-setup'
 | 
					 | 
				
			||||||
import { PlaceholderPlugin, startImageUpload } from './PlaceholderPlugin.js'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const provider = new WebsocketProvider('ws://localhost:1234/')
 | 
					 | 
				
			||||||
const ydocument = provider.get('prosemirror')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @type {any}
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
const type = ydocument.define('prosemirror', Y.XmlFragment)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const view = new EditorView(document.querySelector('#editor'), {
 | 
					 | 
				
			||||||
  state: EditorState.create({
 | 
					 | 
				
			||||||
    doc: DOMParser.fromSchema(schema).parse(document.querySelector('#content')),
 | 
					 | 
				
			||||||
    plugins: exampleSetup({schema}).concat([PlaceholderPlugin, prosemirrorPlugin(type), cursorPlugin])
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
window.provider = provider
 | 
					 | 
				
			||||||
window.ydocument = ydocument
 | 
					 | 
				
			||||||
window.type = type
 | 
					 | 
				
			||||||
window.view = view
 | 
					 | 
				
			||||||
window.EditorState = EditorState
 | 
					 | 
				
			||||||
window.EditorView = EditorView
 | 
					 | 
				
			||||||
window.Mark = Mark
 | 
					 | 
				
			||||||
window.Fragment = Fragment
 | 
					 | 
				
			||||||
window.Node = Node
 | 
					 | 
				
			||||||
window.Schema = Schema
 | 
					 | 
				
			||||||
window.Slice = Slice
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
document.querySelector('#image-upload').addEventListener('change', e => {
 | 
					 | 
				
			||||||
  if (view.state.selection.$from.parent.inlineContent && e.target.files.length) {
 | 
					 | 
				
			||||||
    startImageUpload(view, e.target.files[0])
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  view.focus()
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
@ -1,20 +0,0 @@
 | 
				
			|||||||
import nodeResolve from 'rollup-plugin-node-resolve'
 | 
					 | 
				
			||||||
import commonjs from 'rollup-plugin-commonjs'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
  input: './index.js',
 | 
					 | 
				
			||||||
  output: {
 | 
					 | 
				
			||||||
    name: 'index',
 | 
					 | 
				
			||||||
    file: 'index.dist.js',
 | 
					 | 
				
			||||||
    format: 'umd',
 | 
					 | 
				
			||||||
    sourcemap: true
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  plugins: [
 | 
					 | 
				
			||||||
    nodeResolve({
 | 
					 | 
				
			||||||
      main: true,
 | 
					 | 
				
			||||||
      module: true,
 | 
					 | 
				
			||||||
      browser: true
 | 
					 | 
				
			||||||
    }),
 | 
					 | 
				
			||||||
    commonjs()
 | 
					 | 
				
			||||||
  ]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										54
									
								
								examples/quill.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								examples/quill.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html>
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					    <title>Yjs Prosemirror Example</title>
 | 
				
			||||||
 | 
					    <link rel=stylesheet href="https://prosemirror.net/css/editor.css">
 | 
				
			||||||
 | 
					    <style>
 | 
				
			||||||
 | 
					      placeholder {
 | 
				
			||||||
 | 
					        display: inline;
 | 
				
			||||||
 | 
					        border: 1px solid #ccc;
 | 
				
			||||||
 | 
					        color: #ccc;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      placeholder:after {
 | 
				
			||||||
 | 
					        content: "☁";
 | 
				
			||||||
 | 
					        font-size: 200%;
 | 
				
			||||||
 | 
					        line-height: 0.1;
 | 
				
			||||||
 | 
					        font-weight: bold;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      .ProseMirror img { max-width: 100px }
 | 
				
			||||||
 | 
					      .ProseMirror-yjs-cursor {
 | 
				
			||||||
 | 
					        position: absolute;
 | 
				
			||||||
 | 
					        border-left: black;
 | 
				
			||||||
 | 
					        border-left-style: solid;
 | 
				
			||||||
 | 
					        border-left-width: 2px;
 | 
				
			||||||
 | 
					        border-color: orange;
 | 
				
			||||||
 | 
					        height: 1em;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      .ProseMirror-yjs-cursor > div {
 | 
				
			||||||
 | 
					        position: relative;
 | 
				
			||||||
 | 
					        top: -1.05em;
 | 
				
			||||||
 | 
					        font-size: 13px;
 | 
				
			||||||
 | 
					        background-color: rgb(250, 129, 0);
 | 
				
			||||||
 | 
					        font-family: serif;
 | 
				
			||||||
 | 
					        font-style: normal;
 | 
				
			||||||
 | 
					        font-weight: normal;
 | 
				
			||||||
 | 
					        line-height: normal;
 | 
				
			||||||
 | 
					        user-select: none;
 | 
				
			||||||
 | 
					        color: white;
 | 
				
			||||||
 | 
					        padding-left: 2px;
 | 
				
			||||||
 | 
					        padding-right: 2px;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    </style>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					  <link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
 | 
				
			||||||
 | 
					  <div class="code-html">
 | 
				
			||||||
 | 
					    <div id="quill-container">
 | 
				
			||||||
 | 
					      <div id="quill">
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					  <script class="code-js" src="./build/quill.js">
 | 
				
			||||||
 | 
					  </script>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										27
									
								
								examples/quill.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								examples/quill.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					import * as Y from '../index.js'
 | 
				
			||||||
 | 
					import { QuillBinding } from '../bindings/quill.js'
 | 
				
			||||||
 | 
					import { WebsocketProvider } from '../provider/websocket.js'
 | 
				
			||||||
 | 
					import Quill from 'quill'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const provider = new WebsocketProvider('ws://localhost:1234/')
 | 
				
			||||||
 | 
					const ydocument = provider.get('quill')
 | 
				
			||||||
 | 
					const ytext = ydocument.define('quill', Y.Text)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const quill = new Quill('#quill-container', {
 | 
				
			||||||
 | 
					  modules: {
 | 
				
			||||||
 | 
					    toolbar: [
 | 
				
			||||||
 | 
					      [{ header: [1, 2, false] }],
 | 
				
			||||||
 | 
					      ['bold', 'italic', 'underline'],
 | 
				
			||||||
 | 
					      ['image', 'code-block'],
 | 
				
			||||||
 | 
					      [{ color: [] }, { background: [] }], // Snow theme fills in values
 | 
				
			||||||
 | 
					      [{ script: 'sub' }, { script: 'super' }],
 | 
				
			||||||
 | 
					      ['link', 'image'],
 | 
				
			||||||
 | 
					      ['link', 'code-block'],
 | 
				
			||||||
 | 
					      [{ list: 'ordered' }, { list: 'bullet' }]
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  placeholder: 'Compose an epic...',
 | 
				
			||||||
 | 
					  theme: 'snow' // or 'bubble'
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					window.quillBinding = new QuillBinding(ytext, quill)
 | 
				
			||||||
							
								
								
									
										29
									
								
								examples/style.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								examples/style.css
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					footer img {
 | 
				
			||||||
 | 
					  display: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nav .title h1 a {
 | 
				
			||||||
 | 
					  display: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					footer {
 | 
				
			||||||
 | 
					  background-color: #b93c1d;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#resizer {
 | 
				
			||||||
 | 
					  background-color: #b93c1d;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.main section article.readme h1:first-child img {
 | 
				
			||||||
 | 
					  display: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.main section article.readme h1:first-child {
 | 
				
			||||||
 | 
					  margin-bottom: 16px;
 | 
				
			||||||
 | 
					  margin-top: 30px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.main section article.readme h1:first-child::before {
 | 
				
			||||||
 | 
					  content: "The Shared Editing Library";
 | 
				
			||||||
 | 
					  font-size: 2em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										64
									
								
								examples/textarea.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								examples/textarea.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,64 @@
 | 
				
			|||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html>
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					    <title>Yjs Prosemirror Example</title>
 | 
				
			||||||
 | 
					    <link rel=stylesheet href="https://prosemirror.net/css/editor.css">
 | 
				
			||||||
 | 
					    <style>
 | 
				
			||||||
 | 
					      placeholder {
 | 
				
			||||||
 | 
					        display: inline;
 | 
				
			||||||
 | 
					        border: 1px solid #ccc;
 | 
				
			||||||
 | 
					        color: #ccc;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      placeholder:after {
 | 
				
			||||||
 | 
					        content: "☁";
 | 
				
			||||||
 | 
					        font-size: 200%;
 | 
				
			||||||
 | 
					        line-height: 0.1;
 | 
				
			||||||
 | 
					        font-weight: bold;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      .ProseMirror img { max-width: 100px }
 | 
				
			||||||
 | 
					      .ProseMirror-yjs-cursor {
 | 
				
			||||||
 | 
					        position: absolute;
 | 
				
			||||||
 | 
					        border-left: black;
 | 
				
			||||||
 | 
					        border-left-style: solid;
 | 
				
			||||||
 | 
					        border-left-width: 2px;
 | 
				
			||||||
 | 
					        border-color: orange;
 | 
				
			||||||
 | 
					        height: 1em;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      .ProseMirror-yjs-cursor > div {
 | 
				
			||||||
 | 
					        position: relative;
 | 
				
			||||||
 | 
					        top: -1.05em;
 | 
				
			||||||
 | 
					        font-size: 13px;
 | 
				
			||||||
 | 
					        background-color: rgb(250, 129, 0);
 | 
				
			||||||
 | 
					        font-family: serif;
 | 
				
			||||||
 | 
					        font-style: normal;
 | 
				
			||||||
 | 
					        font-weight: normal;
 | 
				
			||||||
 | 
					        line-height: normal;
 | 
				
			||||||
 | 
					        user-select: none;
 | 
				
			||||||
 | 
					        color: white;
 | 
				
			||||||
 | 
					        padding-left: 2px;
 | 
				
			||||||
 | 
					        padding-right: 2px;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    </style>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					  <div class="code-html">
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    <textarea style="width:80%;" rows=40 autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					  <script class="code-js" src="./build/textarea.js">
 | 
				
			||||||
 | 
					import * as Y from '../index.js'
 | 
				
			||||||
 | 
					import { TextareaBinding } from '../bindings/textarea.js'
 | 
				
			||||||
 | 
					import { WebsocketProvider } from '../provider/websocket.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const provider = new WebsocketProvider('ws://localhost:1234/')
 | 
				
			||||||
 | 
					const ydocument = provider.get('textarea')
 | 
				
			||||||
 | 
					const type = ydocument.define('textarea', Y.Text)
 | 
				
			||||||
 | 
					const textarea = document.querySelector('textarea')
 | 
				
			||||||
 | 
					const binding = new TextareaBinding(type, textarea)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					window.textareaExample = {
 | 
				
			||||||
 | 
					  provider, ydocument, type, textarea, binding
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					  </script>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
@ -1,12 +1,12 @@
 | 
				
			|||||||
/* eslint-env browser */
 | 
					import * as Y from '../index.js'
 | 
				
			||||||
import * as Y from '../../src/index.js'
 | 
					import { TextareaBinding } from '../bindings/textarea.js'
 | 
				
			||||||
import WebsocketProvider from '../../provider/websocket/WebSocketProvider.js'
 | 
					import { WebsocketProvider } from '../provider/websocket.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const provider = new WebsocketProvider('ws://localhost:1234/')
 | 
					const provider = new WebsocketProvider('ws://localhost:1234/')
 | 
				
			||||||
const ydocument = provider.get('textarea')
 | 
					const ydocument = provider.get('textarea')
 | 
				
			||||||
const type = ydocument.define('textarea', Y.Text)
 | 
					const type = ydocument.define('textarea', Y.Text)
 | 
				
			||||||
const textarea = document.querySelector('textarea')
 | 
					const textarea = document.querySelector('textarea')
 | 
				
			||||||
const binding = new Y.TextareaBinding(type, textarea)
 | 
					const binding = new TextareaBinding(type, textarea)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
window.textareaExample = {
 | 
					window.textareaExample = {
 | 
				
			||||||
  provider, ydocument, type, textarea, binding
 | 
					  provider, ydocument, type, textarea, binding
 | 
				
			||||||
@ -1,7 +0,0 @@
 | 
				
			|||||||
<!DOCTYPE html>
 | 
					 | 
				
			||||||
<html>
 | 
					 | 
				
			||||||
<body>
 | 
					 | 
				
			||||||
  <textarea style="width:80%;" rows=40 autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>
 | 
					 | 
				
			||||||
  <script type="module" src="./index.js"></script>
 | 
					 | 
				
			||||||
</body>
 | 
					 | 
				
			||||||
</html>
 | 
					 | 
				
			||||||
@ -14,7 +14,7 @@ let chatprotocol = y.define('chatprotocol', Y.Array)
 | 
				
			|||||||
let chatcontainer = document.querySelector('#chat')
 | 
					let chatcontainer = document.querySelector('#chat')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This functions inserts a message at the specified position in the DOM
 | 
					// This functions inserts a message at the specified position in the DOM
 | 
				
			||||||
function appendMessage (message, position) {
 | 
					const appendMessage = (message, position) => {
 | 
				
			||||||
  var p = document.createElement('p')
 | 
					  var p = document.createElement('p')
 | 
				
			||||||
  var uname = document.createElement('span')
 | 
					  var uname = document.createElement('span')
 | 
				
			||||||
  uname.appendChild(document.createTextNode(message.username + ': '))
 | 
					  uname.appendChild(document.createTextNode(message.username + ': '))
 | 
				
			||||||
@ -25,7 +25,7 @@ function appendMessage (message, position) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// This function makes sure that only 7 messages exist in the chat history.
 | 
					// This function makes sure that only 7 messages exist in the chat history.
 | 
				
			||||||
// The rest is deleted
 | 
					// The rest is deleted
 | 
				
			||||||
function cleanupChat () {
 | 
					const cleanupChat = () => {
 | 
				
			||||||
  if (chatprotocol.length > 7) {
 | 
					  if (chatprotocol.length > 7) {
 | 
				
			||||||
    chatprotocol.delete(0, chatprotocol.length - 7)
 | 
					    chatprotocol.delete(0, chatprotocol.length - 7)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -36,7 +36,7 @@ cleanupChat()
 | 
				
			|||||||
chatprotocol.toArray().forEach(appendMessage)
 | 
					chatprotocol.toArray().forEach(appendMessage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// whenever content changes, make sure to reflect the changes in the DOM
 | 
					// whenever content changes, make sure to reflect the changes in the DOM
 | 
				
			||||||
chatprotocol.observe(function (event) {
 | 
					chatprotocol.observe(event => {
 | 
				
			||||||
  // concurrent insertions may result in a history > 7, so cleanup here
 | 
					  // concurrent insertions may result in a history > 7, so cleanup here
 | 
				
			||||||
  cleanupChat()
 | 
					  cleanupChat()
 | 
				
			||||||
  chatcontainer.innerHTML = ''
 | 
					  chatcontainer.innerHTML = ''
 | 
				
			||||||
@ -36,13 +36,13 @@ let quill = new Quill('#quill-container', {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
let cursors = quill.getModule('cursors')
 | 
					let cursors = quill.getModule('cursors')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function drawCursors () {
 | 
					const drawCursors = () => {
 | 
				
			||||||
  cursors.clearCursors()
 | 
					  cursors.clearCursors()
 | 
				
			||||||
  users.map((user, userId) => {
 | 
					  users.map((user, userId) => {
 | 
				
			||||||
    if (user !== myUserInfo) {
 | 
					    if (user !== myUserInfo) {
 | 
				
			||||||
      let relativeRange = user.get('range')
 | 
					      let relativeRange = user.get('range')
 | 
				
			||||||
      let lastUpdated = new Date(user.get('last updated'))
 | 
					      let lastUpdated = new Date(user.get('last updated')).getTime()
 | 
				
			||||||
      if (lastUpdated != null && new Date() - lastUpdated < 20000 && relativeRange != null) {
 | 
					      if (lastUpdated != null && new Date().getTime() - lastUpdated < 20000 && relativeRange != null) {
 | 
				
			||||||
        let start = Y.utils.fromRelativePosition(y, relativeRange.start).offset
 | 
					        let start = Y.utils.fromRelativePosition(y, relativeRange.start).offset
 | 
				
			||||||
        let end = Y.utils.fromRelativePosition(y, relativeRange.end).offset
 | 
					        let end = Y.utils.fromRelativePosition(y, relativeRange.end).offset
 | 
				
			||||||
        let range = { index: start, length: end - start }
 | 
					        let range = { index: start, length: end - start }
 | 
				
			||||||
@ -26,8 +26,4 @@ let quill = new Quill('#quill-container', {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
let yText = y.define('quill', Y.Text)
 | 
					let yText = y.define('quill', Y.Text)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let quillBinding = new Y.QuillBinding(yText, quill)
 | 
					window.quillBinding = new Y.QuillBinding(yText, quill)
 | 
				
			||||||
window.quillBinding = quillBinding
 | 
					 | 
				
			||||||
window.yText = yText
 | 
					 | 
				
			||||||
window.y = y
 | 
					 | 
				
			||||||
window.quill = quill
 | 
					 | 
				
			||||||
							
								
								
									
										52
									
								
								index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								index.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					import { Delete } from './structs/Delete.js'
 | 
				
			||||||
 | 
					import { ItemJSON } from './structs/ItemJSON.js'
 | 
				
			||||||
 | 
					import { ItemString } from './structs/ItemString.js'
 | 
				
			||||||
 | 
					import { ItemFormat } from './structs/ItemFormat.js'
 | 
				
			||||||
 | 
					import { ItemEmbed } from './structs/ItemEmbed.js'
 | 
				
			||||||
 | 
					import { GC } from './structs/GC.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { YArray } from './types/YArray.js'
 | 
				
			||||||
 | 
					import { YMap } from './types/YMap.js'
 | 
				
			||||||
 | 
					import { YText } from './types/YText.js'
 | 
				
			||||||
 | 
					import { YXmlText } from './types/YXmlText.js'
 | 
				
			||||||
 | 
					import { YXmlHook } from './types/YXmlHook.js'
 | 
				
			||||||
 | 
					import { YXmlElement, YXmlFragment } from './types/YXmlElement.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { registerStruct } from './utils/structReferences.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export { Y } from './utils/Y.js'
 | 
				
			||||||
 | 
					export { UndoManager } from './utils/UndoManager.js'
 | 
				
			||||||
 | 
					export { Transaction } from './utils/Transaction.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export { YArray as Array } from './types/YArray.js'
 | 
				
			||||||
 | 
					export { YMap as Map } from './types/YMap.js'
 | 
				
			||||||
 | 
					export { YText as Text } from './types/YText.js'
 | 
				
			||||||
 | 
					export { YXmlText as XmlText } from './types/YXmlText.js'
 | 
				
			||||||
 | 
					export { YXmlHook as XmlHook } from './types/YXmlHook.js'
 | 
				
			||||||
 | 
					export { YXmlElement as XmlElement, YXmlFragment as XmlFragment } from './types/YXmlElement.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export { getRelativePosition, fromRelativePosition } from './utils/relativePosition.js'
 | 
				
			||||||
 | 
					export { registerStruct } from './utils/structReferences.js'
 | 
				
			||||||
 | 
					export * from './protocols/syncProtocol.js'
 | 
				
			||||||
 | 
					export * from './protocols/awarenessProtocol.js'
 | 
				
			||||||
 | 
					export * from './lib/encoding.js'
 | 
				
			||||||
 | 
					export * from './lib/decoding.js'
 | 
				
			||||||
 | 
					export * from './lib/mutex.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export { WebsocketProvider } from './provider/websocket/WebSocketProvider.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					registerStruct(0, GC)
 | 
				
			||||||
 | 
					registerStruct(1, ItemJSON)
 | 
				
			||||||
 | 
					registerStruct(2, ItemString)
 | 
				
			||||||
 | 
					registerStruct(3, ItemFormat)
 | 
				
			||||||
 | 
					registerStruct(4, Delete)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					registerStruct(5, YArray)
 | 
				
			||||||
 | 
					registerStruct(6, YMap)
 | 
				
			||||||
 | 
					registerStruct(7, YText)
 | 
				
			||||||
 | 
					registerStruct(8, YXmlFragment)
 | 
				
			||||||
 | 
					registerStruct(9, YXmlElement)
 | 
				
			||||||
 | 
					registerStruct(10, YXmlText)
 | 
				
			||||||
 | 
					registerStruct(11, YXmlHook)
 | 
				
			||||||
 | 
					registerStruct(12, ItemEmbed)
 | 
				
			||||||
@ -2,7 +2,7 @@
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Handles named events.
 | 
					 * Handles named events.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export default class NamedEventHandler {
 | 
					export class NamedEventHandler {
 | 
				
			||||||
  constructor () {
 | 
					  constructor () {
 | 
				
			||||||
    this._eventListener = new Map()
 | 
					    this._eventListener = new Map()
 | 
				
			||||||
    this._stateListener = new Map()
 | 
					    this._stateListener = new Map()
 | 
				
			||||||
@ -57,7 +57,7 @@ export default class NamedEventHandler {
 | 
				
			|||||||
    let state = this._stateListener.get(name)
 | 
					    let state = this._stateListener.get(name)
 | 
				
			||||||
    if (state === undefined) {
 | 
					    if (state === undefined) {
 | 
				
			||||||
      state = {}
 | 
					      state = {}
 | 
				
			||||||
      state.promise = new Promise(function (resolve) {
 | 
					      state.promise = new Promise(resolve => {
 | 
				
			||||||
        state.resolve = resolve
 | 
					        state.resolve = resolve
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
      this._stateListener.set(name, state)
 | 
					      this._stateListener.set(name, state)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										19
									
								
								lib/Tree.js
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								lib/Tree.js
									
									
									
									
									
								
							@ -1,5 +1,8 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module tree
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function rotate (tree, parent, newParent, n) {
 | 
					const rotate = (tree, parent, newParent, n) => {
 | 
				
			||||||
  if (parent === null) {
 | 
					  if (parent === null) {
 | 
				
			||||||
    tree.root = newParent
 | 
					    tree.root = newParent
 | 
				
			||||||
    newParent._parent = null
 | 
					    newParent._parent = null
 | 
				
			||||||
@ -111,10 +114,16 @@ class N {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const isBlack = node =>
 | 
				
			||||||
 | 
					  node !== null ? node.isBlack() : true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const isRed = (node) =>
 | 
				
			||||||
 | 
					  node !== null ? node.isRed() : false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * This is a Red Black Tree implementation
 | 
					 * This is a Red Black Tree implementation
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export default class Tree {
 | 
					export class Tree {
 | 
				
			||||||
  constructor () {
 | 
					  constructor () {
 | 
				
			||||||
    this.root = null
 | 
					    this.root = null
 | 
				
			||||||
    this.length = 0
 | 
					    this.length = 0
 | 
				
			||||||
@ -310,12 +319,6 @@ export default class Tree {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  _fixDelete (n) {
 | 
					  _fixDelete (n) {
 | 
				
			||||||
    function isBlack (node) {
 | 
					 | 
				
			||||||
      return node !== null ? node.isBlack() : true
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    function isRed (node) {
 | 
					 | 
				
			||||||
      return node !== null ? node.isRed() : false
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (n.parent === null) {
 | 
					    if (n.parent === null) {
 | 
				
			||||||
      // this can only be called after the first iteration of fixDelete.
 | 
					      // this can only be called after the first iteration of fixDelete.
 | 
				
			||||||
      return
 | 
					      return
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,6 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module binary
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const BITS32 = 0xFFFFFFFF
 | 
					export const BITS32 = 0xFFFFFFFF
 | 
				
			||||||
export const BITS21 = (1 << 21) - 1
 | 
					export const BITS21 = (1 << 21) - 1
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,6 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module decoding
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* global Buffer */
 | 
					/* global Buffer */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -17,17 +20,26 @@ export class Decoder {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {ArrayBuffer} buffer
 | 
					 * @param {ArrayBuffer} buffer
 | 
				
			||||||
 * @return {Decoder}
 | 
					 * @return {Decoder}
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const createDecoder = buffer => new Decoder(buffer)
 | 
					export const createDecoder = buffer => new Decoder(buffer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 | 
					 * @param {Decoder} decoder
 | 
				
			||||||
 | 
					 * @return {boolean}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
export const hasContent = decoder => decoder.pos !== decoder.arr.length
 | 
					export const hasContent = decoder => decoder.pos !== decoder.arr.length
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Clone a decoder instance.
 | 
					 * Clone a decoder instance.
 | 
				
			||||||
 * Optionally set a new position parameter.
 | 
					 * Optionally set a new position parameter.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Decoder} decoder The decoder instance
 | 
					 * @param {Decoder} decoder The decoder instance
 | 
				
			||||||
 | 
					 * @param {number} [newPos] Defaults to current position
 | 
				
			||||||
 * @return {Decoder} A clone of `decoder`
 | 
					 * @return {Decoder} A clone of `decoder`
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const clone = (decoder, newPos = decoder.pos) => {
 | 
					export const clone = (decoder, newPos = decoder.pos) => {
 | 
				
			||||||
@ -38,6 +50,7 @@ export const clone = (decoder, newPos = decoder.pos) => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Read `len` bytes as an ArrayBuffer.
 | 
					 * Read `len` bytes as an ArrayBuffer.
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Decoder} decoder The decoder instance
 | 
					 * @param {Decoder} decoder The decoder instance
 | 
				
			||||||
 * @param {number} len The length of bytes to read
 | 
					 * @param {number} len The length of bytes to read
 | 
				
			||||||
 * @return {ArrayBuffer}
 | 
					 * @return {ArrayBuffer}
 | 
				
			||||||
@ -52,6 +65,7 @@ export const readArrayBuffer = (decoder, len) => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Read variable length payload as ArrayBuffer
 | 
					 * Read variable length payload as ArrayBuffer
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Decoder} decoder
 | 
					 * @param {Decoder} decoder
 | 
				
			||||||
 * @return {ArrayBuffer}
 | 
					 * @return {ArrayBuffer}
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -59,6 +73,7 @@ export const readPayload = decoder => readArrayBuffer(decoder, readVarUint(decod
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Read the rest of the content as an ArrayBuffer
 | 
					 * Read the rest of the content as an ArrayBuffer
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Decoder} decoder
 | 
					 * @param {Decoder} decoder
 | 
				
			||||||
 * @return {ArrayBuffer}
 | 
					 * @return {ArrayBuffer}
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -66,6 +81,7 @@ export const readTail = decoder => readArrayBuffer(decoder, decoder.arr.length -
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Skip one byte, jump to the next position.
 | 
					 * Skip one byte, jump to the next position.
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Decoder} decoder The decoder instance
 | 
					 * @param {Decoder} decoder The decoder instance
 | 
				
			||||||
 * @return {number} The next position
 | 
					 * @return {number} The next position
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -73,6 +89,7 @@ export const skip8 = decoder => decoder.pos++
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Read one byte as unsigned integer.
 | 
					 * Read one byte as unsigned integer.
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Decoder} decoder The decoder instance
 | 
					 * @param {Decoder} decoder The decoder instance
 | 
				
			||||||
 * @return {number} Unsigned 8-bit integer
 | 
					 * @return {number} Unsigned 8-bit integer
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -81,6 +98,7 @@ export const readUint8 = decoder => decoder.arr[decoder.pos++]
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Read 4 bytes as unsigned integer.
 | 
					 * Read 4 bytes as unsigned integer.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Decoder} decoder
 | 
					 * @param {Decoder} decoder
 | 
				
			||||||
 * @return {number} An unsigned integer.
 | 
					 * @return {number} An unsigned integer.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -98,6 +116,7 @@ export const readUint32 = decoder => {
 | 
				
			|||||||
 * Look ahead without incrementing position.
 | 
					 * Look ahead without incrementing position.
 | 
				
			||||||
 * to the next byte and read it as unsigned integer.
 | 
					 * to the next byte and read it as unsigned integer.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Decoder} decoder
 | 
					 * @param {Decoder} decoder
 | 
				
			||||||
 * @return {number} An unsigned integer.
 | 
					 * @return {number} An unsigned integer.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -109,6 +128,7 @@ export const peekUint8 = decoder => decoder.arr[decoder.pos]
 | 
				
			|||||||
 *  * numbers < 2^7 is stored in one bytlength
 | 
					 *  * numbers < 2^7 is stored in one bytlength
 | 
				
			||||||
 *  * numbers < 2^14 is stored in two bylength
 | 
					 *  * numbers < 2^14 is stored in two bylength
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Decoder} decoder
 | 
					 * @param {Decoder} decoder
 | 
				
			||||||
 * @return {number} An unsigned integer.length
 | 
					 * @return {number} An unsigned integer.length
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -137,6 +157,7 @@ export const readVarUint = decoder => {
 | 
				
			|||||||
 * But most environments have a maximum number of arguments per functions.
 | 
					 * But most environments have a maximum number of arguments per functions.
 | 
				
			||||||
 * For effiency reasons we apply a maximum of 10000 characters at once.
 | 
					 * For effiency reasons we apply a maximum of 10000 characters at once.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Decoder} decoder
 | 
					 * @param {Decoder} decoder
 | 
				
			||||||
 * @return {String} The read String.
 | 
					 * @return {String} The read String.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -157,6 +178,8 @@ export const readVarString = decoder => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Look ahead and read varString without incrementing position
 | 
					 * Look ahead and read varString without incrementing position
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Decoder} decoder
 | 
					 * @param {Decoder} decoder
 | 
				
			||||||
 * @return {string}
 | 
					 * @return {string}
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,6 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module diff
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * A SimpleDiff describes a change on a String.
 | 
					 * A SimpleDiff describes a change on a String.
 | 
				
			||||||
@ -27,7 +30,7 @@
 | 
				
			|||||||
 * @param {String} b The updated version of the string
 | 
					 * @param {String} b The updated version of the string
 | 
				
			||||||
 * @return {SimpleDiff} The diff description.
 | 
					 * @return {SimpleDiff} The diff description.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export default function simpleDiff (a, b) {
 | 
					export const simpleDiff = (a, b) => {
 | 
				
			||||||
  let left = 0 // number of same characters counting from left
 | 
					  let left = 0 // number of same characters counting from left
 | 
				
			||||||
  let right = 0 // number of same characters counting from right
 | 
					  let right = 0 // number of same characters counting from right
 | 
				
			||||||
  while (left < a.length && left < b.length && a[left] === b[left]) {
 | 
					  while (left < a.length && left < b.length && a[left] === b[left]) {
 | 
				
			||||||
@ -1,4 +1,6 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module encoding
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
import * as globals from './globals.js'
 | 
					import * as globals from './globals.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const bits7 = 0b1111111
 | 
					const bits7 = 0b1111111
 | 
				
			||||||
@ -15,10 +17,18 @@ export class Encoder {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 | 
					 * @return {Encoder}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
export const createEncoder = () => new Encoder()
 | 
					export const createEncoder = () => new Encoder()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * The current length of the encoded data.
 | 
					 * The current length of the encoded data.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 | 
					 * @param {Encoder} encoder
 | 
				
			||||||
 | 
					 * @return {number}
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const length = encoder => {
 | 
					export const length = encoder => {
 | 
				
			||||||
  let len = encoder.cpos
 | 
					  let len = encoder.cpos
 | 
				
			||||||
@ -30,6 +40,8 @@ export const length = encoder => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Transform to ArrayBuffer. TODO: rename to .toArrayBuffer
 | 
					 * Transform to ArrayBuffer. TODO: rename to .toArrayBuffer
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Encoder} encoder
 | 
					 * @param {Encoder} encoder
 | 
				
			||||||
 * @return {ArrayBuffer} The created ArrayBuffer.
 | 
					 * @return {ArrayBuffer} The created ArrayBuffer.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -48,6 +60,7 @@ export const toBuffer = encoder => {
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Write one byte to the encoder.
 | 
					 * Write one byte to the encoder.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Encoder} encoder
 | 
					 * @param {Encoder} encoder
 | 
				
			||||||
 * @param {number} num The byte that is to be encoded.
 | 
					 * @param {number} num The byte that is to be encoded.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -64,6 +77,7 @@ export const write = (encoder, num) => {
 | 
				
			|||||||
 * Write one byte at a specific position.
 | 
					 * Write one byte at a specific position.
 | 
				
			||||||
 * Position must already be written (i.e. encoder.length > pos)
 | 
					 * Position must already be written (i.e. encoder.length > pos)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Encoder} encoder
 | 
					 * @param {Encoder} encoder
 | 
				
			||||||
 * @param {number} pos Position to which to write data
 | 
					 * @param {number} pos Position to which to write data
 | 
				
			||||||
 * @param {number} num Unsigned 8-bit integer
 | 
					 * @param {number} num Unsigned 8-bit integer
 | 
				
			||||||
@ -89,6 +103,7 @@ export const set = (encoder, pos, num) => {
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Write one byte as an unsigned integer.
 | 
					 * Write one byte as an unsigned integer.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Encoder} encoder
 | 
					 * @param {Encoder} encoder
 | 
				
			||||||
 * @param {number} num The number that is to be encoded.
 | 
					 * @param {number} num The number that is to be encoded.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -97,6 +112,7 @@ export const writeUint8 = (encoder, num) => write(encoder, num & bits8)
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Write one byte as an unsigned Integer at a specific location.
 | 
					 * Write one byte as an unsigned Integer at a specific location.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Encoder} encoder
 | 
					 * @param {Encoder} encoder
 | 
				
			||||||
 * @param {number} pos The location where the data will be written.
 | 
					 * @param {number} pos The location where the data will be written.
 | 
				
			||||||
 * @param {number} num The number that is to be encoded.
 | 
					 * @param {number} num The number that is to be encoded.
 | 
				
			||||||
@ -106,6 +122,7 @@ export const setUint8 = (encoder, pos, num) => set(encoder, pos, num & bits8)
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Write two bytes as an unsigned integer.
 | 
					 * Write two bytes as an unsigned integer.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Encoder} encoder
 | 
					 * @param {Encoder} encoder
 | 
				
			||||||
 * @param {number} num The number that is to be encoded.
 | 
					 * @param {number} num The number that is to be encoded.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -116,6 +133,7 @@ export const writeUint16 = (encoder, num) => {
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Write two bytes as an unsigned integer at a specific location.
 | 
					 * Write two bytes as an unsigned integer at a specific location.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Encoder} encoder
 | 
					 * @param {Encoder} encoder
 | 
				
			||||||
 * @param {number} pos The location where the data will be written.
 | 
					 * @param {number} pos The location where the data will be written.
 | 
				
			||||||
 * @param {number} num The number that is to be encoded.
 | 
					 * @param {number} num The number that is to be encoded.
 | 
				
			||||||
@ -128,6 +146,7 @@ export const setUint16 = (encoder, pos, num) => {
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Write two bytes as an unsigned integer
 | 
					 * Write two bytes as an unsigned integer
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Encoder} encoder
 | 
					 * @param {Encoder} encoder
 | 
				
			||||||
 * @param {number} num The number that is to be encoded.
 | 
					 * @param {number} num The number that is to be encoded.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -141,6 +160,7 @@ export const writeUint32 = (encoder, num) => {
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Write two bytes as an unsigned integer at a specific location.
 | 
					 * Write two bytes as an unsigned integer at a specific location.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Encoder} encoder
 | 
					 * @param {Encoder} encoder
 | 
				
			||||||
 * @param {number} pos The location where the data will be written.
 | 
					 * @param {number} pos The location where the data will be written.
 | 
				
			||||||
 * @param {number} num The number that is to be encoded.
 | 
					 * @param {number} num The number that is to be encoded.
 | 
				
			||||||
@ -157,6 +177,7 @@ export const setUint32 = (encoder, pos, num) => {
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * Encodes integers in the range from [0, 4294967295] / [0, 0xffffffff]. (max 32 bit unsigned integer)
 | 
					 * Encodes integers in the range from [0, 4294967295] / [0, 0xffffffff]. (max 32 bit unsigned integer)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Encoder} encoder
 | 
					 * @param {Encoder} encoder
 | 
				
			||||||
 * @param {number} num The number that is to be encoded.
 | 
					 * @param {number} num The number that is to be encoded.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -171,6 +192,7 @@ export const writeVarUint = (encoder, num) => {
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Write a variable length string.
 | 
					 * Write a variable length string.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Encoder} encoder
 | 
					 * @param {Encoder} encoder
 | 
				
			||||||
 * @param {String} str The string that is to be encoded.
 | 
					 * @param {String} str The string that is to be encoded.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -188,6 +210,7 @@ export const writeVarString = (encoder, str) => {
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * TODO: can be improved!
 | 
					 * TODO: can be improved!
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Encoder} encoder The enUint8Arr
 | 
					 * @param {Encoder} encoder The enUint8Arr
 | 
				
			||||||
 * @param {Encoder} append The BinaryEncoder to be written.
 | 
					 * @param {Encoder} append The BinaryEncoder to be written.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -196,6 +219,7 @@ export const writeBinaryEncoder = (encoder, append) => writeArrayBuffer(encoder,
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Append an arrayBuffer to the encoder.
 | 
					 * Append an arrayBuffer to the encoder.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Encoder} encoder
 | 
					 * @param {Encoder} encoder
 | 
				
			||||||
 * @param {ArrayBuffer} arrayBuffer
 | 
					 * @param {ArrayBuffer} arrayBuffer
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -209,6 +233,7 @@ export const writeArrayBuffer = (encoder, arrayBuffer) => {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 | 
					 * @function
 | 
				
			||||||
 * @param {Encoder} encoder
 | 
					 * @param {Encoder} encoder
 | 
				
			||||||
 * @param {ArrayBuffer} arrayBuffer
 | 
					 * @param {ArrayBuffer} arrayBuffer
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,7 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module globals
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* eslint-env browser */
 | 
					/* eslint-env browser */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const Uint8Array_ = Uint8Array
 | 
					export const Uint8Array_ = Uint8Array
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,7 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module idb
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* eslint-env browser */
 | 
					/* eslint-env browser */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import * as globals from './globals.js'
 | 
					import * as globals from './globals.js'
 | 
				
			||||||
@ -115,7 +119,7 @@ export const getAllKeysValues = (store, range) =>
 | 
				
			|||||||
 * Iterate on keys and values
 | 
					 * Iterate on keys and values
 | 
				
			||||||
 * @param {IDBObjectStore} store
 | 
					 * @param {IDBObjectStore} store
 | 
				
			||||||
 * @param {IDBKeyRange?} keyrange
 | 
					 * @param {IDBKeyRange?} keyrange
 | 
				
			||||||
 * @param {function(any, any)} f Return true in order to continue the cursor
 | 
					 * @param {Function} f Return true in order to continue the cursor
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const iterate = (store, keyrange, f) => globals.createPromise((resolve, reject) => {
 | 
					export const iterate = (store, keyrange, f) => globals.createPromise((resolve, reject) => {
 | 
				
			||||||
  const request = store.openCursor(keyrange)
 | 
					  const request = store.openCursor(keyrange)
 | 
				
			||||||
@ -135,9 +139,10 @@ export const iterate = (store, keyrange, f) => globals.createPromise((resolve, r
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Iterate on the keys (no values)
 | 
					 * Iterate on the keys (no values)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 * @param {IDBObjectStore} store
 | 
					 * @param {IDBObjectStore} store
 | 
				
			||||||
 * @param {IDBKeyRange} keyrange
 | 
					 * @param {IDBKeyRange} keyrange
 | 
				
			||||||
 * @param {function(IDBCursor)} f Call `idbcursor.continue()` to iterate further
 | 
					 * @param {function} f Call `idbcursor.continue()` to iterate further
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const iterateKeys = (store, keyrange, f) => {
 | 
					export const iterateKeys = (store, keyrange, f) => {
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
import * as test from './test.js'
 | 
					import * as test from './testing.js'
 | 
				
			||||||
import * as idb from './idb.js'
 | 
					import * as idb from './idb.js'
 | 
				
			||||||
import * as logging from './logging.js'
 | 
					import * as logging from './logging.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,6 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module logging
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import * as globals from './globals.js'
 | 
					import * as globals from './globals.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,2 +1,4 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module math
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
export const floor = Math.floor
 | 
					export const floor = Math.floor
 | 
				
			||||||
 | 
				
			|||||||
@ -4,11 +4,10 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * @example
 | 
					 * @example
 | 
				
			||||||
 * const mutex = createMutex()
 | 
					 * const mutex = createMutex()
 | 
				
			||||||
 * mutex(function () {
 | 
					 * mutex(() => {
 | 
				
			||||||
 *   // This function is immediately executed
 | 
					 *   // This function is immediately executed
 | 
				
			||||||
 *   mutex(function () {
 | 
					 *   mutex(() => {
 | 
				
			||||||
 *     // This function is never executed, as it is called with the same
 | 
					 *     // This function is not executed, as the mutex is already active.
 | 
				
			||||||
 *     // mutex function
 | 
					 | 
				
			||||||
 *   })
 | 
					 *   })
 | 
				
			||||||
 * })
 | 
					 * })
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
				
			|||||||
@ -1,2 +1,6 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module number
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER
 | 
					export const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER
 | 
				
			||||||
export const MIN_SAFE_INTEGER = Number.MIN_SAFE_INTEGER
 | 
					export const MIN_SAFE_INTEGER = Number.MIN_SAFE_INTEGER
 | 
				
			||||||
 | 
				
			|||||||
@ -1,11 +1,12 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module prng
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
const N = 624
 | 
					const N = 624
 | 
				
			||||||
const M = 397
 | 
					const M = 397
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function twist (u, v) {
 | 
					const twist = (u, v) => ((((u & 0x80000000) | (v & 0x7fffffff)) >>> 1) ^ ((v & 1) ? 0x9908b0df : 0))
 | 
				
			||||||
  return ((((u & 0x80000000) | (v & 0x7fffffff)) >>> 1) ^ ((v & 1) ? 0x9908b0df : 0))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
function nextState (state) {
 | 
					const nextState = (state) => {
 | 
				
			||||||
  let p = 0
 | 
					  let p = 0
 | 
				
			||||||
  let j
 | 
					  let j
 | 
				
			||||||
  for (j = N - M + 1; --j; p++) {
 | 
					  for (j = N - M + 1; --j; p++) {
 | 
				
			||||||
@ -29,7 +30,7 @@ function nextState (state) {
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * @public
 | 
					 * @public
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export default class Mt19937 {
 | 
					export class Mt19937 {
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * @param {Number} seed The starting point for the random number generation. If you use the same seed, the generator will return the same sequence of random numbers.
 | 
					   * @param {Number} seed The starting point for the random number generation. If you use the same seed, the generator will return the same sequence of random numbers.
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
@ -1,13 +1,16 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module prng
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Mt19937 from './Mt19937.js'
 | 
					import { Mt19937 } from './Mt19937.js'
 | 
				
			||||||
import Xoroshiro128plus from './Xoroshiro128plus.js'
 | 
					import { Xoroshiro128plus } from './Xoroshiro128plus.js'
 | 
				
			||||||
import Xorshift32 from './Xorshift32.js'
 | 
					import { Xorshift32 } from './Xorshift32.js'
 | 
				
			||||||
import * as time from '../../time.js'
 | 
					import * as time from '../../time.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const DIAMETER = 300
 | 
					const DIAMETER = 300
 | 
				
			||||||
const NUMBERS = 10000
 | 
					const NUMBERS = 10000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function runPRNG (name, Gen) {
 | 
					const runPRNG = (name, Gen) => {
 | 
				
			||||||
  console.log('== ' + name + ' ==')
 | 
					  console.log('== ' + name + ' ==')
 | 
				
			||||||
  const gen = new Gen(1234)
 | 
					  const gen = new Gen(1234)
 | 
				
			||||||
  let head = 0
 | 
					  let head = 0
 | 
				
			||||||
@ -1,5 +1,8 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module prng
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Xorshift32 from './Xorshift32.js'
 | 
					import { Xorshift32 } from './Xorshift32.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * This is a variant of xoroshiro128plus - the fastest full-period generator passing BigCrush without systematic failures.
 | 
					 * This is a variant of xoroshiro128plus - the fastest full-period generator passing BigCrush without systematic failures.
 | 
				
			||||||
@ -14,7 +17,7 @@ import Xorshift32 from './Xorshift32.js'
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * [Reference implementation](http://vigna.di.unimi.it/xorshift/xoroshiro128plus.c)
 | 
					 * [Reference implementation](http://vigna.di.unimi.it/xorshift/xoroshiro128plus.c)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export default class Xoroshiro128plus {
 | 
					export class Xoroshiro128plus {
 | 
				
			||||||
  constructor (seed) {
 | 
					  constructor (seed) {
 | 
				
			||||||
    this.seed = seed
 | 
					    this.seed = seed
 | 
				
			||||||
    // This is a variant of Xoroshiro128plus to fill the initial state
 | 
					    // This is a variant of Xoroshiro128plus to fill the initial state
 | 
				
			||||||
@ -1,8 +1,11 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module prng
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Xorshift32 is a very simple but elegang PRNG with a period of `2^32-1`.
 | 
					 * Xorshift32 is a very simple but elegang PRNG with a period of `2^32-1`.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export default class Xorshift32 {
 | 
					export class Xorshift32 {
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * @param {number} seed The starting point for the random number generation. If you use the same seed, the generator will return the same sequence of random numbers.
 | 
					   * @param {number} seed The starting point for the random number generation. If you use the same seed, the generator will return the same sequence of random numbers.
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
@ -1,10 +1,13 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module prng
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import * as binary from '../binary.js'
 | 
					import * as binary from '../binary.js'
 | 
				
			||||||
import { fromCharCode, fromCodePoint } from '../string.js'
 | 
					import { fromCharCode, fromCodePoint } from '../string.js'
 | 
				
			||||||
import { MAX_SAFE_INTEGER, MIN_SAFE_INTEGER } from '../number.js'
 | 
					import { MAX_SAFE_INTEGER, MIN_SAFE_INTEGER } from '../number.js'
 | 
				
			||||||
import * as math from '../math.js'
 | 
					import * as math from '../math.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import DefaultPRNG from './PRNG/Xoroshiro128plus.js'
 | 
					import { Xoroshiro128plus as DefaultPRNG } from './PRNG/Xoroshiro128plus.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Description of the function
 | 
					 * Description of the function
 | 
				
			||||||
@ -1,3 +1,7 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module prng
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 *TODO: enable tests
 | 
					 *TODO: enable tests
 | 
				
			||||||
import * as rt from '../rich-text/formatters.mjs'
 | 
					import * as rt from '../rich-text/formatters.mjs'
 | 
				
			||||||
							
								
								
									
										3
									
								
								lib/random.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								lib/random.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module random
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
@ -1,2 +1,6 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module string
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const fromCharCode = String.fromCharCode
 | 
					export const fromCharCode = String.fromCharCode
 | 
				
			||||||
export const fromCodePoint = String.fromCodePoint
 | 
					export const fromCodePoint = String.fromCodePoint
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,9 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module testing
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import * as logging from './logging.js'
 | 
					import * as logging from './logging.js'
 | 
				
			||||||
import simpleDiff from './simpleDiff.js'
 | 
					import { simpleDiff } from './diff.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const run = async (name, f) => {
 | 
					export const run = async (name, f) => {
 | 
				
			||||||
  console.log(`%cStart:%c   ${name}`, 'color:blue;', '')
 | 
					  console.log(`%cStart:%c   ${name}`, 'color:blue;', '')
 | 
				
			||||||
							
								
								
									
										376
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										376
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -4,6 +4,63 @@
 | 
				
			|||||||
  "lockfileVersion": 1,
 | 
					  "lockfileVersion": 1,
 | 
				
			||||||
  "requires": true,
 | 
					  "requires": true,
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
 | 
					    "@babel/code-frame": {
 | 
				
			||||||
 | 
					      "version": "7.0.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==",
 | 
				
			||||||
 | 
					      "dev": true,
 | 
				
			||||||
 | 
					      "requires": {
 | 
				
			||||||
 | 
					        "@babel/highlight": "^7.0.0"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "@babel/highlight": {
 | 
				
			||||||
 | 
					      "version": "7.0.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==",
 | 
				
			||||||
 | 
					      "dev": true,
 | 
				
			||||||
 | 
					      "requires": {
 | 
				
			||||||
 | 
					        "chalk": "^2.0.0",
 | 
				
			||||||
 | 
					        "esutils": "^2.0.2",
 | 
				
			||||||
 | 
					        "js-tokens": "^4.0.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "ansi-styles": {
 | 
				
			||||||
 | 
					          "version": "3.2.1",
 | 
				
			||||||
 | 
					          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
 | 
				
			||||||
 | 
					          "dev": true,
 | 
				
			||||||
 | 
					          "requires": {
 | 
				
			||||||
 | 
					            "color-convert": "^1.9.0"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "chalk": {
 | 
				
			||||||
 | 
					          "version": "2.4.1",
 | 
				
			||||||
 | 
					          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
 | 
				
			||||||
 | 
					          "dev": true,
 | 
				
			||||||
 | 
					          "requires": {
 | 
				
			||||||
 | 
					            "ansi-styles": "^3.2.1",
 | 
				
			||||||
 | 
					            "escape-string-regexp": "^1.0.5",
 | 
				
			||||||
 | 
					            "supports-color": "^5.3.0"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "js-tokens": {
 | 
				
			||||||
 | 
					          "version": "4.0.0",
 | 
				
			||||||
 | 
					          "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
 | 
				
			||||||
 | 
					          "dev": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "supports-color": {
 | 
				
			||||||
 | 
					          "version": "5.5.0",
 | 
				
			||||||
 | 
					          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
 | 
				
			||||||
 | 
					          "dev": true,
 | 
				
			||||||
 | 
					          "requires": {
 | 
				
			||||||
 | 
					            "has-flag": "^3.0.0"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "@types/estree": {
 | 
					    "@types/estree": {
 | 
				
			||||||
      "version": "0.0.38",
 | 
					      "version": "0.0.38",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.38.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.38.tgz",
 | 
				
			||||||
@ -110,17 +167,6 @@
 | 
				
			|||||||
      "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=",
 | 
					      "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "align-text": {
 | 
					 | 
				
			||||||
      "version": "0.1.4",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
 | 
					 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "kind-of": "^3.0.2",
 | 
					 | 
				
			||||||
        "longest": "^1.0.1",
 | 
					 | 
				
			||||||
        "repeat-string": "^1.5.2"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "ansi-escapes": {
 | 
					    "ansi-escapes": {
 | 
				
			||||||
      "version": "3.1.0",
 | 
					      "version": "3.1.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
 | 
				
			||||||
@ -1577,6 +1623,12 @@
 | 
				
			|||||||
      "integrity": "sha1-SOyNFt9Dd+rl+liEaCSAr02Vx3Q=",
 | 
					      "integrity": "sha1-SOyNFt9Dd+rl+liEaCSAr02Vx3Q=",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "bluebird": {
 | 
				
			||||||
 | 
					      "version": "3.5.3",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==",
 | 
				
			||||||
 | 
					      "dev": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "boolbase": {
 | 
					    "boolbase": {
 | 
				
			||||||
      "version": "1.0.0",
 | 
					      "version": "1.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
 | 
				
			||||||
@ -1631,12 +1683,6 @@
 | 
				
			|||||||
      "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
 | 
					      "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "camelcase": {
 | 
					 | 
				
			||||||
      "version": "1.2.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "camelcase-keys": {
 | 
					    "camelcase-keys": {
 | 
				
			||||||
      "version": "2.1.0",
 | 
					      "version": "2.1.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
 | 
				
			||||||
@ -1662,22 +1708,13 @@
 | 
				
			|||||||
      "dev": true,
 | 
					      "dev": true,
 | 
				
			||||||
      "optional": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "center-align": {
 | 
					    "catharsis": {
 | 
				
			||||||
      "version": "0.1.3",
 | 
					      "version": "0.8.9",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz",
 | 
				
			||||||
      "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
 | 
					      "integrity": "sha1-mMyJDKZS3S7w5ws3klMQ/56Q/Is=",
 | 
				
			||||||
      "dev": true,
 | 
					      "dev": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "align-text": "^0.1.3",
 | 
					        "underscore-contrib": "~0.3.0"
 | 
				
			||||||
        "lazy-cache": "^1.0.3"
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "dependencies": {
 | 
					 | 
				
			||||||
        "lazy-cache": {
 | 
					 | 
				
			||||||
          "version": "1.0.4",
 | 
					 | 
				
			||||||
          "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
 | 
					 | 
				
			||||||
          "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=",
 | 
					 | 
				
			||||||
          "dev": true
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "chalk": {
 | 
					    "chalk": {
 | 
				
			||||||
@ -1761,17 +1798,6 @@
 | 
				
			|||||||
      "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
 | 
					      "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "cliui": {
 | 
					 | 
				
			||||||
      "version": "2.1.0",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
 | 
					 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "center-align": "^0.1.1",
 | 
					 | 
				
			||||||
        "right-align": "^0.1.1",
 | 
					 | 
				
			||||||
        "wordwrap": "0.0.2"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "clone": {
 | 
					    "clone": {
 | 
				
			||||||
      "version": "2.1.2",
 | 
					      "version": "2.1.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
 | 
				
			||||||
@ -3079,9 +3105,9 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "extend": {
 | 
					    "extend": {
 | 
				
			||||||
      "version": "3.0.1",
 | 
					      "version": "3.0.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
 | 
				
			||||||
      "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=",
 | 
					      "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "extend-shallow": {
 | 
					    "extend-shallow": {
 | 
				
			||||||
@ -3984,6 +4010,12 @@
 | 
				
			|||||||
      "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
 | 
					      "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "graceful-readlink": {
 | 
				
			||||||
 | 
					      "version": "1.0.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
 | 
				
			||||||
 | 
					      "dev": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "har-schema": {
 | 
					    "har-schema": {
 | 
				
			||||||
      "version": "2.0.0",
 | 
					      "version": "2.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
 | 
				
			||||||
@ -4585,6 +4617,15 @@
 | 
				
			|||||||
      "dev": true,
 | 
					      "dev": true,
 | 
				
			||||||
      "optional": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "jest-worker": {
 | 
				
			||||||
 | 
					      "version": "23.2.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-23.2.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha1-+vcGqNo2+uYOsmlXJX+ntdjqArk=",
 | 
				
			||||||
 | 
					      "dev": true,
 | 
				
			||||||
 | 
					      "requires": {
 | 
				
			||||||
 | 
					        "merge-stream": "^1.0.1"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "js-tokens": {
 | 
					    "js-tokens": {
 | 
				
			||||||
      "version": "3.0.2",
 | 
					      "version": "3.0.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
 | 
				
			||||||
@ -4609,12 +4650,69 @@
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "js2xmlparser": {
 | 
				
			||||||
 | 
					      "version": "3.0.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha1-P7YOqgicVED5MZ9RdgzNB+JJlzM=",
 | 
				
			||||||
 | 
					      "dev": true,
 | 
				
			||||||
 | 
					      "requires": {
 | 
				
			||||||
 | 
					        "xmlcreate": "^1.0.1"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "jsbn": {
 | 
					    "jsbn": {
 | 
				
			||||||
      "version": "0.1.1",
 | 
					      "version": "0.1.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
 | 
				
			||||||
      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
 | 
					      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "jsdoc": {
 | 
				
			||||||
 | 
					      "version": "3.5.5",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.5.5.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-6PxB65TAU4WO0Wzyr/4/YhlGovXl0EVYfpKbpSroSj0qBxT4/xod/l40Opkm38dRHRdQgdeY836M0uVnJQG7kg==",
 | 
				
			||||||
 | 
					      "dev": true,
 | 
				
			||||||
 | 
					      "requires": {
 | 
				
			||||||
 | 
					        "babylon": "7.0.0-beta.19",
 | 
				
			||||||
 | 
					        "bluebird": "~3.5.0",
 | 
				
			||||||
 | 
					        "catharsis": "~0.8.9",
 | 
				
			||||||
 | 
					        "escape-string-regexp": "~1.0.5",
 | 
				
			||||||
 | 
					        "js2xmlparser": "~3.0.0",
 | 
				
			||||||
 | 
					        "klaw": "~2.0.0",
 | 
				
			||||||
 | 
					        "marked": "~0.3.6",
 | 
				
			||||||
 | 
					        "mkdirp": "~0.5.1",
 | 
				
			||||||
 | 
					        "requizzle": "~0.2.1",
 | 
				
			||||||
 | 
					        "strip-json-comments": "~2.0.1",
 | 
				
			||||||
 | 
					        "taffydb": "2.6.2",
 | 
				
			||||||
 | 
					        "underscore": "~1.8.3"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "babylon": {
 | 
				
			||||||
 | 
					          "version": "7.0.0-beta.19",
 | 
				
			||||||
 | 
					          "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A==",
 | 
				
			||||||
 | 
					          "dev": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "klaw": {
 | 
				
			||||||
 | 
					          "version": "2.0.0",
 | 
				
			||||||
 | 
					          "resolved": "https://registry.npmjs.org/klaw/-/klaw-2.0.0.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha1-WcEo4Nxc5BAgEVEZTuucv4WGUPY=",
 | 
				
			||||||
 | 
					          "dev": true,
 | 
				
			||||||
 | 
					          "requires": {
 | 
				
			||||||
 | 
					            "graceful-fs": "^4.1.9"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "taffydb": {
 | 
				
			||||||
 | 
					          "version": "2.6.2",
 | 
				
			||||||
 | 
					          "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=",
 | 
				
			||||||
 | 
					          "dev": true
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "jsdoc-template": {
 | 
				
			||||||
 | 
					      "version": "git+ssh://git@github.com/braintree/jsdoc-template.git#ec0e3c0ec95de6b4e928af3285bbf69aac2f25b6",
 | 
				
			||||||
 | 
					      "from": "git+ssh://git@github.com/braintree/jsdoc-template.git#3.3.0",
 | 
				
			||||||
 | 
					      "dev": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "jsdom": {
 | 
					    "jsdom": {
 | 
				
			||||||
      "version": "7.2.2",
 | 
					      "version": "7.2.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-7.2.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-7.2.2.tgz",
 | 
				
			||||||
@ -5009,12 +5107,6 @@
 | 
				
			|||||||
      "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=",
 | 
					      "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "longest": {
 | 
					 | 
				
			||||||
      "version": "1.0.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "loose-envify": {
 | 
					    "loose-envify": {
 | 
				
			||||||
      "version": "1.3.1",
 | 
					      "version": "1.3.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
 | 
				
			||||||
@ -5120,6 +5212,15 @@
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "merge-stream": {
 | 
				
			||||||
 | 
					      "version": "1.0.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=",
 | 
				
			||||||
 | 
					      "dev": true,
 | 
				
			||||||
 | 
					      "requires": {
 | 
				
			||||||
 | 
					        "readable-stream": "^2.0.1"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "micromatch": {
 | 
					    "micromatch": {
 | 
				
			||||||
      "version": "2.3.11",
 | 
					      "version": "2.3.11",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
 | 
				
			||||||
@ -5424,7 +5525,7 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    "parchment": {
 | 
					    "parchment": {
 | 
				
			||||||
      "version": "1.1.4",
 | 
					      "version": "1.1.4",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz",
 | 
					      "resolved": "http://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz",
 | 
				
			||||||
      "integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==",
 | 
					      "integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@ -5848,7 +5949,7 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    "quill": {
 | 
					    "quill": {
 | 
				
			||||||
      "version": "1.3.6",
 | 
					      "version": "1.3.6",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/quill/-/quill-1.3.6.tgz",
 | 
					      "resolved": "http://registry.npmjs.org/quill/-/quill-1.3.6.tgz",
 | 
				
			||||||
      "integrity": "sha512-K0mvhimWZN6s+9OQ249CH2IEPZ9JmkFuCQeHAOQax3EZ2nDJ3wfGh59mnlQaZV2i7u8eFarx6wAtvQKgShojug==",
 | 
					      "integrity": "sha512-K0mvhimWZN6s+9OQ249CH2IEPZ9JmkFuCQeHAOQax3EZ2nDJ3wfGh59mnlQaZV2i7u8eFarx6wAtvQKgShojug==",
 | 
				
			||||||
      "dev": true,
 | 
					      "dev": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
@ -5879,14 +5980,6 @@
 | 
				
			|||||||
        "deep-equal": "^1.0.1",
 | 
					        "deep-equal": "^1.0.1",
 | 
				
			||||||
        "extend": "^3.0.2",
 | 
					        "extend": "^3.0.2",
 | 
				
			||||||
        "fast-diff": "1.1.2"
 | 
					        "fast-diff": "1.1.2"
 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "dependencies": {
 | 
					 | 
				
			||||||
        "extend": {
 | 
					 | 
				
			||||||
          "version": "3.0.2",
 | 
					 | 
				
			||||||
          "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
 | 
					 | 
				
			||||||
          "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
 | 
					 | 
				
			||||||
          "dev": true
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "randomatic": {
 | 
					    "randomatic": {
 | 
				
			||||||
@ -6198,6 +6291,23 @@
 | 
				
			|||||||
        "resolve-from": "^1.0.0"
 | 
					        "resolve-from": "^1.0.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "requizzle": {
 | 
				
			||||||
 | 
					      "version": "0.2.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha1-aUPDUwxNmn5G8c3dUcFY/GcM294=",
 | 
				
			||||||
 | 
					      "dev": true,
 | 
				
			||||||
 | 
					      "requires": {
 | 
				
			||||||
 | 
					        "underscore": "~1.6.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "underscore": {
 | 
				
			||||||
 | 
					          "version": "1.6.0",
 | 
				
			||||||
 | 
					          "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=",
 | 
				
			||||||
 | 
					          "dev": true
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "resolve": {
 | 
					    "resolve": {
 | 
				
			||||||
      "version": "1.3.3",
 | 
					      "version": "1.3.3",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz",
 | 
				
			||||||
@ -6233,15 +6343,6 @@
 | 
				
			|||||||
        "signal-exit": "^3.0.2"
 | 
					        "signal-exit": "^3.0.2"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "right-align": {
 | 
					 | 
				
			||||||
      "version": "0.1.3",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
 | 
					 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "align-text": "^0.1.1"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "rimraf": {
 | 
					    "rimraf": {
 | 
				
			||||||
      "version": "2.6.2",
 | 
					      "version": "2.6.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
 | 
				
			||||||
@ -6380,12 +6481,46 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "rollup-plugin-uglify": {
 | 
					    "rollup-plugin-uglify": {
 | 
				
			||||||
      "version": "1.0.2",
 | 
					      "version": "6.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/rollup-plugin-uglify/-/rollup-plugin-uglify-1.0.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/rollup-plugin-uglify/-/rollup-plugin-uglify-6.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha1-1KpvXfE1Iurhuhd4DHxMcJYDg1k=",
 | 
					      "integrity": "sha512-XtzZd159QuOaXNvcxyBcbUCSoBsv5YYWK+7ZwUyujSmISst8avRfjWlp7cGu8T2O52OJnpEBvl+D4WLV1k1iQQ==",
 | 
				
			||||||
      "dev": true,
 | 
					      "dev": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "uglify-js": "^2.6.1"
 | 
					        "@babel/code-frame": "^7.0.0",
 | 
				
			||||||
 | 
					        "jest-worker": "^23.2.0",
 | 
				
			||||||
 | 
					        "serialize-javascript": "^1.5.0",
 | 
				
			||||||
 | 
					        "uglify-js": "^3.4.9"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "rollup-plugin-uglify-es": {
 | 
				
			||||||
 | 
					      "version": "0.0.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/rollup-plugin-uglify-es/-/rollup-plugin-uglify-es-0.0.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha1-5FZE8raFpZq9uTY0ByB6A6e1qbc=",
 | 
				
			||||||
 | 
					      "dev": true,
 | 
				
			||||||
 | 
					      "requires": {
 | 
				
			||||||
 | 
					        "uglify-es": "3.0.3"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "commander": {
 | 
				
			||||||
 | 
					          "version": "2.9.0",
 | 
				
			||||||
 | 
					          "resolved": "http://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=",
 | 
				
			||||||
 | 
					          "dev": true,
 | 
				
			||||||
 | 
					          "requires": {
 | 
				
			||||||
 | 
					            "graceful-readlink": ">= 1.0.0"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "uglify-es": {
 | 
				
			||||||
 | 
					          "version": "3.0.3",
 | 
				
			||||||
 | 
					          "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.0.3.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha1-Y8yEqpRos0lzpIh3h8ZMAaiodXY=",
 | 
				
			||||||
 | 
					          "dev": true,
 | 
				
			||||||
 | 
					          "requires": {
 | 
				
			||||||
 | 
					            "commander": "~2.9.0",
 | 
				
			||||||
 | 
					            "source-map": "~0.5.1",
 | 
				
			||||||
 | 
					            "uglify-to-browserify": "~1.0.0"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "rollup-pluginutils": {
 | 
					    "rollup-pluginutils": {
 | 
				
			||||||
@ -6483,6 +6618,12 @@
 | 
				
			|||||||
      "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
 | 
					      "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "serialize-javascript": {
 | 
				
			||||||
 | 
					      "version": "1.5.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==",
 | 
				
			||||||
 | 
					      "dev": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "serve-index": {
 | 
					    "serve-index": {
 | 
				
			||||||
      "version": "1.9.1",
 | 
					      "version": "1.9.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
 | 
				
			||||||
@ -6974,6 +7115,15 @@
 | 
				
			|||||||
      "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
 | 
					      "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "tui-jsdoc-template": {
 | 
				
			||||||
 | 
					      "version": "1.2.2",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/tui-jsdoc-template/-/tui-jsdoc-template-1.2.2.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-oqw0IYaot86VJ2owKBozJnilgta0Z55x8r9PeHj7vb+jDoSvJGRUQUcgs56SZh9HE20fx54Pe75p84X85/ygLA==",
 | 
				
			||||||
 | 
					      "dev": true,
 | 
				
			||||||
 | 
					      "requires": {
 | 
				
			||||||
 | 
					        "cheerio": "^0.22.0"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "tunnel-agent": {
 | 
					    "tunnel-agent": {
 | 
				
			||||||
      "version": "0.6.0",
 | 
					      "version": "0.6.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
 | 
				
			||||||
@ -7012,14 +7162,27 @@
 | 
				
			|||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "uglify-js": {
 | 
					    "uglify-js": {
 | 
				
			||||||
      "version": "2.8.29",
 | 
					      "version": "3.4.9",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz",
 | 
				
			||||||
      "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
 | 
					      "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==",
 | 
				
			||||||
      "dev": true,
 | 
					      "dev": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "source-map": "~0.5.1",
 | 
					        "commander": "~2.17.1",
 | 
				
			||||||
        "uglify-to-browserify": "~1.0.0",
 | 
					        "source-map": "~0.6.1"
 | 
				
			||||||
        "yargs": "~3.10.0"
 | 
					      },
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "commander": {
 | 
				
			||||||
 | 
					          "version": "2.17.1",
 | 
				
			||||||
 | 
					          "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==",
 | 
				
			||||||
 | 
					          "dev": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "source-map": {
 | 
				
			||||||
 | 
					          "version": "0.6.1",
 | 
				
			||||||
 | 
					          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
 | 
				
			||||||
 | 
					          "dev": true
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "uglify-to-browserify": {
 | 
					    "uglify-to-browserify": {
 | 
				
			||||||
@ -7029,6 +7192,29 @@
 | 
				
			|||||||
      "dev": true,
 | 
					      "dev": true,
 | 
				
			||||||
      "optional": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "underscore": {
 | 
				
			||||||
 | 
					      "version": "1.8.3",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=",
 | 
				
			||||||
 | 
					      "dev": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "underscore-contrib": {
 | 
				
			||||||
 | 
					      "version": "0.3.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha1-ZltmwkeD+PorGMn4y7Dix9SMJsc=",
 | 
				
			||||||
 | 
					      "dev": true,
 | 
				
			||||||
 | 
					      "requires": {
 | 
				
			||||||
 | 
					        "underscore": "1.6.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "underscore": {
 | 
				
			||||||
 | 
					          "version": "1.6.0",
 | 
				
			||||||
 | 
					          "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=",
 | 
				
			||||||
 | 
					          "dev": true
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "uniq": {
 | 
					    "uniq": {
 | 
				
			||||||
      "version": "1.0.1",
 | 
					      "version": "1.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz",
 | 
				
			||||||
@ -7173,18 +7359,6 @@
 | 
				
			|||||||
        "isexe": "^2.0.0"
 | 
					        "isexe": "^2.0.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "window-size": {
 | 
					 | 
				
			||||||
      "version": "0.1.0",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "wordwrap": {
 | 
					 | 
				
			||||||
      "version": "0.0.2",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=",
 | 
					 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "wrappy": {
 | 
					    "wrappy": {
 | 
				
			||||||
      "version": "1.0.2",
 | 
					      "version": "1.0.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
 | 
				
			||||||
@ -7215,6 +7389,12 @@
 | 
				
			|||||||
      "dev": true,
 | 
					      "dev": true,
 | 
				
			||||||
      "optional": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "xmlcreate": {
 | 
				
			||||||
 | 
					      "version": "1.0.2",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-1.0.2.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8=",
 | 
				
			||||||
 | 
					      "dev": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "xtend": {
 | 
					    "xtend": {
 | 
				
			||||||
      "version": "4.0.1",
 | 
					      "version": "4.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
 | 
				
			||||||
@ -7226,18 +7406,6 @@
 | 
				
			|||||||
      "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
 | 
				
			||||||
      "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
 | 
					      "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "yargs": {
 | 
					 | 
				
			||||||
      "version": "3.10.0",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
 | 
					 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "camelcase": "^1.0.2",
 | 
					 | 
				
			||||||
        "cliui": "^2.1.0",
 | 
					 | 
				
			||||||
        "decamelize": "^1.0.0",
 | 
					 | 
				
			||||||
        "window-size": "0.1.0"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										30
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								package.json
									
									
									
									
									
								
							@ -2,17 +2,17 @@
 | 
				
			|||||||
  "name": "yjs",
 | 
					  "name": "yjs",
 | 
				
			||||||
  "version": "13.0.0-72",
 | 
					  "version": "13.0.0-72",
 | 
				
			||||||
  "description": "A framework for real-time p2p shared editing on any data",
 | 
					  "description": "A framework for real-time p2p shared editing on any data",
 | 
				
			||||||
  "main": "./build/node/index.js",
 | 
					  "main": "./build/yjs.js",
 | 
				
			||||||
  "module": "./src/index.js",
 | 
					  "module": "./index.js",
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
    "test": "npm run lint",
 | 
					    "test": "npm run lint",
 | 
				
			||||||
    "debug": "concurrently 'rollup -wc rollup.test.js' 'cutest-serve y.test.js -o'",
 | 
					    "build": "rollup -c",
 | 
				
			||||||
    "lint": "standard src/**/*.js test/**/*.js tests-lib/**/*.js",
 | 
					    "watch": "rollup -wc",
 | 
				
			||||||
    "docs": "esdoc",
 | 
					    "debug": "concurrently 'rollup -wc' 'cutest-serve build/y.test.js -o'",
 | 
				
			||||||
 | 
					    "lint": "standard **/*.js",
 | 
				
			||||||
 | 
					    "docs": "rm -rf docs && jsdoc --configure .jsdoc.json --verbose --readme ./README.md --package ./package.json",
 | 
				
			||||||
    "serve-docs": "npm run docs && serve ./docs/",
 | 
					    "serve-docs": "npm run docs && serve ./docs/",
 | 
				
			||||||
    "dist": "rollup -c rollup.browser.js; rollup -c rollup.node.js",
 | 
					    "postversion": "npm run build"
 | 
				
			||||||
    "watch": "concurrently 'rollup -wc rollup.browser.js' 'rollup -wc rollup.node.js'",
 | 
					 | 
				
			||||||
    "postversion": "npm run dist"
 | 
					 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "files": [
 | 
					  "files": [
 | 
				
			||||||
    "src/*",
 | 
					    "src/*",
 | 
				
			||||||
@ -28,8 +28,10 @@
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  "standard": {
 | 
					  "standard": {
 | 
				
			||||||
    "ignore": [
 | 
					    "ignore": [
 | 
				
			||||||
      "/y.js",
 | 
					      "/build",
 | 
				
			||||||
      "/y.js.map"
 | 
					      "/node_modules",
 | 
				
			||||||
 | 
					      "/rollup.test.js",
 | 
				
			||||||
 | 
					      "/rollup.test.js"
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "repository": {
 | 
					  "repository": {
 | 
				
			||||||
@ -62,6 +64,8 @@
 | 
				
			|||||||
    "cutest": "^0.1.9",
 | 
					    "cutest": "^0.1.9",
 | 
				
			||||||
    "esdoc": "^1.1.0",
 | 
					    "esdoc": "^1.1.0",
 | 
				
			||||||
    "esdoc-standard-plugin": "^1.0.0",
 | 
					    "esdoc-standard-plugin": "^1.0.0",
 | 
				
			||||||
 | 
					    "jsdoc": "^3.5.5",
 | 
				
			||||||
 | 
					    "jsdoc-template": "git@github.com:braintree/jsdoc-template.git#3.3.0",
 | 
				
			||||||
    "prosemirror-example-setup": "^1.0.1",
 | 
					    "prosemirror-example-setup": "^1.0.1",
 | 
				
			||||||
    "prosemirror-schema-basic": "^1.0.0",
 | 
					    "prosemirror-schema-basic": "^1.0.0",
 | 
				
			||||||
    "prosemirror-state": "^1.2.2",
 | 
					    "prosemirror-state": "^1.2.2",
 | 
				
			||||||
@ -74,10 +78,12 @@
 | 
				
			|||||||
    "rollup-plugin-inject": "^2.2.0",
 | 
					    "rollup-plugin-inject": "^2.2.0",
 | 
				
			||||||
    "rollup-plugin-multi-entry": "^2.0.2",
 | 
					    "rollup-plugin-multi-entry": "^2.0.2",
 | 
				
			||||||
    "rollup-plugin-node-resolve": "^3.4.0",
 | 
					    "rollup-plugin-node-resolve": "^3.4.0",
 | 
				
			||||||
    "rollup-plugin-uglify": "^1.0.2",
 | 
					    "rollup-plugin-uglify": "^6.0.0",
 | 
				
			||||||
 | 
					    "rollup-plugin-uglify-es": "0.0.1",
 | 
				
			||||||
    "rollup-regenerator-runtime": "^6.23.1",
 | 
					    "rollup-regenerator-runtime": "^6.23.1",
 | 
				
			||||||
    "rollup-watch": "^3.2.2",
 | 
					    "rollup-watch": "^3.2.2",
 | 
				
			||||||
    "standard": "^11.0.1"
 | 
					    "standard": "^11.0.1",
 | 
				
			||||||
 | 
					    "tui-jsdoc-template": "^1.2.2"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "ws": "^6.1.0"
 | 
					    "ws": "^6.1.0"
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,9 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
import fs from 'fs'
 | 
					import fs from 'fs'
 | 
				
			||||||
import path from 'path'
 | 
					import path from 'path'
 | 
				
			||||||
import * as encoding from '../../lib/encoding.js'
 | 
					import * as encoding from '../lib/encoding.js'
 | 
				
			||||||
import * as decoding from '../../lib/decoding.js'
 | 
					import * as decoding from '../lib/decoding.js'
 | 
				
			||||||
import { createMutualExclude } from '../../lib/mutualExclude.js'
 | 
					import { createMutex } from '../lib/mutex.js'
 | 
				
			||||||
import { encodeUpdate, encodeStructsDS, decodePersisted } from './decodePersisted.js'
 | 
					import { encodeUpdate, encodeStructsDS, decodePersisted } from './decodePersisted.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function createFilePath (persistence, roomName) {
 | 
					function createFilePath (persistence, roomName) {
 | 
				
			||||||
@ -10,10 +11,10 @@ function createFilePath (persistence, roomName) {
 | 
				
			|||||||
  return path.join(persistence.dir, roomName)
 | 
					  return path.join(persistence.dir, roomName)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class FilePersistence {
 | 
					export class FilePersistence {
 | 
				
			||||||
  constructor (dir) {
 | 
					  constructor (dir) {
 | 
				
			||||||
    this.dir = dir
 | 
					    this.dir = dir
 | 
				
			||||||
    this._mutex = createMutualExclude()
 | 
					    this._mutex = createMutex()
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  setRemoteUpdateCounter (roomName, remoteUpdateCounter) {
 | 
					  setRemoteUpdateCounter (roomName, remoteUpdateCounter) {
 | 
				
			||||||
    // TODO: implement
 | 
					    // TODO: implement
 | 
				
			||||||
@ -70,3 +71,4 @@ export default class FilePersistence {
 | 
				
			|||||||
    })
 | 
					    })
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
@ -1,13 +1,9 @@
 | 
				
			|||||||
/* global indexedDB, location, BroadcastChannel */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Y from '../Y.js'
 | 
					 | 
				
			||||||
import { createMutualExclude } from '../../lib/mutualExclude.js'
 | 
					 | 
				
			||||||
import { decodePersisted, encodeStructsDS, encodeUpdate, PERSIST_STRUCTS_DS, PERSIST_UPDATE } from './decodePersisted.js'
 | 
					 | 
				
			||||||
import * as decoding from '../../lib/decoding.js'
 | 
					 | 
				
			||||||
import * as encoding from '../../lib/encoding.js'
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Request to Promise transformer
 | 
					import { Y } from '../utils/Y.js'
 | 
				
			||||||
 */
 | 
					import { createMutex } from '../lib/mutex.js'
 | 
				
			||||||
 | 
					import { decodePersisted, encodeStructsDS, encodeUpdate, PERSIST_STRUCTS_DS, PERSIST_UPDATE } from './decodePersisted.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function rtop (request) {
 | 
					function rtop (request) {
 | 
				
			||||||
  return new Promise(function (resolve, reject) {
 | 
					  return new Promise(function (resolve, reject) {
 | 
				
			||||||
    request.onerror = function (event) {
 | 
					    request.onerror = function (event) {
 | 
				
			||||||
@ -50,21 +46,21 @@ function persist (room) {
 | 
				
			|||||||
  let t = room.db.transaction(['updates'], 'readwrite')
 | 
					  let t = room.db.transaction(['updates'], 'readwrite')
 | 
				
			||||||
  let updatesStore = t.objectStore('updates')
 | 
					  let updatesStore = t.objectStore('updates')
 | 
				
			||||||
  return rtop(updatesStore.getAll())
 | 
					  return rtop(updatesStore.getAll())
 | 
				
			||||||
  .then(updates => {
 | 
					    .then(updates => {
 | 
				
			||||||
    // apply all previous updates before deleting them
 | 
					      // apply all previous updates before deleting them
 | 
				
			||||||
    room.mutex(() => {
 | 
					      room.mutex(() => {
 | 
				
			||||||
      updates.forEach(update => {
 | 
					        updates.forEach(update => {
 | 
				
			||||||
        decodePersisted(y, new BinaryDecoder(update))
 | 
					          decodePersisted(y, new BinaryDecoder(update))
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      const encoder = new BinaryEncoder()
 | 
				
			||||||
 | 
					      encodeStructsDS(y, encoder)
 | 
				
			||||||
 | 
					      // delete all pending updates
 | 
				
			||||||
 | 
					      rtop(updatesStore.clear()).then(() => {
 | 
				
			||||||
 | 
					        // write current model
 | 
				
			||||||
 | 
					        updatesStore.put(encoder.createBuffer())
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    const encoder = new BinaryEncoder()
 | 
					 | 
				
			||||||
    encodeStructsDS(y, encoder)
 | 
					 | 
				
			||||||
    // delete all pending updates
 | 
					 | 
				
			||||||
    rtop(updatesStore.clear()).then(() => {
 | 
					 | 
				
			||||||
      // write current model
 | 
					 | 
				
			||||||
      updatesStore.put(encoder.createBuffer())
 | 
					 | 
				
			||||||
    })
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function saveUpdate (room, updateBuffer) {
 | 
					function saveUpdate (room, updateBuffer) {
 | 
				
			||||||
@ -99,7 +95,7 @@ function registerRoomInPersistence (documentsDB, roomName) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const PREFERRED_TRIM_SIZE = 400
 | 
					const PREFERRED_TRIM_SIZE = 400
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class IndexedDBPersistence {
 | 
					export class IndexedDBPersistence {
 | 
				
			||||||
  constructor () {
 | 
					  constructor () {
 | 
				
			||||||
    this._rooms = new Map()
 | 
					    this._rooms = new Map()
 | 
				
			||||||
    this._documentsDB = new Promise(function (resolve, reject) {
 | 
					    this._documentsDB = new Promise(function (resolve, reject) {
 | 
				
			||||||
@ -115,7 +111,17 @@ export default class IndexedDBPersistence {
 | 
				
			|||||||
        reject(new Error(event.target.error))
 | 
					        reject(new Error(event.target.error))
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      request.onblocked = function () {
 | 
					      request.onblocked = function () {
 | 
				
			||||||
        location.reload()
 | 
					        location.reload()EventListener' is not defined.
 | 
				
			||||||
 | 
					        /home/dmonad/go/src/github.com/y-js/yjs/persistences/IndexedDBPersistence.js:160:36: 'BinaryDecoder' is not defined.
 | 
				
			||||||
 | 
					        /home/dmonad/go/src/github.com/y-js/yjs/persistences/IndexedDBPersistence.js:167:25: 'BinaryEncoder' is not defined.
 | 
				
			||||||
 | 
					        /home/dmonad/go/src/github.com/y-js/yjs/persistences/IndexedDBPersistence.js:178:25: 'BinaryEncoder' is not defined.
 | 
				
			||||||
 | 
					        /home/dmonad/go/src/github.com/y-js/yjs/persistences/IndexedDBPersistence.js:203:34: 'BinaryDecoder' is not defined.
 | 
				
			||||||
 | 
					        /home/dmonad/go/src/github.com/y-js/yjs/persistences/IndexedDBPersistence.js:213:17: 'encoder' is assigned a value but never used.
 | 
				
			||||||
 | 
					        /home/dmonad/go/src/github.com/y-js/yjs/persistences/IndexedDBPersistence.js:213:31: 'BinaryEncoder' is not defined.
 | 
				
			||||||
 | 
					        /home/dmonad/go/src/github.com/y-js/yjs/persistences/IndexedDBPersistence.js:214:30: 'BinaryEncoder' is not defined.
 | 
				
			||||||
 | 
					        /home/dmonad/go/src/github.com/y-js/yjs/persistences/IndexedDBPersistence.js:230:12: Trailing spaces not allowed.
 | 
				
			||||||
 | 
					        /home/dmonad/go/src/github.com/y-js/yjs/persistences/IndexedDBPersistence.js:237:5: Return statement should not contain assignment.
 | 
				
			||||||
 | 
					        /home/dmonad/go/src/github.com/y-js/yjs/persistences/IndexedDBPersistence.js:243:29: 'BinaryEncoder' i
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      request.onsuccess = function (event) {
 | 
					      request.onsuccess = function (event) {
 | 
				
			||||||
        const db = event.target.result
 | 
					        const db = event.target.result
 | 
				
			||||||
@ -194,7 +200,7 @@ export default class IndexedDBPersistence {
 | 
				
			|||||||
      db: null,
 | 
					      db: null,
 | 
				
			||||||
      dbPromise: null,
 | 
					      dbPromise: null,
 | 
				
			||||||
      channel: null,
 | 
					      channel: null,
 | 
				
			||||||
      mutex: createMutualExclude(),
 | 
					      mutex: createMutex(),
 | 
				
			||||||
      y
 | 
					      y
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (typeof BroadcastChannel !== 'undefined') {
 | 
					    if (typeof BroadcastChannel !== 'undefined') {
 | 
				
			||||||
@ -273,9 +279,10 @@ export default class IndexedDBPersistence {
 | 
				
			|||||||
   * Automatically destroys all Yjs all Yjs instances that persist to
 | 
					   * Automatically destroys all Yjs all Yjs instances that persist to
 | 
				
			||||||
   * the room. If `destroyYjsInstances = false` the persistence functionality
 | 
					   * the room. If `destroyYjsInstances = false` the persistence functionality
 | 
				
			||||||
   * will be removed from the Yjs instances.
 | 
					   * will be removed from the Yjs instances.
 | 
				
			||||||
   */
 | 
					   *
 | 
				
			||||||
  removePersistedData (roomName, destroyYjsInstances = true) {
 | 
					  removePersistedData (roomName, destroyYjsInstances = true) {
 | 
				
			||||||
    this.disconnectY(roomName)
 | 
					    this.disconnectY(roomName)
 | 
				
			||||||
    return rtop(indexedDB.deleteDatabase(roomName))
 | 
					    return rtop(indexedDB.deleteDatabase(roomName))
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
import { integrateRemoteStructs } from '../MessageHandler/integrateRemoteStructs.js'
 | 
					import { integrateRemoteStructs } from '../MessageHandler/integrateRemoteStructs.js'
 | 
				
			||||||
import { writeStructs } from '../MessageHandler/syncStep1.js'
 | 
					import { writeStructs } from '../MessageHandler/syncStep1.js'
 | 
				
			||||||
import { writeDeleteSet, readDeleteSet } from '../MessageHandler/deleteSet.js'
 | 
					import { writeDeleteSet, readDeleteSet } from '../MessageHandler/deleteSet.js'
 | 
				
			||||||
@ -6,10 +7,10 @@ export const PERSIST_UPDATE = 0
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Write an update to an encoder.
 | 
					 * Write an update to an encoder.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param {Yjs} y A Yjs instance
 | 
					 * @param {Y} y A Yjs instance
 | 
				
			||||||
 * @param {BinaryEncoder} updateEncoder I.e. transaction.encodedStructs
 | 
					 * @param {Encoder} updateEncoder I.e. transaction.encodedStructs
 | 
				
			||||||
 */
 | 
					 *
 | 
				
			||||||
export function encodeUpdate (y, updateEncoder, encoder) {
 | 
					export const encodeUpdate = (y, updateEncoder, encoder) => {
 | 
				
			||||||
  encoder.writeVarUint(PERSIST_UPDATE)
 | 
					  encoder.writeVarUint(PERSIST_UPDATE)
 | 
				
			||||||
  encoder.writeBinaryEncoder(updateEncoder)
 | 
					  encoder.writeBinaryEncoder(updateEncoder)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -19,10 +20,10 @@ export const PERSIST_STRUCTS_DS = 1
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Write the current Yjs data model to an encoder.
 | 
					 * Write the current Yjs data model to an encoder.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param {Yjs} y A Yjs instance
 | 
					 * @param {Y} y A Yjs instance
 | 
				
			||||||
 * @param {BinaryEncoder} encoder An encoder to write to
 | 
					 * @param {Encoder} encoder An encoder to write to
 | 
				
			||||||
 */
 | 
					 *
 | 
				
			||||||
export function encodeStructsDS (y, encoder) {
 | 
					export const encodeStructsDS = (y, encoder) => {
 | 
				
			||||||
  encoder.writeVarUint(PERSIST_STRUCTS_DS)
 | 
					  encoder.writeVarUint(PERSIST_STRUCTS_DS)
 | 
				
			||||||
  writeStructs(y, encoder, new Map())
 | 
					  writeStructs(y, encoder, new Map())
 | 
				
			||||||
  writeDeleteSet(y, encoder)
 | 
					  writeDeleteSet(y, encoder)
 | 
				
			||||||
@ -30,10 +31,10 @@ export function encodeStructsDS (y, encoder) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Feed the Yjs instance with the persisted state
 | 
					 * Feed the Yjs instance with the persisted state
 | 
				
			||||||
 * @param {Yjs} y A Yjs instance.
 | 
					 * @param {Y} y A Yjs instance.
 | 
				
			||||||
 * @param {BinaryDecoder} decoder A Decoder instance that holds the file content.
 | 
					 * @param {Decoder} decoder A Decoder instance that holds the file content.
 | 
				
			||||||
 */
 | 
					 *
 | 
				
			||||||
export function decodePersisted (y, decoder) {
 | 
					export const decodePersisted = (y, decoder) => {
 | 
				
			||||||
  y.transact(() => {
 | 
					  y.transact(() => {
 | 
				
			||||||
    while (decoder.hasContent()) {
 | 
					    while (decoder.hasContent()) {
 | 
				
			||||||
      const contentType = decoder.readVarUint()
 | 
					      const contentType = decoder.readVarUint()
 | 
				
			||||||
@ -49,3 +50,4 @@ export function decodePersisted (y, decoder) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }, true)
 | 
					  }, true)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
@ -1,6 +1,10 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module awareness-protocol
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import * as encoding from '../../lib/encoding.js'
 | 
					import * as encoding from '../lib/encoding.js'
 | 
				
			||||||
import * as decoding from '../../lib/decoding.js'
 | 
					import * as decoding from '../lib/decoding.js'
 | 
				
			||||||
 | 
					import { Y } from '../utils/Y.js' // eslint-disable-line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const messageUsersStateChanged = 0
 | 
					const messageUsersStateChanged = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -77,6 +81,7 @@ export const forwardUsersStateChange = (decoder, encoder) => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @param {decoding.Decoder} decoder
 | 
					 * @param {decoding.Decoder} decoder
 | 
				
			||||||
 | 
					 * @param {Y} y
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const readAwarenessMessage = (decoder, y) => {
 | 
					export const readAwarenessMessage = (decoder, y) => {
 | 
				
			||||||
  switch (decoding.readVarUint(decoder)) {
 | 
					  switch (decoding.readVarUint(decoder)) {
 | 
				
			||||||
@ -1,17 +1,18 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module sync-protocol
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import * as encoding from '../../lib/encoding.js'
 | 
					import * as encoding from '../lib/encoding.js'
 | 
				
			||||||
import * as decoding from '../../lib/decoding.js'
 | 
					import * as decoding from '../lib/decoding.js'
 | 
				
			||||||
import * as ID from '../Util/ID.js'
 | 
					import * as ID from '../utils/ID.js'
 | 
				
			||||||
import { getStruct } from '../Util/structReferences.js'
 | 
					import { getStruct } from '../utils/structReferences.js'
 | 
				
			||||||
import { deleteItemRange } from '../Struct/Delete.js'
 | 
					import { deleteItemRange } from '../structs/Delete.js'
 | 
				
			||||||
import { integrateRemoteStruct } from '../Util/integrateRemoteStructs.js'
 | 
					import { integrateRemoteStruct } from '../utils/integrateRemoteStructs.js'
 | 
				
			||||||
import Item from '../Struct/Item.js'
 | 
					import { Y } from '../utils/Y.js' // eslint-disable-line
 | 
				
			||||||
 | 
					import { Item } from '../structs/Item.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @typedef {import('../Store/StateStore.js').default} StateStore
 | 
					 * @typedef {Map<number, number>} StateSet
 | 
				
			||||||
 * @typedef {import('../Y.js').default} Y
 | 
					 | 
				
			||||||
 * @typedef {import('../Struct/Item.js').default} Item
 | 
					 | 
				
			||||||
 * @typedef {import('../Store/StateStore.js').StateSet} StateSet
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -82,7 +83,8 @@ export const writeDeleteSet = (encoder, y) => {
 | 
				
			|||||||
    const gc = n.gc
 | 
					    const gc = n.gc
 | 
				
			||||||
    if (currentUser !== user) {
 | 
					    if (currentUser !== user) {
 | 
				
			||||||
      numberOfUsers++
 | 
					      numberOfUsers++
 | 
				
			||||||
      // a new user was found
 | 
					      // a new user was foundimport { StateSet } from '../Store/StateStore.js' // eslint-disable-line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (currentUser !== null) { // happens on first iteration
 | 
					      if (currentUser !== null) { // happens on first iteration
 | 
				
			||||||
        encoding.setUint32(encoder, lastLenPos, currentLength)
 | 
					        encoding.setUint32(encoder, lastLenPos, currentLength)
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -201,8 +203,8 @@ export const stringifyStateSet = decoder => {
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Write StateSet to Encoder
 | 
					 * Write StateSet to Encoder
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param {Y} y
 | 
					 | 
				
			||||||
 * @param {encoding.Encoder} encoder
 | 
					 * @param {encoding.Encoder} encoder
 | 
				
			||||||
 | 
					 * @param {Y} y
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const writeStateSet = (encoder, y) => {
 | 
					export const writeStateSet = (encoder, y) => {
 | 
				
			||||||
  const state = y.ss.state
 | 
					  const state = y.ss.state
 | 
				
			||||||
@ -426,6 +428,7 @@ export const stringifyUpdate = (decoder, y) =>
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @param {encoding.Encoder} encoder
 | 
					 * @param {encoding.Encoder} encoder
 | 
				
			||||||
 | 
					 * @param {number} numOfStructs
 | 
				
			||||||
 * @param {encoding.Encoder} updates
 | 
					 * @param {encoding.Encoder} updates
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const writeUpdate = (encoder, numOfStructs, updates) => {
 | 
					export const writeUpdate = (encoder, numOfStructs, updates) => {
 | 
				
			||||||
							
								
								
									
										5
									
								
								provider/websocket.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								provider/websocket.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module provider/websocket
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export * from './websocket/WebSocketProvider.js'
 | 
				
			||||||
@ -1,7 +1,11 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module provider/websocket
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* eslint-env browser */
 | 
					/* eslint-env browser */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import * as Y from '../../src/index.js'
 | 
					import * as Y from '../../index.js'
 | 
				
			||||||
export * from '../../src/index.js'
 | 
					export * from '../../index.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const messageSync = 0
 | 
					const messageSync = 0
 | 
				
			||||||
const messageAwareness = 1
 | 
					const messageAwareness = 1
 | 
				
			||||||
@ -95,7 +99,7 @@ class WebsocketsSharedDocument extends Y.Y {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class WebsocketProvider {
 | 
					export class WebsocketProvider {
 | 
				
			||||||
  constructor (url) {
 | 
					  constructor (url) {
 | 
				
			||||||
    // ensure that url is always ends with /
 | 
					    // ensure that url is always ends with /
 | 
				
			||||||
    while (url[url.length - 1] === '/') {
 | 
					    while (url[url.length - 1] === '/') {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,8 @@
 | 
				
			|||||||
const Y = require('../../build/node/index.js')
 | 
					/**
 | 
				
			||||||
 | 
					 * @module provider/websocket
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Y = require('../../build/yjs.umd.js')
 | 
				
			||||||
const WebSocket = require('ws')
 | 
					const WebSocket = require('ws')
 | 
				
			||||||
const wss = new WebSocket.Server({ port: 1234 })
 | 
					const wss = new WebSocket.Server({ port: 1234 })
 | 
				
			||||||
const docs = new Map()
 | 
					const docs = new Map()
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,6 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module provider/ydb
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import * as globals from './globals.js'
 | 
					import * as globals from './globals.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1,3 +1,7 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module provider/ydb
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* eslint-env browser */
 | 
					/* eslint-env browser */
 | 
				
			||||||
import * as idbactions from './idbactions.js'
 | 
					import * as idbactions from './idbactions.js'
 | 
				
			||||||
import * as globals from '../../lib/globals.js'
 | 
					import * as globals from '../../lib/globals.js'
 | 
				
			||||||
@ -7,7 +11,7 @@ import * as encoding from '../../lib/encoding.js'
 | 
				
			|||||||
import * as logging from '../../lib/logging.js'
 | 
					import * as logging from '../../lib/logging.js'
 | 
				
			||||||
import * as idb from '../../lib/idb.js'
 | 
					import * as idb from '../../lib/idb.js'
 | 
				
			||||||
import * as decoding from '../../lib/decoding.js'
 | 
					import * as decoding from '../../lib/decoding.js'
 | 
				
			||||||
import Y from '../Y.js'
 | 
					import { Y } from '../../utils/Y.js'
 | 
				
			||||||
import { integrateRemoteStruct } from '../MessageHandler/integrateRemoteStructs.js'
 | 
					import { integrateRemoteStruct } from '../MessageHandler/integrateRemoteStructs.js'
 | 
				
			||||||
import { createMutualExclude } from '../../lib/mutualExclude.js'
 | 
					import { createMutualExclude } from '../../lib/mutualExclude.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1,3 +1,7 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module provider/ydb
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* eslint-env browser */
 | 
					/* eslint-env browser */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import * as test from './test.js'
 | 
					import * as test from './test.js'
 | 
				
			||||||
@ -1,8 +1,12 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module provider/ydb
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* eslint-env browser */
 | 
					/* eslint-env browser */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import * as decoding from './decoding.js'
 | 
					import * as decoding from '../../lib/decoding.js'
 | 
				
			||||||
import * as encoding from './encoding.js'
 | 
					import * as encoding from '../../lib/encoding.js'
 | 
				
			||||||
import * as globals from './globals.js'
 | 
					import * as globals from '../../lib/globals.js'
 | 
				
			||||||
import * as NamedEventHandler from './NamedEventHandler.js'
 | 
					import * as NamedEventHandler from './NamedEventHandler.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const bc = new BroadcastChannel('ydb-client')
 | 
					const bc = new BroadcastChannel('ydb-client')
 | 
				
			||||||
@ -52,17 +56,17 @@ const fireRoomStateUpdate = (ydb, room) => {
 | 
				
			|||||||
  if (roomStatesUpdating.length === 1) {
 | 
					  if (roomStatesUpdating.length === 1) {
 | 
				
			||||||
    // first time this is called, trigger actual publisher
 | 
					    // first time this is called, trigger actual publisher
 | 
				
			||||||
    // setTimeout(() => {
 | 
					    // setTimeout(() => {
 | 
				
			||||||
      const updated = new Map()
 | 
					    const updated = new Map()
 | 
				
			||||||
      const unconfirmedRooms = getUnconfirmedRooms(ydb)
 | 
					    const unconfirmedRooms = getUnconfirmedRooms(ydb)
 | 
				
			||||||
      roomStatesUpdating.forEach(room => {
 | 
					    roomStatesUpdating.forEach(room => {
 | 
				
			||||||
        if (!updated.has(room)) {
 | 
					      if (!updated.has(room)) {
 | 
				
			||||||
          updated.set(room, computeRoomState(ydb, unconfirmedRooms, room))
 | 
					        updated.set(room, computeRoomState(ydb, unconfirmedRooms, room))
 | 
				
			||||||
        }
 | 
					      }
 | 
				
			||||||
      })
 | 
					    })
 | 
				
			||||||
      NamedEventHandler.fire(ydb, 'syncstate', {
 | 
					    NamedEventHandler.fire(ydb, 'syncstate', {
 | 
				
			||||||
        updated
 | 
					      updated
 | 
				
			||||||
      })
 | 
					    })
 | 
				
			||||||
      roomStatesUpdating = []
 | 
					    roomStatesUpdating = []
 | 
				
			||||||
    // }, 0)
 | 
					    // }, 0)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -274,7 +278,7 @@ export const _broadcastYdbSyncFromServer = subs => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @param {string} room
 | 
					 * @param {string} room
 | 
				
			||||||
 * @param {function(ArrayBuffer)} f
 | 
					 * @param {Function} f
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const subscribeRoomData = (room, f) => {
 | 
					export const subscribeRoomData = (room, f) => {
 | 
				
			||||||
  let rsubs = datasubs.get(room)
 | 
					  let rsubs = datasubs.get(room)
 | 
				
			||||||
@ -1,3 +1,7 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module provider/ydb
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* eslint-env browser */
 | 
					/* eslint-env browser */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user