working on snapshotting and version history
This commit is contained in:
		
							parent
							
								
									ec58a99748
								
							
						
					
					
						commit
						77e479c03b
					
				@ -31,36 +31,56 @@ export const prosemirrorPluginKey = new PluginKey('yjs')
 | 
				
			|||||||
 * @return {Plugin} Returns a prosemirror plugin that binds to this type
 | 
					 * @return {Plugin} Returns a prosemirror plugin that binds to this type
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const prosemirrorPlugin = yXmlFragment => {
 | 
					export const prosemirrorPlugin = yXmlFragment => {
 | 
				
			||||||
  const pluginState = {
 | 
					 | 
				
			||||||
    type: yXmlFragment,
 | 
					 | 
				
			||||||
    y: yXmlFragment._y,
 | 
					 | 
				
			||||||
    binding: null
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  let changedInitialContent = false
 | 
					  let changedInitialContent = false
 | 
				
			||||||
  const plugin = new Plugin({
 | 
					  const plugin = new Plugin({
 | 
				
			||||||
    key: prosemirrorPluginKey,
 | 
					    key: prosemirrorPluginKey,
 | 
				
			||||||
    state: {
 | 
					    state: {
 | 
				
			||||||
      init: (initargs, state) => {
 | 
					      init: (initargs, state) => {
 | 
				
			||||||
        return pluginState
 | 
					        return {
 | 
				
			||||||
 | 
					          type: yXmlFragment,
 | 
				
			||||||
 | 
					          y: yXmlFragment._y,
 | 
				
			||||||
 | 
					          binding: null,
 | 
				
			||||||
 | 
					          snapshot: null
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      apply: (tr, pluginState) => {
 | 
					      apply: (tr, pluginState) => {
 | 
				
			||||||
 | 
					        const change = tr.getMeta(prosemirrorPluginKey)
 | 
				
			||||||
 | 
					        if (change !== undefined) {
 | 
				
			||||||
 | 
					          pluginState = Object.assign({}, pluginState)
 | 
				
			||||||
 | 
					          for (let key in change) {
 | 
				
			||||||
 | 
					            pluginState[key] = change[key]
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (pluginState.binding !== null) {
 | 
				
			||||||
 | 
					          if (change !== undefined && change.snapshot !== undefined) {
 | 
				
			||||||
 | 
					            // snapshot changed, rerender next
 | 
				
			||||||
 | 
					            setTimeout(() => {
 | 
				
			||||||
 | 
					              pluginState.binding._renderSnapshot(change.snapshot)
 | 
				
			||||||
 | 
					            }, 0)
 | 
				
			||||||
 | 
					          } else if (pluginState.snapshot == null) {
 | 
				
			||||||
 | 
					            // only apply if no snapshot active
 | 
				
			||||||
            // update Yjs state when apply is called. We need to do this here to compute the correct cursor decorations with the cursor plugin
 | 
					            // update Yjs state when apply is called. We need to do this here to compute the correct cursor decorations with the cursor plugin
 | 
				
			||||||
        if (pluginState.binding !== null && (changedInitialContent || tr.doc.content.size > 4)) {
 | 
					            if (changedInitialContent || tr.doc.content.size > 4) {
 | 
				
			||||||
              changedInitialContent = true
 | 
					              changedInitialContent = true
 | 
				
			||||||
              pluginState.binding._prosemirrorChanged(tr.doc)
 | 
					              pluginState.binding._prosemirrorChanged(tr.doc)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        return pluginState
 | 
					        return pluginState
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    view: view => {
 | 
					    view: view => {
 | 
				
			||||||
      const binding = new ProsemirrorBinding(yXmlFragment, view)
 | 
					      const binding = new ProsemirrorBinding(yXmlFragment, view)
 | 
				
			||||||
      pluginState.binding = binding
 | 
					      view.dispatch(view.state.tr.setMeta(prosemirrorPluginKey, { binding }))
 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
        update: () => {
 | 
					        update: () => {
 | 
				
			||||||
 | 
					          const pluginState = plugin.getState(view.state)
 | 
				
			||||||
 | 
					          if (pluginState.snapshot == null) {
 | 
				
			||||||
            if (changedInitialContent || view.state.doc.content.size > 4) {
 | 
					            if (changedInitialContent || view.state.doc.content.size > 4) {
 | 
				
			||||||
              changedInitialContent = true
 | 
					              changedInitialContent = true
 | 
				
			||||||
              binding._prosemirrorChanged(view.state.doc)
 | 
					              binding._prosemirrorChanged(view.state.doc)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        destroy: () => {
 | 
					        destroy: () => {
 | 
				
			||||||
          binding.destroy()
 | 
					          binding.destroy()
 | 
				
			||||||
@ -301,8 +321,18 @@ export class ProsemirrorBinding {
 | 
				
			|||||||
    })
 | 
					    })
 | 
				
			||||||
    yXmlFragment.observeDeep(this._observeFunction)
 | 
					    yXmlFragment.observeDeep(this._observeFunction)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  _renderSnapshot (snapshot) {
 | 
				
			||||||
 | 
					    // clear mapping because we are going to rerender
 | 
				
			||||||
 | 
					    this.mapping = new Map()
 | 
				
			||||||
 | 
					    this.mux(() => {
 | 
				
			||||||
 | 
					      const fragmentContent = this.type.toArray(snapshot).map(t => createNodeFromYElement(t, this.prosemirrorView.state.schema, new Map(), snapshot)).filter(n => n !== null)
 | 
				
			||||||
 | 
					      const tr = this.prosemirrorView.state.tr.replace(0, this.prosemirrorView.state.doc.content.size, new PModel.Slice(new PModel.Fragment(fragmentContent), 0, 0))
 | 
				
			||||||
 | 
					      this.prosemirrorView.dispatch(tr)
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  _typeChanged (events, transaction) {
 | 
					  _typeChanged (events, transaction) {
 | 
				
			||||||
    if (events.length === 0) {
 | 
					    if (events.length === 0 || prosemirrorPluginKey.getState(this.prosemirrorView.state).snapshot != null) {
 | 
				
			||||||
 | 
					      // drop out if snapshot is active
 | 
				
			||||||
      return
 | 
					      return
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    console.info('new types:', transaction.newTypes.size, 'deleted types:', transaction.deletedStructs.size, transaction.newTypes, transaction.deletedStructs)
 | 
					    console.info('new types:', transaction.newTypes.size, 'deleted types:', transaction.deletedStructs.size, transaction.newTypes, transaction.deletedStructs)
 | 
				
			||||||
@ -321,7 +351,7 @@ export class ProsemirrorBinding {
 | 
				
			|||||||
          tr.setSelection(TextSelection.create(tr.doc, anchor, head))
 | 
					          tr.setSelection(TextSelection.create(tr.doc, anchor, head))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      this.prosemirrorView.updateState(this.prosemirrorView.state.apply(tr))
 | 
					      this.prosemirrorView.dispatch(tr)
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  _prosemirrorChanged (doc) {
 | 
					  _prosemirrorChanged (doc) {
 | 
				
			||||||
@ -335,16 +365,17 @@ export class ProsemirrorBinding {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @privateMapping
 | 
					 * @private
 | 
				
			||||||
 * @param {YXmlElement} el
 | 
					 * @param {YXmlElement} el
 | 
				
			||||||
 * @param {PModel.Schema} schema
 | 
					 * @param {PModel.Schema} schema
 | 
				
			||||||
 * @param {ProsemirrorMapping} mapping
 | 
					 * @param {ProsemirrorMapping} mapping
 | 
				
			||||||
 | 
					 * @param {HistorySnapshot} [snapshot]
 | 
				
			||||||
 * @return {PModel.Node}
 | 
					 * @return {PModel.Node}
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const createNodeIfNotExists = (el, schema, mapping) => {
 | 
					export const createNodeIfNotExists = (el, schema, mapping, snapshot) => {
 | 
				
			||||||
  const node = mapping.get(el)
 | 
					  const node = mapping.get(el)
 | 
				
			||||||
  if (node === undefined) {
 | 
					  if (node === undefined) {
 | 
				
			||||||
    return createNodeFromYElement(el, schema, mapping)
 | 
					    return createNodeFromYElement(el, schema, mapping, snapshot)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return node
 | 
					  return node
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -354,18 +385,19 @@ export const createNodeIfNotExists = (el, schema, mapping) => {
 | 
				
			|||||||
 * @param {YXmlElement} el
 | 
					 * @param {YXmlElement} el
 | 
				
			||||||
 * @param {PModel.Schema} schema
 | 
					 * @param {PModel.Schema} schema
 | 
				
			||||||
 * @param {ProsemirrorMapping} mapping
 | 
					 * @param {ProsemirrorMapping} mapping
 | 
				
			||||||
 | 
					 * @param {import('../protocols/history.js').HistorySnapshot} snapshot
 | 
				
			||||||
 * @return {PModel.Node | null} Returns node if node could be created. Otherwise it deletes the yjs type and returns null
 | 
					 * @return {PModel.Node | null} Returns node if node could be created. Otherwise it deletes the yjs type and returns null
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const createNodeFromYElement = (el, schema, mapping) => {
 | 
					export const createNodeFromYElement = (el, schema, mapping, snapshot) => {
 | 
				
			||||||
  const children = []
 | 
					  const children = []
 | 
				
			||||||
  el.toArray().forEach(type => {
 | 
					  el.toArray(snapshot).forEach(type => {
 | 
				
			||||||
    if (type.constructor === YXmlElement) {
 | 
					    if (type.constructor === YXmlElement) {
 | 
				
			||||||
      const n = createNodeIfNotExists(type, schema, mapping)
 | 
					      const n = createNodeIfNotExists(type, schema, mapping, snapshot)
 | 
				
			||||||
      if (n !== null) {
 | 
					      if (n !== null) {
 | 
				
			||||||
        children.push(n)
 | 
					        children.push(n)
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      const ns = createTextNodesFromYText(type, schema, mapping)
 | 
					      const ns = createTextNodesFromYText(type, schema, mapping, snapshot)
 | 
				
			||||||
      if (ns !== null) {
 | 
					      if (ns !== null) {
 | 
				
			||||||
        ns.forEach(textchild => {
 | 
					        ns.forEach(textchild => {
 | 
				
			||||||
          if (textchild !== null) {
 | 
					          if (textchild !== null) {
 | 
				
			||||||
@ -377,7 +409,7 @@ export const createNodeFromYElement = (el, schema, mapping) => {
 | 
				
			|||||||
  })
 | 
					  })
 | 
				
			||||||
  let node
 | 
					  let node
 | 
				
			||||||
  try {
 | 
					  try {
 | 
				
			||||||
    node = schema.node(el.nodeName.toLowerCase(), el.getAttributes(), children)
 | 
					    node = schema.node(el.nodeName.toLowerCase(), el.getAttributes(snapshot), children)
 | 
				
			||||||
  } catch (e) {
 | 
					  } catch (e) {
 | 
				
			||||||
    // an error occured while creating the node. This is probably a result because of a concurrent action.
 | 
					    // an error occured while creating the node. This is probably a result because of a concurrent action.
 | 
				
			||||||
    // delete the node and do not push to children
 | 
					    // delete the node and do not push to children
 | 
				
			||||||
@ -395,11 +427,12 @@ export const createNodeFromYElement = (el, schema, mapping) => {
 | 
				
			|||||||
 * @param {YText} text
 | 
					 * @param {YText} text
 | 
				
			||||||
 * @param {PModel.Schema} schema
 | 
					 * @param {PModel.Schema} schema
 | 
				
			||||||
 * @param {ProsemirrorMapping} mapping
 | 
					 * @param {ProsemirrorMapping} mapping
 | 
				
			||||||
 | 
					 * @param {HistorySnapshot} [snapshot] 
 | 
				
			||||||
 * @return {Array<PModel.Node>}
 | 
					 * @return {Array<PModel.Node>}
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const createTextNodesFromYText = (text, schema, mapping) => {
 | 
					export const createTextNodesFromYText = (text, schema, mapping, snapshot) => {
 | 
				
			||||||
  const nodes = []
 | 
					  const nodes = []
 | 
				
			||||||
  const deltas = text.toDelta()
 | 
					  const deltas = text.toDelta(snapshot)
 | 
				
			||||||
  try {
 | 
					  try {
 | 
				
			||||||
    for (let i = 0; i < deltas.length; i++) {
 | 
					    for (let i = 0; i < deltas.length; i++) {
 | 
				
			||||||
      const delta = deltas[i]
 | 
					      const delta = deltas[i]
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										68
									
								
								examples/prosemirror-history.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								examples/prosemirror-history.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,68 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					import {Plugin} from "prosemirror-state"
 | 
				
			||||||
 | 
					import crel from 'crel'
 | 
				
			||||||
 | 
					import * as Y from '../index.js'
 | 
				
			||||||
 | 
					import { prosemirrorPluginKey } from '../bindings/prosemirror.js'
 | 
				
			||||||
 | 
					import * as encoding from '../lib/encoding.js'
 | 
				
			||||||
 | 
					import * as decoding from '../lib/decoding.js'
 | 
				
			||||||
 | 
					import * as historyProtocol from '../protocols/history.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const noteHistoryPlugin = new Plugin({
 | 
				
			||||||
 | 
					  view (editorView) { return new NoteHistoryPlugin(editorView) }
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const createWrapper = () => {
 | 
				
			||||||
 | 
					  const wrapper = crel('div', { style: 'display: flex' })
 | 
				
			||||||
 | 
					  const historyContainer = crel('div', { style: 'align-self: baseline; flex-basis: 250px;', class: 'shared-history' })
 | 
				
			||||||
 | 
					  wrapper.insertBefore(historyContainer, null)
 | 
				
			||||||
 | 
					  return { wrapper, historyContainer }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class NoteHistoryPlugin {
 | 
				
			||||||
 | 
					  constructor(editorView) {
 | 
				
			||||||
 | 
					    this.editorView = editorView
 | 
				
			||||||
 | 
					    const { historyContainer, wrapper } = createWrapper()
 | 
				
			||||||
 | 
					    this.wrapper = wrapper
 | 
				
			||||||
 | 
					    this.historyContainer = historyContainer
 | 
				
			||||||
 | 
					    const n = editorView.dom.parentNode.parentNode
 | 
				
			||||||
 | 
					    n.parentNode.replaceChild(this.wrapper, n)
 | 
				
			||||||
 | 
					    n.style['flex-grow'] = '1'
 | 
				
			||||||
 | 
					    wrapper.insertBefore(n, this.wrapper.firstChild)
 | 
				
			||||||
 | 
					    this.render()
 | 
				
			||||||
 | 
					    const y = prosemirrorPluginKey.getState(this.editorView.state).y
 | 
				
			||||||
 | 
					    const history = y.define('history', Y.Array)
 | 
				
			||||||
 | 
					    history.observe(this.render.bind(this))
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  render () {
 | 
				
			||||||
 | 
					    const y = prosemirrorPluginKey.getState(this.editorView.state).y
 | 
				
			||||||
 | 
					    const history = y.define('history', Y.Array).toArray()
 | 
				
			||||||
 | 
					    const fragment = document.createDocumentFragment()
 | 
				
			||||||
 | 
					    const snapshotBtn = crel('button', { type: 'button' }, ['snapshot'])
 | 
				
			||||||
 | 
					    snapshotBtn.addEventListener('click', this.snapshot.bind(this))
 | 
				
			||||||
 | 
					    fragment.insertBefore(snapshotBtn, null)
 | 
				
			||||||
 | 
					    history.forEach(buf => {
 | 
				
			||||||
 | 
					      const decoder = decoding.createDecoder(buf)
 | 
				
			||||||
 | 
					      const snapshot = historyProtocol.readHistorySnapshot(decoder)
 | 
				
			||||||
 | 
					      const date = new Date(decoding.readUint32(decoder) * 1000)
 | 
				
			||||||
 | 
					      const a = crel('a', [
 | 
				
			||||||
 | 
					        '• '+ date.toUTCString()
 | 
				
			||||||
 | 
					      ])
 | 
				
			||||||
 | 
					      const el = crel('div', [ a ])
 | 
				
			||||||
 | 
					      a.addEventListener('click', () => {
 | 
				
			||||||
 | 
					        console.log('setting snapshot')
 | 
				
			||||||
 | 
					        this.editorView.dispatch(this.editorView.state.tr.setMeta(prosemirrorPluginKey, { snapshot }))
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      fragment.insertBefore(el, null)
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    this.historyContainer.innerHTML = ''
 | 
				
			||||||
 | 
					    this.historyContainer.insertBefore(fragment, null)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  snapshot () {
 | 
				
			||||||
 | 
					    const y = prosemirrorPluginKey.getState(this.editorView.state).y
 | 
				
			||||||
 | 
					    const history = y.define('history', Y.Array)
 | 
				
			||||||
 | 
					    const encoder = encoding.createEncoder()
 | 
				
			||||||
 | 
					    historyProtocol.writeHistorySnapshot(encoder, y)
 | 
				
			||||||
 | 
					    encoding.writeUint32(encoder, Math.floor(Date.now() / 1000))
 | 
				
			||||||
 | 
					    history.push([encoding.toBuffer(encoder)])
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -9,6 +9,7 @@ import { EditorView } from 'prosemirror-view'
 | 
				
			|||||||
import { DOMParser } from 'prosemirror-model'
 | 
					import { DOMParser } from 'prosemirror-model'
 | 
				
			||||||
import { schema } from 'prosemirror-schema-basic'
 | 
					import { schema } from 'prosemirror-schema-basic'
 | 
				
			||||||
import { exampleSetup } from 'prosemirror-example-setup'
 | 
					import { exampleSetup } from 'prosemirror-example-setup'
 | 
				
			||||||
 | 
					import { noteHistoryPlugin } from './prosemirror-history.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const provider = new WebsocketProvider(conf.serverAddress)
 | 
					const provider = new WebsocketProvider(conf.serverAddress)
 | 
				
			||||||
const ydocument = provider.get('prosemirror')
 | 
					const ydocument = provider.get('prosemirror')
 | 
				
			||||||
@ -17,7 +18,7 @@ const type = ydocument.define('prosemirror', Y.XmlFragment)
 | 
				
			|||||||
const prosemirrorView = new EditorView(document.querySelector('#editor'), {
 | 
					const prosemirrorView = new EditorView(document.querySelector('#editor'), {
 | 
				
			||||||
  state: EditorState.create({
 | 
					  state: EditorState.create({
 | 
				
			||||||
    doc: DOMParser.fromSchema(schema).parse(document.querySelector('#content')),
 | 
					    doc: DOMParser.fromSchema(schema).parse(document.querySelector('#content')),
 | 
				
			||||||
    plugins: exampleSetup({schema}).concat([prosemirrorPlugin(type), cursorPlugin])
 | 
					    plugins: exampleSetup({schema}).concat([prosemirrorPlugin(type), cursorPlugin, noteHistoryPlugin])
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										3
									
								
								index.js
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								index.js
									
									
									
									
									
								
							@ -5,6 +5,7 @@ import { ItemJSON } from './structs/ItemJSON.js'
 | 
				
			|||||||
import { ItemString } from './structs/ItemString.js'
 | 
					import { ItemString } from './structs/ItemString.js'
 | 
				
			||||||
import { ItemFormat } from './structs/ItemFormat.js'
 | 
					import { ItemFormat } from './structs/ItemFormat.js'
 | 
				
			||||||
import { ItemEmbed } from './structs/ItemEmbed.js'
 | 
					import { ItemEmbed } from './structs/ItemEmbed.js'
 | 
				
			||||||
 | 
					import { ItemBinary } from './structs/ItemBinary.js'
 | 
				
			||||||
import { GC } from './structs/GC.js'
 | 
					import { GC } from './structs/GC.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { YArray } from './types/YArray.js'
 | 
					import { YArray } from './types/YArray.js'
 | 
				
			||||||
@ -53,3 +54,5 @@ registerStruct(9, YXmlElement)
 | 
				
			|||||||
registerStruct(10, YXmlText)
 | 
					registerStruct(10, YXmlText)
 | 
				
			||||||
registerStruct(11, YXmlHook)
 | 
					registerStruct(11, YXmlHook)
 | 
				
			||||||
registerStruct(12, ItemEmbed)
 | 
					registerStruct(12, ItemEmbed)
 | 
				
			||||||
 | 
					registerStruct(13, ItemBinary)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										191
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										191
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -100,7 +100,6 @@
 | 
				
			|||||||
      "version": "5.0.0",
 | 
					      "version": "5.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==",
 | 
					      "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==",
 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "xtend": "~4.0.0"
 | 
					        "xtend": "~4.0.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -201,8 +200,7 @@
 | 
				
			|||||||
    "ansi-regex": {
 | 
					    "ansi-regex": {
 | 
				
			||||||
      "version": "2.1.1",
 | 
					      "version": "2.1.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
 | 
				
			||||||
      "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
 | 
					      "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "ansi-styles": {
 | 
					    "ansi-styles": {
 | 
				
			||||||
      "version": "2.2.1",
 | 
					      "version": "2.2.1",
 | 
				
			||||||
@ -239,13 +237,13 @@
 | 
				
			|||||||
      "version": "1.2.0",
 | 
					      "version": "1.2.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
 | 
					      "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "are-we-there-yet": {
 | 
					    "are-we-there-yet": {
 | 
				
			||||||
      "version": "1.1.5",
 | 
					      "version": "1.1.5",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
 | 
				
			||||||
      "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
 | 
					      "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "delegates": "^1.0.0",
 | 
					        "delegates": "^1.0.0",
 | 
				
			||||||
        "readable-stream": "^2.0.6"
 | 
					        "readable-stream": "^2.0.6"
 | 
				
			||||||
@ -1669,13 +1667,13 @@
 | 
				
			|||||||
      "version": "1.3.1",
 | 
					      "version": "1.3.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-i47mqjF9UbjxJhxGf+pZ6kSxrnI3wBLlnGI2ArWJ4r0VrvDS7ZYXkprq/pLaBWYq4GM0r4zdHY+NNRqEMU7uew==",
 | 
					      "integrity": "sha512-i47mqjF9UbjxJhxGf+pZ6kSxrnI3wBLlnGI2ArWJ4r0VrvDS7ZYXkprq/pLaBWYq4GM0r4zdHY+NNRqEMU7uew==",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "bl": {
 | 
					    "bl": {
 | 
				
			||||||
      "version": "1.2.2",
 | 
					      "version": "1.2.2",
 | 
				
			||||||
      "resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
 | 
					      "resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
 | 
				
			||||||
      "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==",
 | 
					      "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "readable-stream": "^2.3.5",
 | 
					        "readable-stream": "^2.3.5",
 | 
				
			||||||
        "safe-buffer": "^5.1.1"
 | 
					        "safe-buffer": "^5.1.1"
 | 
				
			||||||
@ -1685,13 +1683,13 @@
 | 
				
			|||||||
          "version": "2.0.0",
 | 
					          "version": "2.0.0",
 | 
				
			||||||
          "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
 | 
					          "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
 | 
				
			||||||
          "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
 | 
					          "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
 | 
				
			||||||
          "dev": true
 | 
					          "optional": true
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "readable-stream": {
 | 
					        "readable-stream": {
 | 
				
			||||||
          "version": "2.3.6",
 | 
					          "version": "2.3.6",
 | 
				
			||||||
          "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
 | 
					          "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
 | 
				
			||||||
          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
 | 
					          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
 | 
				
			||||||
          "dev": true,
 | 
					          "optional": true,
 | 
				
			||||||
          "requires": {
 | 
					          "requires": {
 | 
				
			||||||
            "core-util-is": "~1.0.0",
 | 
					            "core-util-is": "~1.0.0",
 | 
				
			||||||
            "inherits": "~2.0.3",
 | 
					            "inherits": "~2.0.3",
 | 
				
			||||||
@ -1706,7 +1704,7 @@
 | 
				
			|||||||
          "version": "1.1.1",
 | 
					          "version": "1.1.1",
 | 
				
			||||||
          "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
 | 
					          "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
 | 
				
			||||||
          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
 | 
					          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
 | 
				
			||||||
          "dev": true,
 | 
					          "optional": true,
 | 
				
			||||||
          "requires": {
 | 
					          "requires": {
 | 
				
			||||||
            "safe-buffer": "~5.1.0"
 | 
					            "safe-buffer": "~5.1.0"
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
@ -1750,7 +1748,7 @@
 | 
				
			|||||||
      "version": "1.2.0",
 | 
					      "version": "1.2.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
 | 
					      "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "buffer-alloc-unsafe": "^1.1.0",
 | 
					        "buffer-alloc-unsafe": "^1.1.0",
 | 
				
			||||||
        "buffer-fill": "^1.0.0"
 | 
					        "buffer-fill": "^1.0.0"
 | 
				
			||||||
@ -1760,13 +1758,13 @@
 | 
				
			|||||||
      "version": "1.1.0",
 | 
					      "version": "1.1.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==",
 | 
					      "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "buffer-fill": {
 | 
					    "buffer-fill": {
 | 
				
			||||||
      "version": "1.0.0",
 | 
					      "version": "1.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=",
 | 
					      "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "buffer-from": {
 | 
					    "buffer-from": {
 | 
				
			||||||
      "version": "1.0.0",
 | 
					      "version": "1.0.0",
 | 
				
			||||||
@ -1893,7 +1891,7 @@
 | 
				
			|||||||
      "version": "1.1.1",
 | 
					      "version": "1.1.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==",
 | 
					      "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "circular-json": {
 | 
					    "circular-json": {
 | 
				
			||||||
      "version": "0.3.3",
 | 
					      "version": "0.3.3",
 | 
				
			||||||
@ -1932,12 +1930,13 @@
 | 
				
			|||||||
      "version": "1.1.0",
 | 
					      "version": "1.1.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
 | 
				
			||||||
      "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
 | 
					      "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "codemirror": {
 | 
					    "codemirror": {
 | 
				
			||||||
      "version": "5.42.0",
 | 
					      "version": "5.42.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.42.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.42.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-pbApC8zDzItP3HRphD6kQVwS976qB5Qi0hU3MZMixLk+AyugOW1RF+8XJEjeyl5yWsHNe88tDUxzeRh5AOxPRw=="
 | 
					      "integrity": "sha512-pbApC8zDzItP3HRphD6kQVwS976qB5Qi0hU3MZMixLk+AyugOW1RF+8XJEjeyl5yWsHNe88tDUxzeRh5AOxPRw==",
 | 
				
			||||||
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "color-convert": {
 | 
					    "color-convert": {
 | 
				
			||||||
      "version": "1.9.1",
 | 
					      "version": "1.9.1",
 | 
				
			||||||
@ -2146,8 +2145,7 @@
 | 
				
			|||||||
    "console-control-strings": {
 | 
					    "console-control-strings": {
 | 
				
			||||||
      "version": "1.1.0",
 | 
					      "version": "1.1.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
 | 
				
			||||||
      "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
 | 
					      "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "contains-path": {
 | 
					    "contains-path": {
 | 
				
			||||||
      "version": "0.1.0",
 | 
					      "version": "0.1.0",
 | 
				
			||||||
@ -2170,14 +2168,12 @@
 | 
				
			|||||||
    "core-util-is": {
 | 
					    "core-util-is": {
 | 
				
			||||||
      "version": "1.0.2",
 | 
					      "version": "1.0.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
 | 
				
			||||||
      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
 | 
					      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "crel": {
 | 
					    "crel": {
 | 
				
			||||||
      "version": "3.1.0",
 | 
					      "version": "3.1.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/crel/-/crel-3.1.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/crel/-/crel-3.1.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-VIGY44ERxx8lXVkOEfcB0A49OkjxkQNK+j+fHvoLy7GsGX1KKgAaQ+p9N0YgvQXu+X+ryUWGDeLx/fSI+w7+eg==",
 | 
					      "integrity": "sha512-VIGY44ERxx8lXVkOEfcB0A49OkjxkQNK+j+fHvoLy7GsGX1KKgAaQ+p9N0YgvQXu+X+ryUWGDeLx/fSI+w7+eg=="
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "cross-spawn": {
 | 
					    "cross-spawn": {
 | 
				
			||||||
      "version": "5.1.0",
 | 
					      "version": "5.1.0",
 | 
				
			||||||
@ -2285,7 +2281,7 @@
 | 
				
			|||||||
      "version": "3.3.0",
 | 
					      "version": "3.3.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
 | 
				
			||||||
      "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
 | 
					      "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "mimic-response": "^1.0.0"
 | 
					        "mimic-response": "^1.0.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -2300,7 +2296,7 @@
 | 
				
			|||||||
      "version": "0.6.0",
 | 
					      "version": "0.6.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
 | 
					      "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "deep-is": {
 | 
					    "deep-is": {
 | 
				
			||||||
      "version": "0.1.3",
 | 
					      "version": "0.1.3",
 | 
				
			||||||
@ -2312,7 +2308,7 @@
 | 
				
			|||||||
      "version": "4.0.2",
 | 
					      "version": "4.0.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz",
 | 
				
			||||||
      "integrity": "sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww==",
 | 
					      "integrity": "sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww==",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "abstract-leveldown": "~5.0.0",
 | 
					        "abstract-leveldown": "~5.0.0",
 | 
				
			||||||
        "inherits": "^2.0.3"
 | 
					        "inherits": "^2.0.3"
 | 
				
			||||||
@ -2367,7 +2363,7 @@
 | 
				
			|||||||
      "version": "1.0.0",
 | 
					      "version": "1.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
 | 
					      "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "depd": {
 | 
					    "depd": {
 | 
				
			||||||
      "version": "1.1.2",
 | 
					      "version": "1.1.2",
 | 
				
			||||||
@ -2394,7 +2390,7 @@
 | 
				
			|||||||
      "version": "1.0.3",
 | 
					      "version": "1.0.3",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
 | 
				
			||||||
      "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=",
 | 
					      "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "doctrine": {
 | 
					    "doctrine": {
 | 
				
			||||||
      "version": "2.1.0",
 | 
					      "version": "2.1.0",
 | 
				
			||||||
@ -2490,7 +2486,7 @@
 | 
				
			|||||||
      "version": "5.0.4",
 | 
					      "version": "5.0.4",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-5.0.4.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-5.0.4.tgz",
 | 
				
			||||||
      "integrity": "sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw==",
 | 
					      "integrity": "sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw==",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "abstract-leveldown": "^5.0.0",
 | 
					        "abstract-leveldown": "^5.0.0",
 | 
				
			||||||
        "inherits": "^2.0.3",
 | 
					        "inherits": "^2.0.3",
 | 
				
			||||||
@ -2503,7 +2499,6 @@
 | 
				
			|||||||
      "version": "1.4.1",
 | 
					      "version": "1.4.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
 | 
					      "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "once": "^1.4.0"
 | 
					        "once": "^1.4.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -2518,7 +2513,6 @@
 | 
				
			|||||||
      "version": "0.1.7",
 | 
					      "version": "0.1.7",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
 | 
				
			||||||
      "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
 | 
					      "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "prr": "~1.0.1"
 | 
					        "prr": "~1.0.1"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -3302,7 +3296,7 @@
 | 
				
			|||||||
      "version": "1.1.1",
 | 
					      "version": "1.1.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg==",
 | 
					      "integrity": "sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg==",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "expand-tilde": {
 | 
					    "expand-tilde": {
 | 
				
			||||||
      "version": "1.2.2",
 | 
					      "version": "1.2.2",
 | 
				
			||||||
@ -3370,7 +3364,7 @@
 | 
				
			|||||||
      "version": "1.0.2",
 | 
					      "version": "1.0.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/fast-future/-/fast-future-1.0.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/fast-future/-/fast-future-1.0.2.tgz",
 | 
				
			||||||
      "integrity": "sha1-hDWpqqAteSSNF9cE52JZMB2ZKAo=",
 | 
					      "integrity": "sha1-hDWpqqAteSSNF9cE52JZMB2ZKAo=",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "fast-json-stable-stringify": {
 | 
					    "fast-json-stable-stringify": {
 | 
				
			||||||
      "version": "2.0.0",
 | 
					      "version": "2.0.0",
 | 
				
			||||||
@ -3562,7 +3556,7 @@
 | 
				
			|||||||
      "version": "1.0.0",
 | 
					      "version": "1.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
 | 
					      "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "fs-exists-sync": {
 | 
					    "fs-exists-sync": {
 | 
				
			||||||
      "version": "0.1.0",
 | 
					      "version": "0.1.0",
 | 
				
			||||||
@ -4138,7 +4132,7 @@
 | 
				
			|||||||
      "version": "2.7.4",
 | 
					      "version": "2.7.4",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
 | 
				
			||||||
      "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
 | 
					      "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "aproba": "^1.0.3",
 | 
					        "aproba": "^1.0.3",
 | 
				
			||||||
        "console-control-strings": "^1.0.0",
 | 
					        "console-control-strings": "^1.0.0",
 | 
				
			||||||
@ -4154,7 +4148,7 @@
 | 
				
			|||||||
          "version": "1.0.0",
 | 
					          "version": "1.0.0",
 | 
				
			||||||
          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
 | 
					          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
 | 
				
			||||||
          "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
 | 
					          "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
 | 
				
			||||||
          "dev": true,
 | 
					          "optional": true,
 | 
				
			||||||
          "requires": {
 | 
					          "requires": {
 | 
				
			||||||
            "number-is-nan": "^1.0.0"
 | 
					            "number-is-nan": "^1.0.0"
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
@ -4163,7 +4157,7 @@
 | 
				
			|||||||
          "version": "1.0.2",
 | 
					          "version": "1.0.2",
 | 
				
			||||||
          "resolved": "http://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
 | 
					          "resolved": "http://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
 | 
				
			||||||
          "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
 | 
					          "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
 | 
				
			||||||
          "dev": true,
 | 
					          "optional": true,
 | 
				
			||||||
          "requires": {
 | 
					          "requires": {
 | 
				
			||||||
            "code-point-at": "^1.0.0",
 | 
					            "code-point-at": "^1.0.0",
 | 
				
			||||||
            "is-fullwidth-code-point": "^1.0.0",
 | 
					            "is-fullwidth-code-point": "^1.0.0",
 | 
				
			||||||
@ -4192,7 +4186,7 @@
 | 
				
			|||||||
      "version": "0.0.0",
 | 
					      "version": "0.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=",
 | 
					      "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "glob": {
 | 
					    "glob": {
 | 
				
			||||||
      "version": "7.1.2",
 | 
					      "version": "7.1.2",
 | 
				
			||||||
@ -4336,7 +4330,7 @@
 | 
				
			|||||||
      "version": "2.0.1",
 | 
					      "version": "2.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
 | 
				
			||||||
      "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
 | 
					      "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "home-or-tmp": {
 | 
					    "home-or-tmp": {
 | 
				
			||||||
      "version": "2.0.0",
 | 
					      "version": "2.0.0",
 | 
				
			||||||
@ -4550,14 +4544,12 @@
 | 
				
			|||||||
    "inherits": {
 | 
					    "inherits": {
 | 
				
			||||||
      "version": "2.0.3",
 | 
					      "version": "2.0.3",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
 | 
				
			||||||
      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
 | 
					      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "ini": {
 | 
					    "ini": {
 | 
				
			||||||
      "version": "1.3.5",
 | 
					      "version": "1.3.5",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
 | 
				
			||||||
      "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
 | 
					      "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "inquirer": {
 | 
					    "inquirer": {
 | 
				
			||||||
      "version": "3.3.0",
 | 
					      "version": "3.3.0",
 | 
				
			||||||
@ -4723,8 +4715,7 @@
 | 
				
			|||||||
    "is-fullwidth-code-point": {
 | 
					    "is-fullwidth-code-point": {
 | 
				
			||||||
      "version": "2.0.0",
 | 
					      "version": "2.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
 | 
					      "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "is-glob": {
 | 
					    "is-glob": {
 | 
				
			||||||
      "version": "2.0.1",
 | 
					      "version": "2.0.1",
 | 
				
			||||||
@ -4853,8 +4844,7 @@
 | 
				
			|||||||
    "isarray": {
 | 
					    "isarray": {
 | 
				
			||||||
      "version": "1.0.0",
 | 
					      "version": "1.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
 | 
					      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "isexe": {
 | 
					    "isexe": {
 | 
				
			||||||
      "version": "2.0.0",
 | 
					      "version": "2.0.0",
 | 
				
			||||||
@ -5118,7 +5108,7 @@
 | 
				
			|||||||
      "version": "4.0.0",
 | 
					      "version": "4.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/level/-/level-4.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/level/-/level-4.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-4epzCOlEcJ529NOdlAYiuiakS/kZTDdiKSBNJmE1B8bsmA+zEVwcpxyH86qJSQTpOu7SODrlaD9WgPRHLkGutA==",
 | 
					      "integrity": "sha512-4epzCOlEcJ529NOdlAYiuiakS/kZTDdiKSBNJmE1B8bsmA+zEVwcpxyH86qJSQTpOu7SODrlaD9WgPRHLkGutA==",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "level-packager": "^3.0.0",
 | 
					        "level-packager": "^3.0.0",
 | 
				
			||||||
        "leveldown": "^4.0.0",
 | 
					        "leveldown": "^4.0.0",
 | 
				
			||||||
@ -5129,13 +5119,12 @@
 | 
				
			|||||||
      "version": "9.0.0",
 | 
					      "version": "9.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-OIpVvjCcZNP5SdhcNupnsI1zo5Y9Vpm+k/F1gfG5kXrtctlrwanisakweJtE0uA0OpLukRfOQae+Fg0M5Debhg==",
 | 
					      "integrity": "sha512-OIpVvjCcZNP5SdhcNupnsI1zo5Y9Vpm+k/F1gfG5kXrtctlrwanisakweJtE0uA0OpLukRfOQae+Fg0M5Debhg==",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "level-errors": {
 | 
					    "level-errors": {
 | 
				
			||||||
      "version": "2.0.0",
 | 
					      "version": "2.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-AmY4HCp9h3OiU19uG+3YWkdELgy05OTP/r23aNHaQKWv8DO787yZgsEuGVkoph40uwN+YdUKnANlrxSsoOaaxg==",
 | 
					      "integrity": "sha512-AmY4HCp9h3OiU19uG+3YWkdELgy05OTP/r23aNHaQKWv8DO787yZgsEuGVkoph40uwN+YdUKnANlrxSsoOaaxg==",
 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "errno": "~0.1.1"
 | 
					        "errno": "~0.1.1"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -5144,7 +5133,7 @@
 | 
				
			|||||||
      "version": "3.0.1",
 | 
					      "version": "3.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g==",
 | 
					      "integrity": "sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g==",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "inherits": "^2.0.1",
 | 
					        "inherits": "^2.0.1",
 | 
				
			||||||
        "readable-stream": "^2.3.6",
 | 
					        "readable-stream": "^2.3.6",
 | 
				
			||||||
@ -5155,13 +5144,13 @@
 | 
				
			|||||||
          "version": "2.0.0",
 | 
					          "version": "2.0.0",
 | 
				
			||||||
          "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
 | 
					          "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
 | 
				
			||||||
          "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
 | 
					          "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
 | 
				
			||||||
          "dev": true
 | 
					          "optional": true
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "readable-stream": {
 | 
					        "readable-stream": {
 | 
				
			||||||
          "version": "2.3.6",
 | 
					          "version": "2.3.6",
 | 
				
			||||||
          "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
 | 
					          "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
 | 
				
			||||||
          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
 | 
					          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
 | 
				
			||||||
          "dev": true,
 | 
					          "optional": true,
 | 
				
			||||||
          "requires": {
 | 
					          "requires": {
 | 
				
			||||||
            "core-util-is": "~1.0.0",
 | 
					            "core-util-is": "~1.0.0",
 | 
				
			||||||
            "inherits": "~2.0.3",
 | 
					            "inherits": "~2.0.3",
 | 
				
			||||||
@ -5176,7 +5165,7 @@
 | 
				
			|||||||
          "version": "1.1.1",
 | 
					          "version": "1.1.1",
 | 
				
			||||||
          "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
 | 
					          "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
 | 
				
			||||||
          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
 | 
					          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
 | 
				
			||||||
          "dev": true,
 | 
					          "optional": true,
 | 
				
			||||||
          "requires": {
 | 
					          "requires": {
 | 
				
			||||||
            "safe-buffer": "~5.1.0"
 | 
					            "safe-buffer": "~5.1.0"
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
@ -5187,7 +5176,7 @@
 | 
				
			|||||||
      "version": "3.1.0",
 | 
					      "version": "3.1.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/level-packager/-/level-packager-3.1.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/level-packager/-/level-packager-3.1.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-UxVEfK5WH0u0InR3WxTCSAroiorAGKzXWZT6i+nBjambmvINuXFUsFx2Ai3UIjUUtnyWhluv42jMlzUZCsAk9A==",
 | 
					      "integrity": "sha512-UxVEfK5WH0u0InR3WxTCSAroiorAGKzXWZT6i+nBjambmvINuXFUsFx2Ai3UIjUUtnyWhluv42jMlzUZCsAk9A==",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "encoding-down": "~5.0.0",
 | 
					        "encoding-down": "~5.0.0",
 | 
				
			||||||
        "levelup": "^3.0.0"
 | 
					        "levelup": "^3.0.0"
 | 
				
			||||||
@ -5197,7 +5186,7 @@
 | 
				
			|||||||
      "version": "4.0.1",
 | 
					      "version": "4.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-4.0.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-4.0.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-ZlBKVSsglPIPJnz4ggB8o2R0bxDxbsMzuQohbfgoFMVApyTE118DK5LNRG0cRju6rt3OkGxe0V6UYACGlq/byg==",
 | 
					      "integrity": "sha512-ZlBKVSsglPIPJnz4ggB8o2R0bxDxbsMzuQohbfgoFMVApyTE118DK5LNRG0cRju6rt3OkGxe0V6UYACGlq/byg==",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "abstract-leveldown": "~5.0.0",
 | 
					        "abstract-leveldown": "~5.0.0",
 | 
				
			||||||
        "bindings": "~1.3.0",
 | 
					        "bindings": "~1.3.0",
 | 
				
			||||||
@ -5210,7 +5199,7 @@
 | 
				
			|||||||
          "version": "2.10.0",
 | 
					          "version": "2.10.0",
 | 
				
			||||||
          "resolved": "http://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
 | 
					          "resolved": "http://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
 | 
				
			||||||
          "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==",
 | 
					          "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==",
 | 
				
			||||||
          "dev": true
 | 
					          "optional": true
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@ -5218,7 +5207,7 @@
 | 
				
			|||||||
      "version": "3.1.1",
 | 
					      "version": "3.1.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/levelup/-/levelup-3.1.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/levelup/-/levelup-3.1.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg==",
 | 
					      "integrity": "sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg==",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "deferred-leveldown": "~4.0.0",
 | 
					        "deferred-leveldown": "~4.0.0",
 | 
				
			||||||
        "level-errors": "~2.0.0",
 | 
					        "level-errors": "~2.0.0",
 | 
				
			||||||
@ -5647,7 +5636,7 @@
 | 
				
			|||||||
      "version": "1.0.1",
 | 
					      "version": "1.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
 | 
					      "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "minimatch": {
 | 
					    "minimatch": {
 | 
				
			||||||
      "version": "3.0.4",
 | 
					      "version": "3.0.4",
 | 
				
			||||||
@ -5661,14 +5650,12 @@
 | 
				
			|||||||
    "minimist": {
 | 
					    "minimist": {
 | 
				
			||||||
      "version": "0.0.8",
 | 
					      "version": "0.0.8",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
 | 
				
			||||||
      "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
 | 
					      "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "mkdirp": {
 | 
					    "mkdirp": {
 | 
				
			||||||
      "version": "0.5.1",
 | 
					      "version": "0.5.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
 | 
				
			||||||
      "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
 | 
					      "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "minimist": "0.0.8"
 | 
					        "minimist": "0.0.8"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -5721,7 +5708,7 @@
 | 
				
			|||||||
      "version": "2.5.0",
 | 
					      "version": "2.5.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.5.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.5.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-9g2twBGSP6wIR5PW7tXvAWnEWKJDH/VskdXp168xsw9VVxpEGov8K4jsP4/VeoC7b2ZAyzckvMCuQuQlw44lXg==",
 | 
					      "integrity": "sha512-9g2twBGSP6wIR5PW7tXvAWnEWKJDH/VskdXp168xsw9VVxpEGov8K4jsP4/VeoC7b2ZAyzckvMCuQuQlw44lXg==",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "semver": "^5.4.1"
 | 
					        "semver": "^5.4.1"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
@ -5730,7 +5717,7 @@
 | 
				
			|||||||
          "version": "5.6.0",
 | 
					          "version": "5.6.0",
 | 
				
			||||||
          "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
 | 
					          "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
 | 
				
			||||||
          "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
 | 
					          "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
 | 
				
			||||||
          "dev": true
 | 
					          "optional": true
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@ -5748,7 +5735,7 @@
 | 
				
			|||||||
      "version": "0.1.1",
 | 
					      "version": "0.1.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz",
 | 
				
			||||||
      "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=",
 | 
					      "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "normalize-package-data": {
 | 
					    "normalize-package-data": {
 | 
				
			||||||
      "version": "2.4.0",
 | 
					      "version": "2.4.0",
 | 
				
			||||||
@ -5775,7 +5762,7 @@
 | 
				
			|||||||
      "version": "4.1.2",
 | 
					      "version": "4.1.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
 | 
				
			||||||
      "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
 | 
					      "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "are-we-there-yet": "~1.1.2",
 | 
					        "are-we-there-yet": "~1.1.2",
 | 
				
			||||||
        "console-control-strings": "~1.1.0",
 | 
					        "console-control-strings": "~1.1.0",
 | 
				
			||||||
@ -5795,8 +5782,7 @@
 | 
				
			|||||||
    "number-is-nan": {
 | 
					    "number-is-nan": {
 | 
				
			||||||
      "version": "1.0.1",
 | 
					      "version": "1.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
 | 
				
			||||||
      "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
 | 
					      "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "nwmatcher": {
 | 
					    "nwmatcher": {
 | 
				
			||||||
      "version": "1.4.3",
 | 
					      "version": "1.4.3",
 | 
				
			||||||
@ -5815,8 +5801,7 @@
 | 
				
			|||||||
    "object-assign": {
 | 
					    "object-assign": {
 | 
				
			||||||
      "version": "4.1.1",
 | 
					      "version": "4.1.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
 | 
				
			||||||
      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
 | 
					      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "object-keys": {
 | 
					    "object-keys": {
 | 
				
			||||||
      "version": "1.0.11",
 | 
					      "version": "1.0.11",
 | 
				
			||||||
@ -5853,7 +5838,6 @@
 | 
				
			|||||||
      "version": "1.4.0",
 | 
					      "version": "1.4.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
 | 
				
			||||||
      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
 | 
					      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "wrappy": "1"
 | 
					        "wrappy": "1"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -5871,7 +5855,7 @@
 | 
				
			|||||||
      "version": "2.0.1",
 | 
					      "version": "2.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-saQQ9hjLwu/oS0492eyYotoh+bra1819cfAT5rjY/e4REWwuc8IgZ844Oo44SiftWcJuBiqp0SA0BFVbmLX0IQ==",
 | 
					      "integrity": "sha512-saQQ9hjLwu/oS0492eyYotoh+bra1819cfAT5rjY/e4REWwuc8IgZ844Oo44SiftWcJuBiqp0SA0BFVbmLX0IQ==",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "optionator": {
 | 
					    "optionator": {
 | 
				
			||||||
      "version": "0.8.2",
 | 
					      "version": "0.8.2",
 | 
				
			||||||
@ -5904,8 +5888,7 @@
 | 
				
			|||||||
    "os-homedir": {
 | 
					    "os-homedir": {
 | 
				
			||||||
      "version": "1.0.2",
 | 
					      "version": "1.0.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
 | 
				
			||||||
      "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
 | 
					      "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "os-tmpdir": {
 | 
					    "os-tmpdir": {
 | 
				
			||||||
      "version": "1.0.2",
 | 
					      "version": "1.0.2",
 | 
				
			||||||
@ -6148,7 +6131,7 @@
 | 
				
			|||||||
      "version": "4.0.0",
 | 
					      "version": "4.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-4.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-4.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-7tayxeYboJX0RbVzdnKyGl2vhQRWr6qfClEXDhOkXjuaOKCw2q8aiuFhONRYVsG/czia7KhpykIlI2S2VaPunA==",
 | 
					      "integrity": "sha512-7tayxeYboJX0RbVzdnKyGl2vhQRWr6qfClEXDhOkXjuaOKCw2q8aiuFhONRYVsG/czia7KhpykIlI2S2VaPunA==",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "detect-libc": "^1.0.3",
 | 
					        "detect-libc": "^1.0.3",
 | 
				
			||||||
        "expand-template": "^1.0.2",
 | 
					        "expand-template": "^1.0.2",
 | 
				
			||||||
@ -6171,7 +6154,7 @@
 | 
				
			|||||||
          "version": "1.2.0",
 | 
					          "version": "1.2.0",
 | 
				
			||||||
          "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
 | 
					          "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
 | 
				
			||||||
          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
 | 
					          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
 | 
				
			||||||
          "dev": true
 | 
					          "optional": true
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@ -6196,8 +6179,7 @@
 | 
				
			|||||||
    "process-nextick-args": {
 | 
					    "process-nextick-args": {
 | 
				
			||||||
      "version": "1.0.7",
 | 
					      "version": "1.0.7",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
 | 
				
			||||||
      "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
 | 
					      "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "progress": {
 | 
					    "progress": {
 | 
				
			||||||
      "version": "2.0.0",
 | 
					      "version": "2.0.0",
 | 
				
			||||||
@ -6380,8 +6362,7 @@
 | 
				
			|||||||
    "prr": {
 | 
					    "prr": {
 | 
				
			||||||
      "version": "1.0.1",
 | 
					      "version": "1.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
 | 
				
			||||||
      "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
 | 
					      "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY="
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "pseudomap": {
 | 
					    "pseudomap": {
 | 
				
			||||||
      "version": "1.0.2",
 | 
					      "version": "1.0.2",
 | 
				
			||||||
@ -6400,7 +6381,7 @@
 | 
				
			|||||||
      "version": "2.0.1",
 | 
					      "version": "2.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
 | 
					      "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "end-of-stream": "^1.1.0",
 | 
					        "end-of-stream": "^1.1.0",
 | 
				
			||||||
        "once": "^1.3.1"
 | 
					        "once": "^1.3.1"
 | 
				
			||||||
@ -6495,7 +6476,7 @@
 | 
				
			|||||||
      "version": "1.2.8",
 | 
					      "version": "1.2.8",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
 | 
				
			||||||
      "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
 | 
					      "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "deep-extend": "^0.6.0",
 | 
					        "deep-extend": "^0.6.0",
 | 
				
			||||||
        "ini": "~1.3.0",
 | 
					        "ini": "~1.3.0",
 | 
				
			||||||
@ -6507,7 +6488,7 @@
 | 
				
			|||||||
          "version": "1.2.0",
 | 
					          "version": "1.2.0",
 | 
				
			||||||
          "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
 | 
					          "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
 | 
				
			||||||
          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
 | 
					          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
 | 
				
			||||||
          "dev": true
 | 
					          "optional": true
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@ -6560,7 +6541,6 @@
 | 
				
			|||||||
      "version": "2.3.3",
 | 
					      "version": "2.3.3",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
 | 
				
			||||||
      "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
 | 
					      "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "core-util-is": "~1.0.0",
 | 
					        "core-util-is": "~1.0.0",
 | 
				
			||||||
        "inherits": "~2.0.3",
 | 
					        "inherits": "~2.0.3",
 | 
				
			||||||
@ -7094,8 +7074,7 @@
 | 
				
			|||||||
    "safe-buffer": {
 | 
					    "safe-buffer": {
 | 
				
			||||||
      "version": "5.1.1",
 | 
					      "version": "5.1.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
 | 
					      "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "safer-buffer": {
 | 
					    "safer-buffer": {
 | 
				
			||||||
      "version": "2.1.2",
 | 
					      "version": "2.1.2",
 | 
				
			||||||
@ -7164,7 +7143,7 @@
 | 
				
			|||||||
      "version": "2.0.0",
 | 
					      "version": "2.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
 | 
					      "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "set-getter": {
 | 
					    "set-getter": {
 | 
				
			||||||
      "version": "0.1.0",
 | 
					      "version": "0.1.0",
 | 
				
			||||||
@ -7211,20 +7190,19 @@
 | 
				
			|||||||
    "signal-exit": {
 | 
					    "signal-exit": {
 | 
				
			||||||
      "version": "3.0.2",
 | 
					      "version": "3.0.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
 | 
				
			||||||
      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
 | 
					      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "simple-concat": {
 | 
					    "simple-concat": {
 | 
				
			||||||
      "version": "1.0.0",
 | 
					      "version": "1.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=",
 | 
					      "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "simple-get": {
 | 
					    "simple-get": {
 | 
				
			||||||
      "version": "2.8.1",
 | 
					      "version": "2.8.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==",
 | 
					      "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "decompress-response": "^3.3.0",
 | 
					        "decompress-response": "^3.3.0",
 | 
				
			||||||
        "once": "^1.3.1",
 | 
					        "once": "^1.3.1",
 | 
				
			||||||
@ -7419,7 +7397,6 @@
 | 
				
			|||||||
      "version": "2.1.1",
 | 
					      "version": "2.1.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
 | 
					      "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "is-fullwidth-code-point": "^2.0.0",
 | 
					        "is-fullwidth-code-point": "^2.0.0",
 | 
				
			||||||
        "strip-ansi": "^4.0.0"
 | 
					        "strip-ansi": "^4.0.0"
 | 
				
			||||||
@ -7428,14 +7405,12 @@
 | 
				
			|||||||
        "ansi-regex": {
 | 
					        "ansi-regex": {
 | 
				
			||||||
          "version": "3.0.0",
 | 
					          "version": "3.0.0",
 | 
				
			||||||
          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
 | 
					          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
 | 
				
			||||||
          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
 | 
					          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
 | 
				
			||||||
          "dev": true
 | 
					 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "strip-ansi": {
 | 
					        "strip-ansi": {
 | 
				
			||||||
          "version": "4.0.0",
 | 
					          "version": "4.0.0",
 | 
				
			||||||
          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
 | 
					          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
 | 
				
			||||||
          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
 | 
					          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
 | 
				
			||||||
          "dev": true,
 | 
					 | 
				
			||||||
          "requires": {
 | 
					          "requires": {
 | 
				
			||||||
            "ansi-regex": "^3.0.0"
 | 
					            "ansi-regex": "^3.0.0"
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
@ -7446,7 +7421,6 @@
 | 
				
			|||||||
      "version": "1.0.3",
 | 
					      "version": "1.0.3",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
 | 
				
			||||||
      "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
 | 
					      "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "safe-buffer": "~5.1.0"
 | 
					        "safe-buffer": "~5.1.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -7455,7 +7429,6 @@
 | 
				
			|||||||
      "version": "3.0.1",
 | 
					      "version": "3.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
 | 
				
			||||||
      "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
 | 
					      "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
 | 
				
			||||||
      "dev": true,
 | 
					 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "ansi-regex": "^2.0.0"
 | 
					        "ansi-regex": "^2.0.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -7486,8 +7459,7 @@
 | 
				
			|||||||
    "strip-json-comments": {
 | 
					    "strip-json-comments": {
 | 
				
			||||||
      "version": "2.0.1",
 | 
					      "version": "2.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
 | 
				
			||||||
      "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
 | 
					      "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "supports-color": {
 | 
					    "supports-color": {
 | 
				
			||||||
      "version": "2.0.0",
 | 
					      "version": "2.0.0",
 | 
				
			||||||
@ -7563,7 +7535,7 @@
 | 
				
			|||||||
      "version": "1.16.3",
 | 
					      "version": "1.16.3",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz",
 | 
				
			||||||
      "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==",
 | 
					      "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "chownr": "^1.0.1",
 | 
					        "chownr": "^1.0.1",
 | 
				
			||||||
        "mkdirp": "^0.5.1",
 | 
					        "mkdirp": "^0.5.1",
 | 
				
			||||||
@ -7575,7 +7547,7 @@
 | 
				
			|||||||
          "version": "1.0.3",
 | 
					          "version": "1.0.3",
 | 
				
			||||||
          "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz",
 | 
					          "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz",
 | 
				
			||||||
          "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==",
 | 
					          "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==",
 | 
				
			||||||
          "dev": true,
 | 
					          "optional": true,
 | 
				
			||||||
          "requires": {
 | 
					          "requires": {
 | 
				
			||||||
            "end-of-stream": "^1.1.0",
 | 
					            "end-of-stream": "^1.1.0",
 | 
				
			||||||
            "once": "^1.3.1"
 | 
					            "once": "^1.3.1"
 | 
				
			||||||
@ -7587,7 +7559,7 @@
 | 
				
			|||||||
      "version": "1.6.2",
 | 
					      "version": "1.6.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz",
 | 
				
			||||||
      "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==",
 | 
					      "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "bl": "^1.0.0",
 | 
					        "bl": "^1.0.0",
 | 
				
			||||||
        "buffer-alloc": "^1.2.0",
 | 
					        "buffer-alloc": "^1.2.0",
 | 
				
			||||||
@ -7629,7 +7601,7 @@
 | 
				
			|||||||
      "version": "1.1.1",
 | 
					      "version": "1.1.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==",
 | 
					      "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "to-fast-properties": {
 | 
					    "to-fast-properties": {
 | 
				
			||||||
      "version": "1.0.3",
 | 
					      "version": "1.0.3",
 | 
				
			||||||
@ -7694,7 +7666,7 @@
 | 
				
			|||||||
      "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",
 | 
				
			||||||
      "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
 | 
					      "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "safe-buffer": "^5.0.1"
 | 
					        "safe-buffer": "^5.0.1"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -7813,8 +7785,7 @@
 | 
				
			|||||||
    "util-deprecate": {
 | 
					    "util-deprecate": {
 | 
				
			||||||
      "version": "1.0.2",
 | 
					      "version": "1.0.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
 | 
				
			||||||
      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
 | 
					      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "utils-merge": {
 | 
					    "utils-merge": {
 | 
				
			||||||
      "version": "1.0.0",
 | 
					      "version": "1.0.0",
 | 
				
			||||||
@ -7928,13 +7899,13 @@
 | 
				
			|||||||
      "version": "1.0.0",
 | 
					      "version": "1.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=",
 | 
					      "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=",
 | 
				
			||||||
      "dev": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "wide-align": {
 | 
					    "wide-align": {
 | 
				
			||||||
      "version": "1.1.3",
 | 
					      "version": "1.1.3",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
 | 
				
			||||||
      "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
 | 
					      "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
 | 
				
			||||||
      "dev": true,
 | 
					      "optional": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "string-width": "^1.0.2 || 2"
 | 
					        "string-width": "^1.0.2 || 2"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -7942,8 +7913,7 @@
 | 
				
			|||||||
    "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",
 | 
				
			||||||
      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
 | 
					      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "write": {
 | 
					    "write": {
 | 
				
			||||||
      "version": "0.2.1",
 | 
					      "version": "0.2.1",
 | 
				
			||||||
@ -7979,8 +7949,7 @@
 | 
				
			|||||||
    "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",
 | 
				
			||||||
      "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
 | 
					      "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
 | 
				
			||||||
      "dev": true
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "yallist": {
 | 
					    "yallist": {
 | 
				
			||||||
      "version": "2.1.2",
 | 
					      "version": "2.1.2",
 | 
				
			||||||
 | 
				
			|||||||
@ -97,7 +97,8 @@
 | 
				
			|||||||
    "rollup-watch": "^3.2.2",
 | 
					    "rollup-watch": "^3.2.2",
 | 
				
			||||||
    "standard": "^11.0.1",
 | 
					    "standard": "^11.0.1",
 | 
				
			||||||
    "tui-jsdoc-template": "^1.2.2",
 | 
					    "tui-jsdoc-template": "^1.2.2",
 | 
				
			||||||
    "codemirror": "^5.42.0"
 | 
					    "codemirror": "^5.42.0",
 | 
				
			||||||
 | 
					    "crel": "^3.1.0"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "optionalDependencies": {
 | 
					  "optionalDependencies": {
 | 
				
			||||||
    "level": "^4.0.0",
 | 
					    "level": "^4.0.0",
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										33
									
								
								protocols/history.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								protocols/history.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import * as encoding from '../lib/encoding.js'
 | 
				
			||||||
 | 
					import * as decoding from '../lib/decoding.js'
 | 
				
			||||||
 | 
					import { Y } from '../utils/Y.js' // eslint-disable-line
 | 
				
			||||||
 | 
					import { writeDeleteStore, readFreshDeleteStore, DeleteStore } from '../utils/DeleteStore.js' // eslint-disable-line
 | 
				
			||||||
 | 
					import { writeStateMap, readStateMap } from '../utils/StateStore.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @typedef {Object} HistorySnapshot
 | 
				
			||||||
 | 
					 * @property {DeleteStore} HistorySnapshot.ds
 | 
				
			||||||
 | 
					 * @property {Map<number,number>} HistorySnapshot.sm
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @param {encoding.Encoder} encoder
 | 
				
			||||||
 | 
					 * @param {Y} y
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const writeHistorySnapshot = (encoder, y) => {
 | 
				
			||||||
 | 
					  writeDeleteStore(encoder, y.ds)
 | 
				
			||||||
 | 
					  writeStateMap(encoder, y.ss.state)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @param {decoding.Decoder} decoder
 | 
				
			||||||
 | 
					 * @return {HistorySnapshot}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const readHistorySnapshot = (decoder) => {
 | 
				
			||||||
 | 
					  const ds = readFreshDeleteStore(decoder)
 | 
				
			||||||
 | 
					  const sm = readStateMap(decoder)
 | 
				
			||||||
 | 
					  return { ds, sm }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -10,9 +10,11 @@ import { deleteItemRange } from '../utils/structManipulation.js'
 | 
				
			|||||||
import { integrateRemoteStruct } from '../utils/integrateRemoteStructs.js'
 | 
					import { integrateRemoteStruct } from '../utils/integrateRemoteStructs.js'
 | 
				
			||||||
import { Y } from '../utils/Y.js' // eslint-disable-line
 | 
					import { Y } from '../utils/Y.js' // eslint-disable-line
 | 
				
			||||||
import * as stringify from '../utils/structStringify.js'
 | 
					import * as stringify from '../utils/structStringify.js'
 | 
				
			||||||
 | 
					import { readStateMap, writeStateMap } from '../utils/StateStore.js'
 | 
				
			||||||
 | 
					import { writeDeleteStore, readDeleteStore, stringifyDeleteStore } from '../utils/DeleteStore.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @typedef {Map<number, number>} StateSet
 | 
					 * @typedef {Map<number, number>} StateMap
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -44,196 +46,6 @@ export const messageYjsSyncStep1 = 0
 | 
				
			|||||||
export const messageYjsSyncStep2 = 1
 | 
					export const messageYjsSyncStep2 = 1
 | 
				
			||||||
export const messageYjsUpdate = 2
 | 
					export const messageYjsUpdate = 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Stringifies a message-encoded Delete Set.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param {decoding.Decoder} decoder
 | 
					 | 
				
			||||||
 * @return {string}
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
export const stringifyDeleteSet = (decoder) => {
 | 
					 | 
				
			||||||
  let str = ''
 | 
					 | 
				
			||||||
  const dsLength = decoding.readUint32(decoder)
 | 
					 | 
				
			||||||
  for (let i = 0; i < dsLength; i++) {
 | 
					 | 
				
			||||||
    str += ' -' + decoding.readVarUint(decoder) + ':\n' // decodes user
 | 
					 | 
				
			||||||
    const dvLength = decoding.readUint32(decoder)
 | 
					 | 
				
			||||||
    for (let j = 0; j < dvLength; j++) {
 | 
					 | 
				
			||||||
      str += `clock: ${decoding.readVarUint(decoder)}, length: ${decoding.readVarUint(decoder)}, gc: ${decoding.readUint8(decoder) === 1}\n`
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return str
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Write the DeleteSet of a shared document to an Encoder.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param {encoding.Encoder} encoder
 | 
					 | 
				
			||||||
 * @param {Y} y
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
export const writeDeleteSet = (encoder, y) => {
 | 
					 | 
				
			||||||
  let currentUser = null
 | 
					 | 
				
			||||||
  let currentLength
 | 
					 | 
				
			||||||
  let lastLenPos
 | 
					 | 
				
			||||||
  let numberOfUsers = 0
 | 
					 | 
				
			||||||
  const laterDSLenPus = encoding.length(encoder)
 | 
					 | 
				
			||||||
  encoding.writeUint32(encoder, 0)
 | 
					 | 
				
			||||||
  y.ds.iterate(null, null, n => {
 | 
					 | 
				
			||||||
    const user = n._id.user
 | 
					 | 
				
			||||||
    const clock = n._id.clock
 | 
					 | 
				
			||||||
    const len = n.len
 | 
					 | 
				
			||||||
    const gc = n.gc
 | 
					 | 
				
			||||||
    if (currentUser !== user) {
 | 
					 | 
				
			||||||
      numberOfUsers++
 | 
					 | 
				
			||||||
      // a new user was foundimport { StateSet } from '../Store/StateStore.js' // eslint-disable-line
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (currentUser !== null) { // happens on first iteration
 | 
					 | 
				
			||||||
        encoding.setUint32(encoder, lastLenPos, currentLength)
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      currentUser = user
 | 
					 | 
				
			||||||
      encoding.writeVarUint(encoder, user)
 | 
					 | 
				
			||||||
      // pseudo-fill pos
 | 
					 | 
				
			||||||
      lastLenPos = encoding.length(encoder)
 | 
					 | 
				
			||||||
      encoding.writeUint32(encoder, 0)
 | 
					 | 
				
			||||||
      currentLength = 0
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    encoding.writeVarUint(encoder, clock)
 | 
					 | 
				
			||||||
    encoding.writeVarUint(encoder, len)
 | 
					 | 
				
			||||||
    encoding.writeUint8(encoder, gc ? 1 : 0)
 | 
					 | 
				
			||||||
    currentLength++
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
  if (currentUser !== null) { // happens on first iteration
 | 
					 | 
				
			||||||
    encoding.setUint32(encoder, lastLenPos, currentLength)
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  encoding.setUint32(encoder, laterDSLenPus, numberOfUsers)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Read delete set from Decoder and apply it to a shared document.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param {decoding.Decoder} decoder
 | 
					 | 
				
			||||||
 * @param {Y} y
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
export const readDeleteSet = (decoder, y) => {
 | 
					 | 
				
			||||||
  const dsLength = decoding.readUint32(decoder)
 | 
					 | 
				
			||||||
  for (let i = 0; i < dsLength; i++) {
 | 
					 | 
				
			||||||
    const user = decoding.readVarUint(decoder)
 | 
					 | 
				
			||||||
    const dv = []
 | 
					 | 
				
			||||||
    const dvLength = decoding.readUint32(decoder)
 | 
					 | 
				
			||||||
    for (let j = 0; j < dvLength; j++) {
 | 
					 | 
				
			||||||
      const from = decoding.readVarUint(decoder)
 | 
					 | 
				
			||||||
      const len = decoding.readVarUint(decoder)
 | 
					 | 
				
			||||||
      const gc = decoding.readUint8(decoder) === 1
 | 
					 | 
				
			||||||
      dv.push({from, len, gc})
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (dvLength > 0) {
 | 
					 | 
				
			||||||
      const deletions = []
 | 
					 | 
				
			||||||
      let pos = 0
 | 
					 | 
				
			||||||
      let d = dv[pos]
 | 
					 | 
				
			||||||
      y.ds.iterate(ID.createID(user, 0), ID.createID(user, Number.MAX_VALUE), n => {
 | 
					 | 
				
			||||||
        // cases:
 | 
					 | 
				
			||||||
        // 1. d deletes something to the right of n
 | 
					 | 
				
			||||||
        //  => go to next n (break)
 | 
					 | 
				
			||||||
        // 2. d deletes something to the left of n
 | 
					 | 
				
			||||||
        //  => create deletions
 | 
					 | 
				
			||||||
        //  => reset d accordingly
 | 
					 | 
				
			||||||
        //  *)=> if d doesn't delete anything anymore, go to next d (continue)
 | 
					 | 
				
			||||||
        // 3. not 2) and d deletes something that also n deletes
 | 
					 | 
				
			||||||
        //  => reset d so that it doesn't contain n's deletion
 | 
					 | 
				
			||||||
        //  *)=> if d does not delete anything anymore, go to next d (continue)
 | 
					 | 
				
			||||||
        while (d != null) {
 | 
					 | 
				
			||||||
          var diff = 0 // describe the diff of length in 1) and 2)
 | 
					 | 
				
			||||||
          if (n._id.clock + n.len <= d.from) {
 | 
					 | 
				
			||||||
            // 1)
 | 
					 | 
				
			||||||
            break
 | 
					 | 
				
			||||||
          } else if (d.from < n._id.clock) {
 | 
					 | 
				
			||||||
            // 2)
 | 
					 | 
				
			||||||
            // delete maximum the len of d
 | 
					 | 
				
			||||||
            // else delete as much as possible
 | 
					 | 
				
			||||||
            diff = Math.min(n._id.clock - d.from, d.len)
 | 
					 | 
				
			||||||
            // deleteItemRange(y, user, d.from, diff, true)
 | 
					 | 
				
			||||||
            deletions.push([user, d.from, diff])
 | 
					 | 
				
			||||||
          } else {
 | 
					 | 
				
			||||||
            // 3)
 | 
					 | 
				
			||||||
            diff = n._id.clock + n.len - d.from // never null (see 1)
 | 
					 | 
				
			||||||
            if (d.gc && !n.gc) {
 | 
					 | 
				
			||||||
              // d marks as gc'd but n does not
 | 
					 | 
				
			||||||
              // then delete either way
 | 
					 | 
				
			||||||
              // deleteItemRange(y, user, d.from, Math.min(diff, d.len), true)
 | 
					 | 
				
			||||||
              deletions.push([user, d.from, Math.min(diff, d.len)])
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          if (d.len <= diff) {
 | 
					 | 
				
			||||||
            // d doesn't delete anything anymore
 | 
					 | 
				
			||||||
            d = dv[++pos]
 | 
					 | 
				
			||||||
          } else {
 | 
					 | 
				
			||||||
            d.from = d.from + diff // reset pos
 | 
					 | 
				
			||||||
            d.len = d.len - diff // reset length
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
      // TODO: It would be more performant to apply the deletes in the above loop
 | 
					 | 
				
			||||||
      // Adapt the Tree implementation to support delete while iterating
 | 
					 | 
				
			||||||
      for (let i = deletions.length - 1; i >= 0; i--) {
 | 
					 | 
				
			||||||
        const del = deletions[i]
 | 
					 | 
				
			||||||
        deleteItemRange(y, del[0], del[1], del[2], true)
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      // for the rest.. just apply it
 | 
					 | 
				
			||||||
      for (; pos < dv.length; pos++) {
 | 
					 | 
				
			||||||
        d = dv[pos]
 | 
					 | 
				
			||||||
        deleteItemRange(y, user, d.from, d.len, true)
 | 
					 | 
				
			||||||
        // deletions.push([user, d.from, d.len, d.gc)
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Read a StateSet from Decoder and return it as string.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param {decoding.Decoder} decoder
 | 
					 | 
				
			||||||
 * @return {string}
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
export const stringifyStateSet = decoder => {
 | 
					 | 
				
			||||||
  let s = 'State Set: '
 | 
					 | 
				
			||||||
  readStateSet(decoder).forEach((clock, user) => {
 | 
					 | 
				
			||||||
    s += `(${user}: ${clock}), `
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
  return s
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Write StateSet to Encoder
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param {encoding.Encoder} encoder
 | 
					 | 
				
			||||||
 * @param {Y} y
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
export const writeStateSet = (encoder, y) => {
 | 
					 | 
				
			||||||
  const state = y.ss.state
 | 
					 | 
				
			||||||
  // write as fixed-size number to stay consistent with the other encode functions.
 | 
					 | 
				
			||||||
  // => anytime we write the number of objects that follow, encode as fixed-size number.
 | 
					 | 
				
			||||||
  encoding.writeUint32(encoder, state.size)
 | 
					 | 
				
			||||||
  state.forEach((clock, user) => {
 | 
					 | 
				
			||||||
    encoding.writeVarUint(encoder, user)
 | 
					 | 
				
			||||||
    encoding.writeVarUint(encoder, clock)
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Read StateSet from Decoder and return as Map
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param {decoding.Decoder} decoder
 | 
					 | 
				
			||||||
 * @return {StateSet}
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
export const readStateSet = decoder => {
 | 
					 | 
				
			||||||
  const ss = new Map()
 | 
					 | 
				
			||||||
  const ssLength = decoding.readUint32(decoder)
 | 
					 | 
				
			||||||
  for (let i = 0; i < ssLength; i++) {
 | 
					 | 
				
			||||||
    const user = decoding.readVarUint(decoder)
 | 
					 | 
				
			||||||
    const clock = decoding.readVarUint(decoder)
 | 
					 | 
				
			||||||
    ss.set(user, clock)
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return ss
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @param {decoding.Decoder} decoder
 | 
					 * @param {decoding.Decoder} decoder
 | 
				
			||||||
 * @param {Y} y
 | 
					 * @param {Y} y
 | 
				
			||||||
@ -262,7 +74,7 @@ export const stringifyStructs = (decoder, y) => {
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param {encoding.Encoder} encoder
 | 
					 * @param {encoding.Encoder} encoder
 | 
				
			||||||
 * @param {Y} y
 | 
					 * @param {Y} y
 | 
				
			||||||
 * @param {StateSet} ss State Set received from a remote client. Maps from client id to number of created operations by client id.
 | 
					 * @param {StateMap} ss State Set received from a remote client. Maps from client id to number of created operations by client id.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const writeStructs = (encoder, y, ss) => {
 | 
					export const writeStructs = (encoder, y, ss) => {
 | 
				
			||||||
  const lenPos = encoding.length(encoder)
 | 
					  const lenPos = encoding.length(encoder)
 | 
				
			||||||
@ -328,7 +140,7 @@ export const stringifySyncStep1 = (decoder) => {
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
export const writeSyncStep1 = (encoder, y) => {
 | 
					export const writeSyncStep1 = (encoder, y) => {
 | 
				
			||||||
  encoding.writeVarUint(encoder, messageYjsSyncStep1)
 | 
					  encoding.writeVarUint(encoder, messageYjsSyncStep1)
 | 
				
			||||||
  writeStateSet(encoder, y)
 | 
					  writeStateMap(encoder, y.ss.state)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -339,7 +151,7 @@ export const writeSyncStep1 = (encoder, y) => {
 | 
				
			|||||||
export const writeSyncStep2 = (encoder, y, ss) => {
 | 
					export const writeSyncStep2 = (encoder, y, ss) => {
 | 
				
			||||||
  encoding.writeVarUint(encoder, messageYjsSyncStep2)
 | 
					  encoding.writeVarUint(encoder, messageYjsSyncStep2)
 | 
				
			||||||
  writeStructs(encoder, y, ss)
 | 
					  writeStructs(encoder, y, ss)
 | 
				
			||||||
  writeDeleteSet(encoder, y)
 | 
					  writeDeleteStore(encoder, y.ds)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -350,7 +162,7 @@ export const writeSyncStep2 = (encoder, y, ss) => {
 | 
				
			|||||||
 * @param {Y} y
 | 
					 * @param {Y} y
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const readSyncStep1 = (decoder, encoder, y) =>
 | 
					export const readSyncStep1 = (decoder, encoder, y) =>
 | 
				
			||||||
  writeSyncStep2(encoder, y, readStateSet(decoder))
 | 
					  writeSyncStep2(encoder, y, readStateMap(decoder))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @param {decoding.Decoder} decoder
 | 
					 * @param {decoding.Decoder} decoder
 | 
				
			||||||
@ -363,19 +175,19 @@ export const stringifySyncStep2 = (decoder, y) => {
 | 
				
			|||||||
  str += stringifyStructs(decoder, y)
 | 
					  str += stringifyStructs(decoder, y)
 | 
				
			||||||
  // write DS to string
 | 
					  // write DS to string
 | 
				
			||||||
  str += ' + Delete Set:\n'
 | 
					  str += ' + Delete Set:\n'
 | 
				
			||||||
  str += stringifyDeleteSet(decoder)
 | 
					  str += stringifyDeleteStore(decoder)
 | 
				
			||||||
  return str
 | 
					  return str
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Read and apply Structs and then DeleteSet to a y instance.
 | 
					 * Read and apply Structs and then DeleteStore to a y instance.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param {decoding.Decoder} decoder
 | 
					 * @param {decoding.Decoder} decoder
 | 
				
			||||||
 * @param {Y} y
 | 
					 * @param {Y} y
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const readSyncStep2 = (decoder, y) => {
 | 
					export const readSyncStep2 = (decoder, y) => {
 | 
				
			||||||
  readStructs(decoder, y)
 | 
					  readStructs(decoder, y)
 | 
				
			||||||
  readDeleteSet(decoder, y)
 | 
					  readDeleteStore(decoder, y)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										48
									
								
								structs/ItemBinary.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								structs/ItemBinary.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @module structs
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: ItemBinary should be able to merge with right (similar to other items). Or the other items (ItemJSON) should not be able to merge - extra byte + consistency
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { Item, splitHelper } from './Item.js'
 | 
				
			||||||
 | 
					import * as stringify from '../utils/structStringify.js'
 | 
				
			||||||
 | 
					import * as encoding from '../lib/encoding.js'
 | 
				
			||||||
 | 
					import * as decoding from '../lib/decoding.js'
 | 
				
			||||||
 | 
					import { Y } from '../utils/Y.js' // eslint-disable-line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class ItemBinary extends Item {
 | 
				
			||||||
 | 
					  constructor () {
 | 
				
			||||||
 | 
					    super()
 | 
				
			||||||
 | 
					    this._content = null
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  _copy () {
 | 
				
			||||||
 | 
					    let struct = super._copy()
 | 
				
			||||||
 | 
					    struct._content = this._content
 | 
				
			||||||
 | 
					    return struct
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * @param {Y} y
 | 
				
			||||||
 | 
					   * @param {decoding.Decoder} decoder
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  _fromBinary (y, decoder) {
 | 
				
			||||||
 | 
					    const missing = super._fromBinary(y, decoder)
 | 
				
			||||||
 | 
					    this._content = decoding.readPayload(decoder)
 | 
				
			||||||
 | 
					    return missing
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * @param {encoding.Encoder} encoder
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  _toBinary (encoder) {
 | 
				
			||||||
 | 
					    super._toBinary(encoder)
 | 
				
			||||||
 | 
					    encoding.writePayload(encoder, this._content)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Transform this YXml Type to a readable format.
 | 
				
			||||||
 | 
					   * Useful for logging as all Items and Delete implement this method.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @private
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  _logString () {
 | 
				
			||||||
 | 
					    return stringify.logItemHelper('ItemBinary', this)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -9,6 +9,8 @@ import * as stringify from '../utils/structStringify.js'
 | 
				
			|||||||
import { YEvent } from '../utils/YEvent.js'
 | 
					import { YEvent } from '../utils/YEvent.js'
 | 
				
			||||||
import { Transaction } from '../utils/Transaction.js' // eslint-disable-line
 | 
					import { Transaction } from '../utils/Transaction.js' // eslint-disable-line
 | 
				
			||||||
import { Item } from '../structs/Item.js' // eslint-disable-line
 | 
					import { Item } from '../structs/Item.js' // eslint-disable-line
 | 
				
			||||||
 | 
					import { ItemBinary } from '../structs/ItemBinary.js'
 | 
				
			||||||
 | 
					import { isVisible } from '../utils/snapshot.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Event that describes the changes on a YArray
 | 
					 * Event that describes the changes on a YArray
 | 
				
			||||||
@ -89,6 +91,7 @@ export class YArray extends Type {
 | 
				
			|||||||
   * Returns the i-th element from a YArray.
 | 
					   * Returns the i-th element from a YArray.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * @param {number} index The index of the element to return from the YArray
 | 
					   * @param {number} index The index of the element to return from the YArray
 | 
				
			||||||
 | 
					   * @return {any}
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  get (index) {
 | 
					  get (index) {
 | 
				
			||||||
    let n = this._start
 | 
					    let n = this._start
 | 
				
			||||||
@ -112,10 +115,11 @@ export class YArray extends Type {
 | 
				
			|||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Transforms this YArray to a JavaScript Array.
 | 
					   * Transforms this YArray to a JavaScript Array.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
 | 
					   * @param {Object} [snapshot]
 | 
				
			||||||
   * @return {Array}
 | 
					   * @return {Array}
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  toArray () {
 | 
					  toArray (snapshot) {
 | 
				
			||||||
    return this.map(c => c)
 | 
					    return this.map(c => c, snapshot)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
@ -137,14 +141,15 @@ export class YArray extends Type {
 | 
				
			|||||||
   * element of this YArray.
 | 
					   * element of this YArray.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * @param {Function} f Function that produces an element of the new Array
 | 
					   * @param {Function} f Function that produces an element of the new Array
 | 
				
			||||||
 | 
					   * @param {import('../protocols/history.js').HistorySnapshot} [snapshot]
 | 
				
			||||||
   * @return {Array} A new array with each element being the result of the
 | 
					   * @return {Array} A new array with each element being the result of the
 | 
				
			||||||
   *                 callback function
 | 
					   *                 callback function
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  map (f) {
 | 
					  map (f, snapshot) {
 | 
				
			||||||
    const res = []
 | 
					    const res = []
 | 
				
			||||||
    this.forEach((c, i) => {
 | 
					    this.forEach((c, i) => {
 | 
				
			||||||
      res.push(f(c, i, this))
 | 
					      res.push(f(c, i, this))
 | 
				
			||||||
    })
 | 
					    }, snapshot)
 | 
				
			||||||
    return res
 | 
					    return res
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -152,14 +157,17 @@ export class YArray extends Type {
 | 
				
			|||||||
   * Executes a provided function on once on overy element of this YArray.
 | 
					   * Executes a provided function on once on overy element of this YArray.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * @param {Function} f A function to execute on every element of this YArray.
 | 
					   * @param {Function} f A function to execute on every element of this YArray.
 | 
				
			||||||
 | 
					   * @param {import('../protocols/history.js').HistorySnapshot} [snapshot]
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  forEach (f) {
 | 
					  forEach (f, snapshot) {
 | 
				
			||||||
    let index = 0
 | 
					    let index = 0
 | 
				
			||||||
    let n = this._start
 | 
					    let n = this._start
 | 
				
			||||||
    while (n !== null) {
 | 
					    while (n !== null) {
 | 
				
			||||||
      if (!n._deleted && n._countable) {
 | 
					      if (isVisible(n, snapshot) && n._countable) {
 | 
				
			||||||
        if (n instanceof Type) {
 | 
					        if (n instanceof Type) {
 | 
				
			||||||
          f(n, index++, this)
 | 
					          f(n, index++, this)
 | 
				
			||||||
 | 
					        } else if (n.constructor === ItemBinary) {
 | 
				
			||||||
 | 
					          f(n._content, index++, this)
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          const content = n._content
 | 
					          const content = n._content
 | 
				
			||||||
          const contentLen = content.length
 | 
					          const contentLen = content.length
 | 
				
			||||||
@ -239,7 +247,7 @@ export class YArray extends Type {
 | 
				
			|||||||
   *
 | 
					   *
 | 
				
			||||||
   * @private
 | 
					   * @private
 | 
				
			||||||
   * @param {Item} left The element container to use as a reference.
 | 
					   * @param {Item} left The element container to use as a reference.
 | 
				
			||||||
   * @param {Array} content The Array of content to insert (see {@see insert})
 | 
					   * @param {Array<number|string|Object|ArrayBuffer>} content The Array of content to insert (see {@see insert})
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  insertAfter (left, content) {
 | 
					  insertAfter (left, content) {
 | 
				
			||||||
    this._transact(y => {
 | 
					    this._transact(y => {
 | 
				
			||||||
@ -276,6 +284,29 @@ export class YArray extends Type {
 | 
				
			|||||||
            left._right = c
 | 
					            left._right = c
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          left = c
 | 
					          left = c
 | 
				
			||||||
 | 
					        } else if (c.constructor === ArrayBuffer) {
 | 
				
			||||||
 | 
					          if (prevJsonIns !== null) {
 | 
				
			||||||
 | 
					            if (y !== null) {
 | 
				
			||||||
 | 
					              prevJsonIns._integrate(y)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            left = prevJsonIns
 | 
				
			||||||
 | 
					            prevJsonIns = null
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          const itemBinary = new ItemBinary()
 | 
				
			||||||
 | 
					          itemBinary._origin = left
 | 
				
			||||||
 | 
					          itemBinary._left = left
 | 
				
			||||||
 | 
					          itemBinary._right = right
 | 
				
			||||||
 | 
					          itemBinary._right_origin = right
 | 
				
			||||||
 | 
					          itemBinary._parent = this
 | 
				
			||||||
 | 
					          itemBinary._content = c
 | 
				
			||||||
 | 
					          if (y !== null) {
 | 
				
			||||||
 | 
					            itemBinary._integrate(y)
 | 
				
			||||||
 | 
					          } else if (left === null) {
 | 
				
			||||||
 | 
					            this._start = itemBinary
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            left._right = itemBinary
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          left = itemBinary
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          if (prevJsonIns === null) {
 | 
					          if (prevJsonIns === null) {
 | 
				
			||||||
            prevJsonIns = new ItemJSON()
 | 
					            prevJsonIns = new ItemJSON()
 | 
				
			||||||
@ -294,6 +325,8 @@ export class YArray extends Type {
 | 
				
			|||||||
          prevJsonIns._integrate(y)
 | 
					          prevJsonIns._integrate(y)
 | 
				
			||||||
        } else if (prevJsonIns._left === null) {
 | 
					        } else if (prevJsonIns._left === null) {
 | 
				
			||||||
          this._start = prevJsonIns
 | 
					          this._start = prevJsonIns
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          left._right = prevJsonIns
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
@ -314,7 +347,7 @@ export class YArray extends Type {
 | 
				
			|||||||
   *  yarray.insert(2, [1, 2])
 | 
					   *  yarray.insert(2, [1, 2])
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * @param {number} index The index to insert content at.
 | 
					   * @param {number} index The index to insert content at.
 | 
				
			||||||
   * @param {Array} content The array of content
 | 
					   * @param {Array<number|string|ArrayBuffer|Type>} content The array of content
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  insert (index, content) {
 | 
					  insert (index, content) {
 | 
				
			||||||
    this._transact(() => {
 | 
					    this._transact(() => {
 | 
				
			||||||
@ -347,7 +380,7 @@ export class YArray extends Type {
 | 
				
			|||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Appends content to this YArray.
 | 
					   * Appends content to this YArray.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * @param {Array} content Array of content to append.
 | 
					   * @param {Array<number|string|ArrayBuffer|Type>} content Array of content to append.
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  push (content) {
 | 
					  push (content) {
 | 
				
			||||||
    let n = this._start
 | 
					    let n = this._start
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,8 @@ import { Type } from '../structs/Type.js'
 | 
				
			|||||||
import { ItemJSON } from '../structs/ItemJSON.js'
 | 
					import { ItemJSON } from '../structs/ItemJSON.js'
 | 
				
			||||||
import * as stringify from '../utils/structStringify.js'
 | 
					import * as stringify from '../utils/structStringify.js'
 | 
				
			||||||
import { YEvent } from '../utils/YEvent.js'
 | 
					import { YEvent } from '../utils/YEvent.js'
 | 
				
			||||||
 | 
					import { ItemBinary } from '../structs/ItemBinary.js'
 | 
				
			||||||
 | 
					import { isVisible } from '../utils/snapshot.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Event that describes the changes on a YMap.
 | 
					 * Event that describes the changes on a YMap.
 | 
				
			||||||
@ -53,6 +55,8 @@ export class YMap extends Type {
 | 
				
			|||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            res = item.toString()
 | 
					            res = item.toString()
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
 | 
					        } else if (item.constructor === ItemBinary) {
 | 
				
			||||||
 | 
					          res = item._content
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          res = item._content[0]
 | 
					          res = item._content[0]
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -65,16 +69,25 @@ export class YMap extends Type {
 | 
				
			|||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Returns the keys for each element in the YMap Type.
 | 
					   * Returns the keys for each element in the YMap Type.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
 | 
					   * @param {import('../protocols/history.js').HistorySnapshot} [snapshot]
 | 
				
			||||||
   * @return {Array}
 | 
					   * @return {Array}
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  keys () {
 | 
					  keys (snapshot) {
 | 
				
			||||||
    // TODO: Should return either Iterator or Set!
 | 
					    // TODO: Should return either Iterator or Set!
 | 
				
			||||||
    let keys = []
 | 
					    let keys = []
 | 
				
			||||||
 | 
					    if (snapshot === undefined) {
 | 
				
			||||||
      for (let [key, value] of this._map) {
 | 
					      for (let [key, value] of this._map) {
 | 
				
			||||||
      if (!value._deleted) {
 | 
					        if (value._deleted) {
 | 
				
			||||||
          keys.push(key)
 | 
					          keys.push(key)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      for (let key in this._map) {
 | 
				
			||||||
 | 
					        if (this.has(key, snapshot)) {
 | 
				
			||||||
 | 
					          keys.push(key)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return keys
 | 
					    return keys
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -96,7 +109,7 @@ export class YMap extends Type {
 | 
				
			|||||||
   * Adds or updates an element with a specified key and value.
 | 
					   * Adds or updates an element with a specified key and value.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * @param {string} key The key of the element to add to this YMap
 | 
					   * @param {string} key The key of the element to add to this YMap
 | 
				
			||||||
   * @param {Object | string | number | Type} value The value of the element to add
 | 
					   * @param {Object | string | number | Type | ArrayBuffer } value The value of the element to add
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  set (key, value) {
 | 
					  set (key, value) {
 | 
				
			||||||
    this._transact(y => {
 | 
					    this._transact(y => {
 | 
				
			||||||
@ -120,6 +133,9 @@ export class YMap extends Type {
 | 
				
			|||||||
        value = v
 | 
					        value = v
 | 
				
			||||||
      } else if (value instanceof Item) {
 | 
					      } else if (value instanceof Item) {
 | 
				
			||||||
        v = value
 | 
					        v = value
 | 
				
			||||||
 | 
					      } else if (value.constructor === ArrayBuffer) {
 | 
				
			||||||
 | 
					        v = new ItemBinary()
 | 
				
			||||||
 | 
					        v._content = value
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        v = new ItemJSON()
 | 
					        v = new ItemJSON()
 | 
				
			||||||
        v._content = [value]
 | 
					        v._content = [value]
 | 
				
			||||||
@ -141,31 +157,48 @@ export class YMap extends Type {
 | 
				
			|||||||
   * Returns a specified element from this YMap.
 | 
					   * Returns a specified element from this YMap.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * @param {string} key The key of the element to return.
 | 
					   * @param {string} key The key of the element to return.
 | 
				
			||||||
 | 
					   * @param {import('../protocols/history.js').HistorySnapshot} [snapshot]
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  get (key) {
 | 
					  get (key, snapshot) {
 | 
				
			||||||
    let v = this._map.get(key)
 | 
					    let v = this._map.get(key)
 | 
				
			||||||
    if (v === undefined || v._deleted) {
 | 
					    if (v === undefined) {
 | 
				
			||||||
      return undefined
 | 
					      return undefined
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (snapshot !== undefined) {
 | 
				
			||||||
 | 
					      // iterate until found element that exists
 | 
				
			||||||
 | 
					      while (!snapshot.sm.has(v._id.user) || v._id.clock >= snapshot.sm.get(v._id.user)) {
 | 
				
			||||||
 | 
					        v = v._right
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (isVisible(v, snapshot)) {
 | 
				
			||||||
      if (v instanceof Type) {
 | 
					      if (v instanceof Type) {
 | 
				
			||||||
        return v
 | 
					        return v
 | 
				
			||||||
 | 
					      } else if (v.constructor === ItemBinary) {
 | 
				
			||||||
 | 
					        return v._content
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        return v._content[v._content.length - 1]
 | 
					        return v._content[v._content.length - 1]
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Returns a boolean indicating whether the specified key exists or not.
 | 
					   * Returns a boolean indicating whether the specified key exists or not.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * @param {string} key The key to test.
 | 
					   * @param {string} key The key to test.
 | 
				
			||||||
 | 
					   * @param {import('../protocols/history.js').HistorySnapshot} [snapshot]
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  has (key) {
 | 
					  has (key, snapshot) {
 | 
				
			||||||
    let v = this._map.get(key)
 | 
					    let v = this._map.get(key)
 | 
				
			||||||
    if (v === undefined || v._deleted) {
 | 
					    if (v === undefined) {
 | 
				
			||||||
      return false
 | 
					      return false
 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      return true
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (snapshot !== undefined) {
 | 
				
			||||||
 | 
					      // iterate until found element that exists
 | 
				
			||||||
 | 
					      while (!snapshot.sm.has(v._id.user) || v._id.clock >= snapshot.sm.get(v._id.user)) {
 | 
				
			||||||
 | 
					        v = v._right
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return isVisible(v, snapshot)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@ import { ItemString } from '../structs/ItemString.js'
 | 
				
			|||||||
import { ItemFormat } from '../structs/ItemFormat.js'
 | 
					import { ItemFormat } from '../structs/ItemFormat.js'
 | 
				
			||||||
import * as stringify from '../utils/structStringify.js'
 | 
					import * as stringify from '../utils/structStringify.js'
 | 
				
			||||||
import { YArrayEvent, YArray } from './YArray.js'
 | 
					import { YArrayEvent, YArray } from './YArray.js'
 | 
				
			||||||
 | 
					import { isVisible } from '../utils/snapshot.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @private
 | 
					 * @private
 | 
				
			||||||
@ -570,11 +571,12 @@ export class YText extends YArray {
 | 
				
			|||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Returns the Delta representation of this YText type.
 | 
					   * Returns the Delta representation of this YText type.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
 | 
					   * @param {import('../protocols/history.js').HistorySnapshot} [snapshot]
 | 
				
			||||||
   * @return {Delta} The Delta representation of this type.
 | 
					   * @return {Delta} The Delta representation of this type.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * @public
 | 
					   * @public
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  toDelta () {
 | 
					  toDelta (snapshot) {
 | 
				
			||||||
    let ops = []
 | 
					    let ops = []
 | 
				
			||||||
    let currentAttributes = new Map()
 | 
					    let currentAttributes = new Map()
 | 
				
			||||||
    let str = ''
 | 
					    let str = ''
 | 
				
			||||||
@ -600,7 +602,7 @@ export class YText extends YArray {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    while (n !== null) {
 | 
					    while (n !== null) {
 | 
				
			||||||
      if (!n._deleted) {
 | 
					      if (isVisible(n, snapshot)) {
 | 
				
			||||||
        switch (n.constructor) {
 | 
					        switch (n.constructor) {
 | 
				
			||||||
          case ItemString:
 | 
					          case ItemString:
 | 
				
			||||||
            str += n._content
 | 
					            str += n._content
 | 
				
			||||||
 | 
				
			|||||||
@ -300,28 +300,36 @@ export class YXmlElement extends YXmlFragment {
 | 
				
			|||||||
   *
 | 
					   *
 | 
				
			||||||
   * @param {String} attributeName The attribute name that identifies the
 | 
					   * @param {String} attributeName The attribute name that identifies the
 | 
				
			||||||
   *                               queried value.
 | 
					   *                               queried value.
 | 
				
			||||||
 | 
					   * @param {import('../protocols/history.js').HistorySnapshot} [snapshot]
 | 
				
			||||||
   * @return {String} The queried attribute value.
 | 
					   * @return {String} The queried attribute value.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * @public
 | 
					   * @public
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  getAttribute (attributeName) {
 | 
					  getAttribute (attributeName, snapshot) {
 | 
				
			||||||
    return YMap.prototype.get.call(this, attributeName)
 | 
					    return YMap.prototype.get.call(this, attributeName, snapshot)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Returns all attribute name/value pairs in a JSON Object.
 | 
					   * Returns all attribute name/value pairs in a JSON Object.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
 | 
					   * @param {import('../protocols/history.js').HistorySnapshot} [snapshot]
 | 
				
			||||||
   * @return {Object} A JSON Object that describes the attributes.
 | 
					   * @return {Object} A JSON Object that describes the attributes.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * @public
 | 
					   * @public
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  getAttributes () {
 | 
					  getAttributes (snapshot) {
 | 
				
			||||||
    const obj = {}
 | 
					    const obj = {}
 | 
				
			||||||
 | 
					    if (snapshot === undefined) {
 | 
				
			||||||
      for (let [key, value] of this._map) {
 | 
					      for (let [key, value] of this._map) {
 | 
				
			||||||
        if (!value._deleted) {
 | 
					        if (!value._deleted) {
 | 
				
			||||||
          obj[key] = value._content[0]
 | 
					          obj[key] = value._content[0]
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      for (let key in this._map) {
 | 
				
			||||||
 | 
					        return YMap.prototype.get.call(this, key, snapshot)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return obj
 | 
					    return obj
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  // TODO: outsource the binding property.
 | 
					  // TODO: outsource the binding property.
 | 
				
			||||||
 | 
				
			|||||||
@ -5,6 +5,10 @@
 | 
				
			|||||||
import { Tree } from '../lib/Tree.js'
 | 
					import { Tree } from '../lib/Tree.js'
 | 
				
			||||||
import * as ID from './ID.js'
 | 
					import * as ID from './ID.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import * as encoding from '../lib/encoding.js'
 | 
				
			||||||
 | 
					import * as decoding from '../lib/decoding.js'
 | 
				
			||||||
 | 
					import { deleteItemRange } from '../utils/structManipulation.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DSNode {
 | 
					class DSNode {
 | 
				
			||||||
  constructor (id, len, gc) {
 | 
					  constructor (id, len, gc) {
 | 
				
			||||||
    this._id = id
 | 
					    this._id = id
 | 
				
			||||||
@ -86,8 +90,168 @@ export class DeleteStore extends Tree {
 | 
				
			|||||||
      this.put(newMark)
 | 
					      this.put(newMark)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  // TODO: exchange markDeleted for mark()
 | 
					}
 | 
				
			||||||
  markDeleted (id, length) {
 | 
					
 | 
				
			||||||
    this.mark(id, length, false)
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Stringifies a message-encoded Delete Set.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param {decoding.Decoder} decoder
 | 
				
			||||||
 | 
					 * @return {string}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const stringifyDeleteStore = (decoder) => {
 | 
				
			||||||
 | 
					  let str = ''
 | 
				
			||||||
 | 
					  const dsLength = decoding.readUint32(decoder)
 | 
				
			||||||
 | 
					  for (let i = 0; i < dsLength; i++) {
 | 
				
			||||||
 | 
					    str += ' -' + decoding.readVarUint(decoder) + ':\n' // decodes user
 | 
				
			||||||
 | 
					    const dvLength = decoding.readUint32(decoder)
 | 
				
			||||||
 | 
					    for (let j = 0; j < dvLength; j++) {
 | 
				
			||||||
 | 
					      str += `clock: ${decoding.readVarUint(decoder)}, length: ${decoding.readVarUint(decoder)}, gc: ${decoding.readUint8(decoder) === 1}\n`
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return str
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Write the DeleteSet of a shared document to an Encoder.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param {encoding.Encoder} encoder
 | 
				
			||||||
 | 
					 * @param {DeleteStore} ds
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const writeDeleteStore = (encoder, ds) => {
 | 
				
			||||||
 | 
					  let currentUser = null
 | 
				
			||||||
 | 
					  let currentLength
 | 
				
			||||||
 | 
					  let lastLenPos
 | 
				
			||||||
 | 
					  let numberOfUsers = 0
 | 
				
			||||||
 | 
					  const laterDSLenPus = encoding.length(encoder)
 | 
				
			||||||
 | 
					  encoding.writeUint32(encoder, 0)
 | 
				
			||||||
 | 
					  ds.iterate(null, null, n => {
 | 
				
			||||||
 | 
					    const user = n._id.user
 | 
				
			||||||
 | 
					    const clock = n._id.clock
 | 
				
			||||||
 | 
					    const len = n.len
 | 
				
			||||||
 | 
					    const gc = n.gc
 | 
				
			||||||
 | 
					    if (currentUser !== user) {
 | 
				
			||||||
 | 
					      numberOfUsers++
 | 
				
			||||||
 | 
					      // a new user was found
 | 
				
			||||||
 | 
					      if (currentUser !== null) { // happens on first iteration
 | 
				
			||||||
 | 
					        encoding.setUint32(encoder, lastLenPos, currentLength)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      currentUser = user
 | 
				
			||||||
 | 
					      encoding.writeVarUint(encoder, user)
 | 
				
			||||||
 | 
					      // pseudo-fill pos
 | 
				
			||||||
 | 
					      lastLenPos = encoding.length(encoder)
 | 
				
			||||||
 | 
					      encoding.writeUint32(encoder, 0)
 | 
				
			||||||
 | 
					      currentLength = 0
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    encoding.writeVarUint(encoder, clock)
 | 
				
			||||||
 | 
					    encoding.writeVarUint(encoder, len)
 | 
				
			||||||
 | 
					    encoding.writeUint8(encoder, gc ? 1 : 0)
 | 
				
			||||||
 | 
					    currentLength++
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					  if (currentUser !== null) { // happens on first iteration
 | 
				
			||||||
 | 
					    encoding.setUint32(encoder, lastLenPos, currentLength)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  encoding.setUint32(encoder, laterDSLenPus, numberOfUsers)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Read delete store from Decoder and create a fresh DeleteStore
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param {decoding.Decoder} decoder
 | 
				
			||||||
 | 
					 * @return {DeleteStore}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const readFreshDeleteStore = decoder => {
 | 
				
			||||||
 | 
					  const ds = new DeleteStore()
 | 
				
			||||||
 | 
					  const dsLength = decoding.readUint32(decoder)
 | 
				
			||||||
 | 
					  for (let i = 0; i < dsLength; i++) {
 | 
				
			||||||
 | 
					    const user = decoding.readVarUint(decoder)
 | 
				
			||||||
 | 
					    const dvLength = decoding.readUint32(decoder)
 | 
				
			||||||
 | 
					    for (let j = 0; j < dvLength; j++) {
 | 
				
			||||||
 | 
					      const from = decoding.readVarUint(decoder)
 | 
				
			||||||
 | 
					      const len = decoding.readVarUint(decoder)
 | 
				
			||||||
 | 
					      const gc = decoding.readUint8(decoder)
 | 
				
			||||||
 | 
					      ds.put(new DSNode(ID.createID(user, from), len, gc))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return ds
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Read delete set from Decoder and apply it to a shared document.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param {decoding.Decoder} decoder
 | 
				
			||||||
 | 
					 * @param {Y} y
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const readDeleteStore = (decoder, y) => {
 | 
				
			||||||
 | 
					  const dsLength = decoding.readUint32(decoder)
 | 
				
			||||||
 | 
					  for (let i = 0; i < dsLength; i++) {
 | 
				
			||||||
 | 
					    const user = decoding.readVarUint(decoder)
 | 
				
			||||||
 | 
					    const dv = []
 | 
				
			||||||
 | 
					    const dvLength = decoding.readUint32(decoder)
 | 
				
			||||||
 | 
					    for (let j = 0; j < dvLength; j++) {
 | 
				
			||||||
 | 
					      const from = decoding.readVarUint(decoder)
 | 
				
			||||||
 | 
					      const len = decoding.readVarUint(decoder)
 | 
				
			||||||
 | 
					      const gc = decoding.readUint8(decoder) === 1
 | 
				
			||||||
 | 
					      dv.push({from, len, gc})
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (dvLength > 0) {
 | 
				
			||||||
 | 
					      const deletions = []
 | 
				
			||||||
 | 
					      let pos = 0
 | 
				
			||||||
 | 
					      let d = dv[pos]
 | 
				
			||||||
 | 
					      y.ds.iterate(ID.createID(user, 0), ID.createID(user, Number.MAX_VALUE), n => {
 | 
				
			||||||
 | 
					        // cases:
 | 
				
			||||||
 | 
					        // 1. d deletes something to the right of n
 | 
				
			||||||
 | 
					        //  => go to next n (break)
 | 
				
			||||||
 | 
					        // 2. d deletes something to the left of n
 | 
				
			||||||
 | 
					        //  => create deletions
 | 
				
			||||||
 | 
					        //  => reset d accordingly
 | 
				
			||||||
 | 
					        //  *)=> if d doesn't delete anything anymore, go to next d (continue)
 | 
				
			||||||
 | 
					        // 3. not 2) and d deletes something that also n deletes
 | 
				
			||||||
 | 
					        //  => reset d so that it doesn't contain n's deletion
 | 
				
			||||||
 | 
					        //  *)=> if d does not delete anything anymore, go to next d (continue)
 | 
				
			||||||
 | 
					        while (d != null) {
 | 
				
			||||||
 | 
					          var diff = 0 // describe the diff of length in 1) and 2)
 | 
				
			||||||
 | 
					          if (n._id.clock + n.len <= d.from) {
 | 
				
			||||||
 | 
					            // 1)
 | 
				
			||||||
 | 
					            break
 | 
				
			||||||
 | 
					          } else if (d.from < n._id.clock) {
 | 
				
			||||||
 | 
					            // 2)
 | 
				
			||||||
 | 
					            // delete maximum the len of d
 | 
				
			||||||
 | 
					            // else delete as much as possible
 | 
				
			||||||
 | 
					            diff = Math.min(n._id.clock - d.from, d.len)
 | 
				
			||||||
 | 
					            // deleteItemRange(y, user, d.from, diff, true)
 | 
				
			||||||
 | 
					            deletions.push([user, d.from, diff])
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            // 3)
 | 
				
			||||||
 | 
					            diff = n._id.clock + n.len - d.from // never null (see 1)
 | 
				
			||||||
 | 
					            if (d.gc && !n.gc) {
 | 
				
			||||||
 | 
					              // d marks as gc'd but n does not
 | 
				
			||||||
 | 
					              // then delete either way
 | 
				
			||||||
 | 
					              // deleteItemRange(y, user, d.from, Math.min(diff, d.len), true)
 | 
				
			||||||
 | 
					              deletions.push([user, d.from, Math.min(diff, d.len)])
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          if (d.len <= diff) {
 | 
				
			||||||
 | 
					            // d doesn't delete anything anymore
 | 
				
			||||||
 | 
					            d = dv[++pos]
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            d.from = d.from + diff // reset pos
 | 
				
			||||||
 | 
					            d.len = d.len - diff // reset length
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      // TODO: It would be more performant to apply the deletes in the above loop
 | 
				
			||||||
 | 
					      // Adapt the Tree implementation to support delete while iterating
 | 
				
			||||||
 | 
					      for (let i = deletions.length - 1; i >= 0; i--) {
 | 
				
			||||||
 | 
					        const del = deletions[i]
 | 
				
			||||||
 | 
					        deleteItemRange(y, del[0], del[1], del[2], true)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      // for the rest.. just apply it
 | 
				
			||||||
 | 
					      for (; pos < dv.length; pos++) {
 | 
				
			||||||
 | 
					        d = dv[pos]
 | 
				
			||||||
 | 
					        deleteItemRange(y, user, d.from, d.len, true)
 | 
				
			||||||
 | 
					        // deletions.push([user, d.from, d.len, d.gc)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -4,12 +4,65 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import * as ID from '../utils/ID.js'
 | 
					import * as ID from '../utils/ID.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import * as encoding from '../lib/encoding.js'
 | 
				
			||||||
 | 
					import * as decoding from '../lib/decoding.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const writeStateStore = (encoder, ss) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @typedef {Map<number, number>} StateSet
 | 
					 * @typedef {Map<number, number>} StateMap
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @private
 | 
					 * Read StateMap from Decoder and return as Map
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param {decoding.Decoder} decoder
 | 
				
			||||||
 | 
					 * @return {StateMap}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const readStateMap = decoder => {
 | 
				
			||||||
 | 
					  const ss = new Map()
 | 
				
			||||||
 | 
					  const ssLength = decoding.readUint32(decoder)
 | 
				
			||||||
 | 
					  for (let i = 0; i < ssLength; i++) {
 | 
				
			||||||
 | 
					    const user = decoding.readVarUint(decoder)
 | 
				
			||||||
 | 
					    const clock = decoding.readVarUint(decoder)
 | 
				
			||||||
 | 
					    ss.set(user, clock)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return ss
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Write StateMap to Encoder
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param {encoding.Encoder} encoder
 | 
				
			||||||
 | 
					 * @param {StateMap} state
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const writeStateMap = (encoder, state) => {
 | 
				
			||||||
 | 
					  // write as fixed-size number to stay consistent with the other encode functions.
 | 
				
			||||||
 | 
					  // => anytime we write the number of objects that follow, encode as fixed-size number.
 | 
				
			||||||
 | 
					  encoding.writeUint32(encoder, state.size)
 | 
				
			||||||
 | 
					  state.forEach((clock, user) => {
 | 
				
			||||||
 | 
					    encoding.writeVarUint(encoder, user)
 | 
				
			||||||
 | 
					    encoding.writeVarUint(encoder, clock)
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Read a StateMap from Decoder and return it as string.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param {decoding.Decoder} decoder
 | 
				
			||||||
 | 
					 * @return {string}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const stringifyStateMap = decoder => {
 | 
				
			||||||
 | 
					  let s = 'State Set: '
 | 
				
			||||||
 | 
					  readStateMap(decoder).forEach((clock, user) => {
 | 
				
			||||||
 | 
					    s += `(${user}: ${clock}), `
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					  return s
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export class StateStore {
 | 
					export class StateStore {
 | 
				
			||||||
  constructor (y) {
 | 
					  constructor (y) {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
import { DeleteStore } from './DeleteStore.js'
 | 
					import { DeleteStore, readDeleteStore, writeDeleteStore } from './DeleteStore.js'
 | 
				
			||||||
import { OperationStore } from './OperationStore.js'
 | 
					import { OperationStore } from './OperationStore.js'
 | 
				
			||||||
import { StateStore } from './StateStore.js'
 | 
					import { StateStore } from './StateStore.js'
 | 
				
			||||||
import { generateRandomUint32 } from './generateRandomUint32.js'
 | 
					import { generateRandomUint32 } from './generateRandomUint32.js'
 | 
				
			||||||
@ -59,7 +59,7 @@ export class Y extends NamedEventHandler {
 | 
				
			|||||||
  importModel (decoder) {
 | 
					  importModel (decoder) {
 | 
				
			||||||
    this.transact(() => {
 | 
					    this.transact(() => {
 | 
				
			||||||
      integrateRemoteStructs(decoder, this)
 | 
					      integrateRemoteStructs(decoder, this)
 | 
				
			||||||
      message.readDeleteSet(decoder, this)
 | 
					      readDeleteStore(decoder, this)
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -71,7 +71,7 @@ export class Y extends NamedEventHandler {
 | 
				
			|||||||
  exportModel () {
 | 
					  exportModel () {
 | 
				
			||||||
    const encoder = encoding.createEncoder()
 | 
					    const encoder = encoding.createEncoder()
 | 
				
			||||||
    message.writeStructs(encoder, this, new Map())
 | 
					    message.writeStructs(encoder, this, new Map())
 | 
				
			||||||
    message.writeDeleteSet(encoder, this)
 | 
					    writeDeleteStore(encoder, this.ds)
 | 
				
			||||||
    return encoding.toBuffer(encoder)
 | 
					    return encoding.toBuffer(encoder)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  _beforeChange () {}
 | 
					  _beforeChange () {}
 | 
				
			||||||
@ -174,7 +174,7 @@ export class Y extends NamedEventHandler {
 | 
				
			|||||||
   *
 | 
					   *
 | 
				
			||||||
   * @param {String} name
 | 
					   * @param {String} name
 | 
				
			||||||
   * @param {Function} TypeConstructor The constructor of the type definition
 | 
					   * @param {Function} TypeConstructor The constructor of the type definition
 | 
				
			||||||
   * @returns {Type} The created type. Constructed with TypeConstructor
 | 
					   * @returns {any} The created type. Constructed with TypeConstructor
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  define (name, TypeConstructor) {
 | 
					  define (name, TypeConstructor) {
 | 
				
			||||||
    let id = createRootID(name, TypeConstructor)
 | 
					    let id = createRootID(name, TypeConstructor)
 | 
				
			||||||
@ -194,6 +194,7 @@ export class Y extends NamedEventHandler {
 | 
				
			|||||||
   * This returns the same value as `y.share[name]`
 | 
					   * This returns the same value as `y.share[name]`
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * @param {String} name The typename
 | 
					   * @param {String} name The typename
 | 
				
			||||||
 | 
					   * @return {any}
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  get (name) {
 | 
					  get (name) {
 | 
				
			||||||
    return this._map.get(name)
 | 
					    return this._map.get(name)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										8
									
								
								utils/snapshot.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								utils/snapshot.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @param {Item} item
 | 
				
			||||||
 | 
					 * @param {import("../protocols/history").HistorySnapshot} [snapshot]
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const isVisible = (item, snapshot) => snapshot === undefined ? !item._deleted : (snapshot.sm.has(item._id.user) && snapshot.sm.get(item._id.user) > item._id.clock && !snapshot.ds.isDeleted(item._id))
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user