UNPKG

json-joy

Version:

Collection of libraries for building collaborative editing apps.

75 lines (74 loc) 2.65 kB
import { isEmpty } from '@jsonjoy.com/util/lib/isEmpty'; import { deepEqual } from '@jsonjoy.com/util/lib/json-equal/deepEqual'; import { Peritext } from '../peritext'; import { ExtensionId } from '../constants'; import { MNEMONIC, QuillConst } from './constants'; import { ExtNode } from '../../json-crdt/extensions/ExtNode'; import { getAttributes } from './util'; import { updateRga } from '../../json-crdt/hash'; export class QuillDeltaNode extends ExtNode { data; txt; constructor(data) { super(data); this.data = data; this.txt = new Peritext(data.doc, this.text(), this.slices()); } text() { return this.data.get(0); } slices() { return this.data.get(1); } // ------------------------------------------------------------------ ExtNode extId = ExtensionId.quill; name() { return MNEMONIC; } _view = []; _viewHash = -1; view() { const overlay = this.txt.overlay; const hash = updateRga(overlay.refresh(true), this.txt.str); if (hash === this._viewHash) return this._view; const ops = []; let chunk; const nextTuple = overlay.tuples0(undefined); let tuple; while ((tuple = nextTuple())) { const [p1, p2] = tuple; const attributes = getAttributes(p1); let insert = ''; chunk = overlay.chunkSlices0(chunk, p1, p2, (chunk, off, len) => { const data = chunk.data; if (data) insert += data.slice(off, off + len); }); if (insert) { if (insert === QuillConst.EmbedChar && attributes && attributes[QuillConst.EmbedSliceType]) { const op = { insert: attributes[QuillConst.EmbedSliceType] }; delete attributes[QuillConst.EmbedSliceType]; if (!isEmpty(attributes)) op.attributes = attributes; ops.push(op); continue; } else { const lastOp = ops[ops.length - 1]; if (lastOp && typeof lastOp.insert === 'string' && deepEqual(lastOp.attributes, attributes)) { lastOp.insert += insert; continue; } } const op = { insert }; if (attributes) op.attributes = attributes; ops.push(op); } } this._viewHash = hash; this._view = ops; return ops; } }