Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | 12x 12x 12x 1009x 1009x 1009x 24467x 24467x 24467x 24467x 24467x 11452x 13015x 13015x 13015x 13015x 13015x 13015x 13015x 13015x 8562x 8562x 8562x 8562x 13015x 24467x 24467x 24467x 5523x 5523x 10252x 10252x 10252x 10252x 10252x 3524x 3524x 10252x 10252x 10252x 10252x 10252x 11700x 11700x 11700x 11700x 24467x 24467x 24467x 24467x 24467x 1009x 1009x 1009x 1009x 1009x | import {Anchor} from 'json-joy/lib/json-crdt-extensions/peritext/rga/constants';
import {SliceHeaderShift, SliceStacking} from 'json-joy/lib/json-crdt-extensions/peritext/slice/constants';
import type {ViewRange, ViewSlice} from 'json-joy/lib/json-crdt-extensions/peritext/editor/types';
import type {SliceTypeStep, SliceTypeSteps} from 'json-joy/lib/json-crdt-extensions/peritext';
import type {PmFragment, PmNode, PmTextNode} from '../types';
/**
* Converts ProseMirror raw nodes to a {@link ViewRange} flat string with
* annotation ranges, which is the natural view format for a Peritext model.
*
* Usage:
*
* ```typescript
* FromPm.convert(node);
* ```
*/
export class FromPm {
static readonly convert = (node: PmNode): ViewRange => new FromPm().convert(node);
private text = '';
private slices: ViewSlice[] = [];
private conv(node: PmNode, path: SliceTypeSteps, nodeDiscriminator: number): void {
const text = this.text;
const start = text.length;
let inlineText: string = '';
const type = node.type.name;
if (type === 'text' && (inlineText = (node as PmTextNode).text || '')) {
this.text += inlineText;
} else {
const content = node.content?.content;
const data = node.attrs;
const step: SliceTypeStep = nodeDiscriminator || data ? [type, nodeDiscriminator, data] : type;
const length = content?.length ?? 0;
const hasNoChildren = length === 0;
const isFirstChildInline = content?.[0]?.type.name === 'text';
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: ViewSlice = [header, start, start, [...path, step]];
this.slices.push(slice);
}
if (length > 0) this.cont([...path, step], content!);
}
const marks = node.marks;
let length = 0;
if (marks && (length = marks.length) > 0) {
const end = start + inlineText.length;
for (let i = 0; i < length; i++) {
const mark = marks[i];
const type = mark.type.name;
const data = mark.attrs;
let dataEmpty = true;
for (const _ in data) {
dataEmpty = false;
break;
}
const stacking: SliceStacking = dataEmpty ? SliceStacking.One : SliceStacking.Many;
const header =
(stacking << SliceHeaderShift.Stacking) +
(Anchor.Before << SliceHeaderShift.X1Anchor) +
(Anchor.After << SliceHeaderShift.X2Anchor);
const slice: ViewSlice = [header, start, end, type];
if (!dataEmpty) slice.push(data);
this.slices.push(slice);
}
}
}
private cont(path: SliceTypeSteps, content: PmFragment['content']): void {
let prevTag: string = '';
let discriminator: number = 0;
const length = content.length;
for (let i = 0; i < length; i++) {
const child = content[i];
const tag = child.type.name;
discriminator = tag === prevTag ? discriminator + 1 : 0;
this.conv(child, path, discriminator);
prevTag = tag;
}
}
public convert(node: PmNode): ViewRange {
const content = node.content?.content;
let length = 0;
Eif (content && (length = content.length) > 0) this.cont([], content);
const view: ViewRange = [this.text, 0, this.slices];
return view;
}
}
|