json-joy
Version:
Collection of libraries for building collaborative editing apps.
87 lines • 3.51 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FromSlate = void 0;
const constants_1 = require("../peritext/rga/constants");
const constants_2 = require("../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);
* ```
*/
class FromSlate {
constructor() {
this.text = '';
this.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 ? constants_2.SliceStacking.One : constants_2.SliceStacking.Many;
const header = (stacking << constants_2.SliceHeaderShift.Stacking) +
(constants_1.Anchor.Before << constants_2.SliceHeaderShift.X1Anchor) +
(constants_1.Anchor.After << constants_2.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 = (constants_2.SliceStacking.Marker << constants_2.SliceHeaderShift.Stacking) +
(constants_1.Anchor.Before << constants_2.SliceHeaderShift.X1Anchor) +
(constants_1.Anchor.Before << constants_2.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];
}
}
exports.FromSlate = FromSlate;
FromSlate.convert = (doc) => new FromSlate().convert(doc);
//# sourceMappingURL=FromSlate.js.map