UNPKG

json-joy

Version:

Collection of libraries for building collaborative editing apps.

81 lines 3.19 kB
import { Anchor } from '../peritext/rga/constants'; import { SliceHeaderShift, SliceStacking } from '../peritext/slice/constants'; const isInline = (node) => typeof node === 'object' && !!node && typeof node.text === 'string'; /** * Converts Slate.js state to a {@link ViewRange} flat string with * annotation ranges, which is the natural view format for a Peritext model. * * Usage: * * ```typescript * FromSlate.convert(node); * ``` */ export class FromSlate { static convert = (doc) => new FromSlate().convert(doc); text = ''; slices = []; conv(node, path, nodeDiscriminator) { if (!node || typeof node !== 'object') return; const start = this.text.length; if ('text' in node) { const { text, ...tagMap } = node; this.text += text; const tags = Object.keys(tagMap); if (tags.length) { const end = start + text.length; for (const tag of tags) { const data = tagMap[tag]; const dataEmpty = !data || data === true; const stacking = dataEmpty ? SliceStacking.One : SliceStacking.Many; const header = (stacking << SliceHeaderShift.Stacking) + (Anchor.Before << SliceHeaderShift.X1Anchor) + (Anchor.After << SliceHeaderShift.X2Anchor); const slice = [header, start, end, tag]; if (!dataEmpty) slice.push(data); this.slices.push(slice); } } } else { const element = node; const { type, children, ...data } = element; const step = nodeDiscriminator || data ? [type, nodeDiscriminator, data] : type; const length = children?.length ?? 0; const hasNoChildren = length === 0; const isFirstChildInline = isInline(children?.[0]); const doEmitSplitMarker = hasNoChildren || isFirstChildInline; if (doEmitSplitMarker) { this.text += '\n'; const header = (SliceStacking.Marker << SliceHeaderShift.Stacking) + (Anchor.Before << SliceHeaderShift.X1Anchor) + (Anchor.Before << SliceHeaderShift.X2Anchor); const slice = [header, start, start, [...path, step]]; this.slices.push(slice); } if (length > 0) this.cont([...path, step], children); } } cont(path, content) { let prevTag = ''; let discriminator = 0; const length = content.length; for (let i = 0; i < length; i++) { const child = content[i]; const tag = child.type; discriminator = tag === prevTag ? discriminator + 1 : 0; this.conv(child, path, discriminator); prevTag = tag; } } convert(node) { let length = 0; if (node && (length = node.length) > 0) this.cont([], node); return [this.text, 0, this.slices]; } } //# sourceMappingURL=FromSlate.js.map