Skip to content

Commit

Permalink
Merge pull request #622 from streamich/overlay-7
Browse files Browse the repository at this point in the history
Improve iteration methods through Peritext `Overlay`
  • Loading branch information
streamich authored May 8, 2024
2 parents 670ff71 + 91e6a92 commit 6676486
Show file tree
Hide file tree
Showing 13 changed files with 924 additions and 211 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ const setup = () => {
test('can insert markers', () => {
const {peritext} = setup();
const {editor} = peritext;
expect([...peritext.overlay].length).toBe(0);
expect([...peritext.overlay.points()].length).toBe(0);
editor.cursor.setAt(0);
peritext.refresh();
expect([...peritext.overlay].length).toBe(1);
editor.insMarker(['p'], '<p>');
expect([...peritext.overlay.points()].length).toBe(1);
editor.saved.insMarker(['p'], '<p>');
peritext.refresh();
expect(size(peritext.overlay.root)).toBe(2);
editor.cursor.setAt(9);
editor.insMarker(['p'], '<p>');
editor.saved.insMarker(['p'], '<p>');
peritext.refresh();
expect(size(peritext.overlay.root)).toBe(3);
});
Expand All @@ -37,15 +37,15 @@ test('can insert slices', () => {
const {editor} = peritext;
expect(size(peritext.overlay.root)).toBe(0);
editor.cursor.setAt(2, 2);
editor.insStackSlice('bold');
editor.saved.insStack('bold');
peritext.refresh();
expect(size(peritext.overlay.root)).toBe(2);
editor.cursor.setAt(6, 5);
editor.insStackSlice('italic');
editor.extra.insStack('italic');
peritext.refresh();
expect(size(peritext.overlay.root)).toBe(4);
editor.cursor.setAt(0, 5);
editor.insStackSlice('underline');
editor.local.insStack('underline');
peritext.refresh();
expect(size(peritext.overlay.root)).toBe(6);
});
116 changes: 82 additions & 34 deletions src/json-crdt-extensions/peritext/__tests__/setup.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,22 @@
import {s} from '../../../json-crdt-patch';
import {Model} from '../../../json-crdt/model';
import {SchemaToJsonNode} from '../../../json-crdt/schema/types';
import {ModelWithExt, ext} from '../../ModelWithExt';

/**
* Creates a Peritext instance with text "0123456789", with single-char and
* block-wise chunks, as well as with plenty of tombstones.
*/
export const setupNumbersWithTombstones = () => {
const schema = s.obj({
text: ext.peritext.new('1234'),
export type Schema = ReturnType<typeof schema>;
export type Kit = ReturnType<typeof setupKit>;

const schema = (text: string) =>
s.obj({
text: ext.peritext.new(text),
});
const model = ModelWithExt.create(schema);
const str = model.s.text.toExt().text();
str.ins(1, '234');
str.ins(2, '345');
str.ins(3, '456');
str.ins(4, '567');
str.ins(5, '678');
str.ins(6, '789');
str.del(7, 1);
str.del(8, 1);
str.ins(0, '0');
str.del(1, 4);
str.del(2, 1);
str.ins(1, '1');
str.del(0, 1);
str.ins(0, '0');
str.ins(2, '234');
str.del(4, 7);
str.del(4, 2);
str.del(7, 3);
str.ins(6, '6789');
str.del(7, 2);
str.ins(7, '78');
str.del(10, 2);
str.del(2, 3);
str.ins(2, '234');
if (str.view() !== '0123456789') throw new Error('Invalid text');

export const setupKit = (
initialText: string = '',
edits: (model: Model<SchemaToJsonNode<Schema>>) => void = () => {},
) => {
const model = ModelWithExt.create(schema(initialText));
edits(model);
const api = model.api;
const peritextApi = model.s.text.toExt();
const peritext = peritextApi.txt;
Expand All @@ -49,3 +30,70 @@ export const setupNumbersWithTombstones = () => {
editor,
};
};

export const setupHelloWorldKit = (): Kit => {
return setupKit('', (model) => {
const str = model.s.text.toExt().text();
str.ins(0, 'hello world');
if (str.view() !== 'hello world') throw new Error('Invalid text');
});
};

export const setupHelloWorldWithFewEditsKit = (): Kit => {
return setupKit('', (model) => {
const str = model.s.text.toExt().text();
str.ins(0, 'wworld');
str.ins(0, 'helo ');
str.ins(2, 'l');
str.del(7, 1);
if (str.view() !== 'hello world') throw new Error('Invalid text');
});
};

/**
* Creates a Peritext instance with text "0123456789", no edits.
*/
export const setupNumbersKit = (): Kit => {
return setupKit('', (model) => {
const str = model.s.text.toExt().text();
str.ins(0, '0123456789');
if (str.view() !== '0123456789') throw new Error('Invalid text');
});
};

/**
* Creates a Peritext instance with text "0123456789", with single-char and
* block-wise chunks, as well as with plenty of tombstones.
*/
export const setupNumbersWithTombstonesKit = (): Kit => {
return setupKit('1234', (model) => {
const str = model.s.text.toExt().text();
str.ins(0, '234');
str.ins(1, '234');
str.ins(2, '345');
str.ins(3, '456');
str.ins(4, '567');
str.ins(5, '678');
str.ins(6, '789');
str.del(7, 1);
str.del(8, 1);
str.ins(0, '0');
str.del(1, 4);
str.del(2, 1);
str.ins(1, '1');
str.del(0, 1);
str.ins(0, '0');
str.ins(2, '234');
str.del(4, 7);
str.del(4, 2);
str.del(7, 3);
str.ins(6, '6789');
str.del(7, 2);
str.ins(7, '78');
str.del(10, 2);
str.del(2, 3);
str.ins(2, '234');
str.del(10, 3);
if (str.view() !== '0123456789') throw new Error('Invalid text');
});
};
4 changes: 4 additions & 0 deletions src/json-crdt-extensions/peritext/editor/Editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@ import type {MarkerSlice} from '../slice/MarkerSlice';

export class Editor<T = string> {
public readonly saved: EditorSlices<T>;
public readonly extra: EditorSlices<T>;
public readonly local: EditorSlices<T>;

constructor(public readonly txt: Peritext<T>) {
this.saved = new EditorSlices(txt, txt.savedSlices);
this.extra = new EditorSlices(txt, txt.extraSlices);
this.local = new EditorSlices(txt, txt.localSlices);
}

public firstCursor(): Cursor<T> | undefined {
Expand Down
Loading

0 comments on commit 6676486

Please sign in to comment.