Skip to content

Commit 6676486

Browse files
authored
Merge pull request #622 from streamich/overlay-7
Improve iteration methods through Peritext `Overlay`
2 parents 670ff71 + 91e6a92 commit 6676486

13 files changed

+924
-211
lines changed

src/json-crdt-extensions/peritext/__tests__/Peritext.overlay.spec.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@ const setup = () => {
1919
test('can insert markers', () => {
2020
const {peritext} = setup();
2121
const {editor} = peritext;
22-
expect([...peritext.overlay].length).toBe(0);
22+
expect([...peritext.overlay.points()].length).toBe(0);
2323
editor.cursor.setAt(0);
2424
peritext.refresh();
25-
expect([...peritext.overlay].length).toBe(1);
26-
editor.insMarker(['p'], '<p>');
25+
expect([...peritext.overlay.points()].length).toBe(1);
26+
editor.saved.insMarker(['p'], '<p>');
2727
peritext.refresh();
2828
expect(size(peritext.overlay.root)).toBe(2);
2929
editor.cursor.setAt(9);
30-
editor.insMarker(['p'], '<p>');
30+
editor.saved.insMarker(['p'], '<p>');
3131
peritext.refresh();
3232
expect(size(peritext.overlay.root)).toBe(3);
3333
});
@@ -37,15 +37,15 @@ test('can insert slices', () => {
3737
const {editor} = peritext;
3838
expect(size(peritext.overlay.root)).toBe(0);
3939
editor.cursor.setAt(2, 2);
40-
editor.insStackSlice('bold');
40+
editor.saved.insStack('bold');
4141
peritext.refresh();
4242
expect(size(peritext.overlay.root)).toBe(2);
4343
editor.cursor.setAt(6, 5);
44-
editor.insStackSlice('italic');
44+
editor.extra.insStack('italic');
4545
peritext.refresh();
4646
expect(size(peritext.overlay.root)).toBe(4);
4747
editor.cursor.setAt(0, 5);
48-
editor.insStackSlice('underline');
48+
editor.local.insStack('underline');
4949
peritext.refresh();
5050
expect(size(peritext.overlay.root)).toBe(6);
5151
});
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,22 @@
11
import {s} from '../../../json-crdt-patch';
2+
import {Model} from '../../../json-crdt/model';
3+
import {SchemaToJsonNode} from '../../../json-crdt/schema/types';
24
import {ModelWithExt, ext} from '../../ModelWithExt';
35

4-
/**
5-
* Creates a Peritext instance with text "0123456789", with single-char and
6-
* block-wise chunks, as well as with plenty of tombstones.
7-
*/
8-
export const setupNumbersWithTombstones = () => {
9-
const schema = s.obj({
10-
text: ext.peritext.new('1234'),
6+
export type Schema = ReturnType<typeof schema>;
7+
export type Kit = ReturnType<typeof setupKit>;
8+
9+
const schema = (text: string) =>
10+
s.obj({
11+
text: ext.peritext.new(text),
1112
});
12-
const model = ModelWithExt.create(schema);
13-
const str = model.s.text.toExt().text();
14-
str.ins(1, '234');
15-
str.ins(2, '345');
16-
str.ins(3, '456');
17-
str.ins(4, '567');
18-
str.ins(5, '678');
19-
str.ins(6, '789');
20-
str.del(7, 1);
21-
str.del(8, 1);
22-
str.ins(0, '0');
23-
str.del(1, 4);
24-
str.del(2, 1);
25-
str.ins(1, '1');
26-
str.del(0, 1);
27-
str.ins(0, '0');
28-
str.ins(2, '234');
29-
str.del(4, 7);
30-
str.del(4, 2);
31-
str.del(7, 3);
32-
str.ins(6, '6789');
33-
str.del(7, 2);
34-
str.ins(7, '78');
35-
str.del(10, 2);
36-
str.del(2, 3);
37-
str.ins(2, '234');
38-
if (str.view() !== '0123456789') throw new Error('Invalid text');
13+
14+
export const setupKit = (
15+
initialText: string = '',
16+
edits: (model: Model<SchemaToJsonNode<Schema>>) => void = () => {},
17+
) => {
18+
const model = ModelWithExt.create(schema(initialText));
19+
edits(model);
3920
const api = model.api;
4021
const peritextApi = model.s.text.toExt();
4122
const peritext = peritextApi.txt;
@@ -49,3 +30,70 @@ export const setupNumbersWithTombstones = () => {
4930
editor,
5031
};
5132
};
33+
34+
export const setupHelloWorldKit = (): Kit => {
35+
return setupKit('', (model) => {
36+
const str = model.s.text.toExt().text();
37+
str.ins(0, 'hello world');
38+
if (str.view() !== 'hello world') throw new Error('Invalid text');
39+
});
40+
};
41+
42+
export const setupHelloWorldWithFewEditsKit = (): Kit => {
43+
return setupKit('', (model) => {
44+
const str = model.s.text.toExt().text();
45+
str.ins(0, 'wworld');
46+
str.ins(0, 'helo ');
47+
str.ins(2, 'l');
48+
str.del(7, 1);
49+
if (str.view() !== 'hello world') throw new Error('Invalid text');
50+
});
51+
};
52+
53+
/**
54+
* Creates a Peritext instance with text "0123456789", no edits.
55+
*/
56+
export const setupNumbersKit = (): Kit => {
57+
return setupKit('', (model) => {
58+
const str = model.s.text.toExt().text();
59+
str.ins(0, '0123456789');
60+
if (str.view() !== '0123456789') throw new Error('Invalid text');
61+
});
62+
};
63+
64+
/**
65+
* Creates a Peritext instance with text "0123456789", with single-char and
66+
* block-wise chunks, as well as with plenty of tombstones.
67+
*/
68+
export const setupNumbersWithTombstonesKit = (): Kit => {
69+
return setupKit('1234', (model) => {
70+
const str = model.s.text.toExt().text();
71+
str.ins(0, '234');
72+
str.ins(1, '234');
73+
str.ins(2, '345');
74+
str.ins(3, '456');
75+
str.ins(4, '567');
76+
str.ins(5, '678');
77+
str.ins(6, '789');
78+
str.del(7, 1);
79+
str.del(8, 1);
80+
str.ins(0, '0');
81+
str.del(1, 4);
82+
str.del(2, 1);
83+
str.ins(1, '1');
84+
str.del(0, 1);
85+
str.ins(0, '0');
86+
str.ins(2, '234');
87+
str.del(4, 7);
88+
str.del(4, 2);
89+
str.del(7, 3);
90+
str.ins(6, '6789');
91+
str.del(7, 2);
92+
str.ins(7, '78');
93+
str.del(10, 2);
94+
str.del(2, 3);
95+
str.ins(2, '234');
96+
str.del(10, 3);
97+
if (str.view() !== '0123456789') throw new Error('Invalid text');
98+
});
99+
};

src/json-crdt-extensions/peritext/editor/Editor.ts

+4
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ import type {MarkerSlice} from '../slice/MarkerSlice';
1010

1111
export class Editor<T = string> {
1212
public readonly saved: EditorSlices<T>;
13+
public readonly extra: EditorSlices<T>;
14+
public readonly local: EditorSlices<T>;
1315

1416
constructor(public readonly txt: Peritext<T>) {
1517
this.saved = new EditorSlices(txt, txt.savedSlices);
18+
this.extra = new EditorSlices(txt, txt.extraSlices);
19+
this.local = new EditorSlices(txt, txt.localSlices);
1620
}
1721

1822
public firstCursor(): Cursor<T> | undefined {

0 commit comments

Comments
 (0)