json-joy
Version:
Collection of libraries for building collaborative editing apps.
81 lines • 3.19 kB
JavaScript
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