| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- /* eslint-disable
- camelcase,
- no-undef,
- */
- // TODO: This file was created by bulk-decaffeinate.
- // Fix any style issues and re-enable lint.
- /*
- * decaffeinate suggestions:
- * DS101: Remove unnecessary use of Array.from
- * DS102: Remove unnecessary code created because of implicit returns
- * DS205: Consider reworking code to avoid use of IIFEs
- * DS207: Consider shorter variations of null checks
- * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
- */
- // API for JSON OT
- let json
- if (typeof WEB === 'undefined') {
- json = require('./json')
- }
- if (typeof WEB !== 'undefined' && WEB !== null) {
- const { extendDoc } = exports
- exports.extendDoc = function (name, fn) {
- SubDoc.prototype[name] = fn
- return extendDoc(name, fn)
- }
- }
- const depath = function (path) {
- if (path.length === 1 && path[0].constructor === Array) {
- return path[0]
- } else {
- return path
- }
- }
- class SubDoc {
- constructor(doc, path) {
- this.doc = doc
- this.path = path
- }
- at(...path) {
- return this.doc.at(this.path.concat(depath(path)))
- }
- get() {
- return this.doc.getAt(this.path)
- }
- // for objects and lists
- set(value, cb) {
- return this.doc.setAt(this.path, value, cb)
- }
- // for strings and lists.
- insert(pos, value, cb) {
- return this.doc.insertAt(this.path, pos, value, cb)
- }
- // for strings
- del(pos, length, cb) {
- return this.doc.deleteTextAt(this.path, length, pos, cb)
- }
- // for objects and lists
- remove(cb) {
- return this.doc.removeAt(this.path, cb)
- }
- push(value, cb) {
- return this.insert(this.get().length, value, cb)
- }
- move(from, to, cb) {
- return this.doc.moveAt(this.path, from, to, cb)
- }
- add(amount, cb) {
- return this.doc.addAt(this.path, amount, cb)
- }
- on(event, cb) {
- return this.doc.addListener(this.path, event, cb)
- }
- removeListener(l) {
- return this.doc.removeListener(l)
- }
- // text API compatibility
- getLength() {
- return this.get().length
- }
- getText() {
- return this.get()
- }
- }
- const traverse = function (snapshot, path) {
- const container = { data: snapshot }
- let key = 'data'
- let elem = container
- for (const p of Array.from(path)) {
- elem = elem[key]
- key = p
- if (typeof elem === 'undefined') {
- throw new Error('bad path')
- }
- }
- return { elem, key }
- }
- const pathEquals = function (p1, p2) {
- if (p1.length !== p2.length) {
- return false
- }
- for (let i = 0; i < p1.length; i++) {
- const e = p1[i]
- if (e !== p2[i]) {
- return false
- }
- }
- return true
- }
- json.api = {
- provides: { json: true },
- at(...path) {
- return new SubDoc(this, depath(path))
- },
- get() {
- return this.snapshot
- },
- set(value, cb) {
- return this.setAt([], value, cb)
- },
- getAt(path) {
- const { elem, key } = traverse(this.snapshot, path)
- return elem[key]
- },
- setAt(path, value, cb) {
- const { elem, key } = traverse(this.snapshot, path)
- const op = { p: path }
- if (elem.constructor === Array) {
- op.li = value
- if (typeof elem[key] !== 'undefined') {
- op.ld = elem[key]
- }
- } else if (typeof elem === 'object') {
- op.oi = value
- if (typeof elem[key] !== 'undefined') {
- op.od = elem[key]
- }
- } else {
- throw new Error('bad path')
- }
- return this.submitOp([op], cb)
- },
- removeAt(path, cb) {
- const { elem, key } = traverse(this.snapshot, path)
- if (typeof elem[key] === 'undefined') {
- throw new Error('no element at that path')
- }
- const op = { p: path }
- if (elem.constructor === Array) {
- op.ld = elem[key]
- } else if (typeof elem === 'object') {
- op.od = elem[key]
- } else {
- throw new Error('bad path')
- }
- return this.submitOp([op], cb)
- },
- insertAt(path, pos, value, cb) {
- const { elem, key } = traverse(this.snapshot, path)
- const op = { p: path.concat(pos) }
- if (elem[key].constructor === Array) {
- op.li = value
- } else if (typeof elem[key] === 'string') {
- op.si = value
- }
- return this.submitOp([op], cb)
- },
- moveAt(path, from, to, cb) {
- const op = [{ p: path.concat(from), lm: to }]
- return this.submitOp(op, cb)
- },
- addAt(path, amount, cb) {
- const op = [{ p: path, na: amount }]
- return this.submitOp(op, cb)
- },
- deleteTextAt(path, length, pos, cb) {
- const { elem, key } = traverse(this.snapshot, path)
- const op = [{ p: path.concat(pos), sd: elem[key].slice(pos, pos + length) }]
- return this.submitOp(op, cb)
- },
- addListener(path, event, cb) {
- const l = { path, event, cb }
- this._listeners.push(l)
- return l
- },
- removeListener(l) {
- const i = this._listeners.indexOf(l)
- if (i < 0) {
- return false
- }
- this._listeners.splice(i, 1)
- return true
- },
- _register() {
- this._listeners = []
- this.on('change', function (op) {
- return (() => {
- const result = []
- for (const c of Array.from(op)) {
- var i
- if (c.na !== undefined || c.si !== undefined || c.sd !== undefined) {
- // no change to structure
- continue
- }
- var to_remove = []
- for (i = 0; i < this._listeners.length; i++) {
- // Transform a dummy op by the incoming op to work out what
- // should happen to the listener.
- const l = this._listeners[i]
- const dummy = { p: l.path, na: 0 }
- const xformed = this.type.transformComponent([], dummy, c, 'left')
- if (xformed.length === 0) {
- // The op was transformed to noop, so we should delete the listener.
- to_remove.push(i)
- } else if (xformed.length === 1) {
- // The op remained, so grab its new path into the listener.
- l.path = xformed[0].p
- } else {
- throw new Error(
- "Bad assumption in json-api: xforming an 'si' op will always result in 0 or 1 components."
- )
- }
- }
- to_remove.sort((a, b) => b - a)
- result.push(
- (() => {
- const result1 = []
- for (i of Array.from(to_remove)) {
- result1.push(this._listeners.splice(i, 1))
- }
- return result1
- })()
- )
- }
- return result
- })()
- })
- return this.on('remoteop', function (op) {
- return (() => {
- const result = []
- for (var c of Array.from(op)) {
- var match_path =
- c.na === undefined ? c.p.slice(0, c.p.length - 1) : c.p
- result.push(
- (() => {
- const result1 = []
- for (const { path, event, cb } of Array.from(this._listeners)) {
- var common
- if (pathEquals(path, match_path)) {
- switch (event) {
- case 'insert':
- if (c.li !== undefined && c.ld === undefined) {
- result1.push(cb(c.p[c.p.length - 1], c.li))
- } else if (c.oi !== undefined && c.od === undefined) {
- result1.push(cb(c.p[c.p.length - 1], c.oi))
- } else if (c.si !== undefined) {
- result1.push(cb(c.p[c.p.length - 1], c.si))
- } else {
- result1.push(undefined)
- }
- break
- case 'delete':
- if (c.li === undefined && c.ld !== undefined) {
- result1.push(cb(c.p[c.p.length - 1], c.ld))
- } else if (c.oi === undefined && c.od !== undefined) {
- result1.push(cb(c.p[c.p.length - 1], c.od))
- } else if (c.sd !== undefined) {
- result1.push(cb(c.p[c.p.length - 1], c.sd))
- } else {
- result1.push(undefined)
- }
- break
- case 'replace':
- if (c.li !== undefined && c.ld !== undefined) {
- result1.push(cb(c.p[c.p.length - 1], c.ld, c.li))
- } else if (c.oi !== undefined && c.od !== undefined) {
- result1.push(cb(c.p[c.p.length - 1], c.od, c.oi))
- } else {
- result1.push(undefined)
- }
- break
- case 'move':
- if (c.lm !== undefined) {
- result1.push(cb(c.p[c.p.length - 1], c.lm))
- } else {
- result1.push(undefined)
- }
- break
- case 'add':
- if (c.na !== undefined) {
- result1.push(cb(c.na))
- } else {
- result1.push(undefined)
- }
- break
- default:
- result1.push(undefined)
- }
- } else if (
- (common = this.type.commonPath(match_path, path)) != null
- ) {
- if (event === 'child op') {
- if (
- match_path.length === path.length &&
- path.length === common
- ) {
- throw new Error(
- "paths match length and have commonality, but aren't equal?"
- )
- }
- const child_path = c.p.slice(common + 1)
- result1.push(cb(child_path, c))
- } else {
- result1.push(undefined)
- }
- } else {
- result1.push(undefined)
- }
- }
- return result1
- })()
- )
- }
- return result
- })()
- })
- },
- }
|