UNPKG

json-joy

Version:

Collection of libraries for building collaborative editing apps.

77 lines (76 loc) 3.02 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Fragment = void 0; const Block_1 = require("./Block"); const commonLength_1 = require("../util/commonLength"); const printTree_1 = require("tree-dump/lib/printTree"); const LeafBlock_1 = require("./LeafBlock"); const Range_1 = require("../rga/Range"); const slice_1 = require("../slice"); /** * A *fragment* represents a structural slice of a rich-text document. A * fragment can be bound to a specific range of text contents, however it * always constructs a tree of {@link Block}s, which represent the nested * structure of the text contents. */ class Fragment extends Range_1.Range { constructor(txt, start, end) { super(txt.str, start, end); this.txt = txt; // ----------------------------------------------------------------- Stateful this.hash = 0; this.root = new Block_1.Block(txt, [], void 0, start, end); } // ------------------------------------------------------------------- export toJson() { const node = this.root.toJson(); node[0] = ''; return node; } // ---------------------------------------------------------------- Printable toString(tab = '') { return 'Fragment' + (0, printTree_1.printTree)(tab, [(tab) => this.root.toString(tab)]); } refresh() { this.build(); return (this.hash = this.root.refresh()); } insertBlock(parent, path, marker, end = this.end) { const txt = this.txt; const common = (0, commonLength_1.commonLength)(path, parent.path); const start = marker ? marker : this.start; while (parent.path.length > common && parent.parent) parent = parent.parent; while (parent.path.length + 1 < path.length) { const block = new Block_1.Block(txt, path.slice(0, parent.path.length + 1), void 0, start, end); block.parent = parent; parent.children.push(block); parent = block; } const block = new LeafBlock_1.LeafBlock(txt, path, marker, start, end); block.parent = parent; parent.children.push(block); return block; } build() { const { root } = this; root.children = []; let parent = this.root; const txt = this.txt; const overlay = txt.overlay; const iterator = overlay.markerPairs0(this.start, this.end); let pair; while ((pair = iterator())) { const [p1, p2] = pair; const skipFirstVirtualBlock = !p1 && this.start.isAbsStart() && p2 && p2.viewPos() === 0; if (skipFirstVirtualBlock) continue; const type = p1 ? p1.type() : slice_1.CommonSliceType.p; const path = type instanceof Array ? type : [type]; const block = this.insertBlock(parent, path, p1, p2); if (block.parent) parent = block.parent; } } } exports.Fragment = Fragment;