Skip to content

Commit

Permalink
feat(json-crdt-extensions): 🎸 improve Inline attribute construction
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Jun 8, 2024
1 parent bc8eb9b commit 3ef2fe6
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 30 deletions.
66 changes: 38 additions & 28 deletions src/json-crdt-extensions/peritext/block/Inline.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import {printTree} from 'tree-dump/lib/printTree';
import {OverlayPoint} from '../overlay/OverlayPoint';
import {stringify} from '../../../json-text/stringify';
import {SliceBehavior} from '../slice/constants';
import {SliceBehavior, SliceTypes} from '../slice/constants';
import {Range} from '../rga/Range';
import {ChunkSlice} from '../util/ChunkSlice';
import {updateNum} from '../../../json-hash';
import type {AbstractRga} from '../../../json-crdt/nodes/rga';
import type {Printable} from 'tree-dump/lib/types';
import type {PathStep} from '../../../json-pointer';
import type {Slice} from '../slice/types';
import type {Peritext} from '../Peritext';

export type InlineAttributes = Record<string | number, unknown>;
Expand Down Expand Up @@ -57,7 +56,7 @@ export class Inline extends Range implements Printable {
}

/**
* @returns The position of the inline withing the text.
* @returns The position of the inline within the text.
*/
public pos(): number {
const chunkSlice = this.texts[0];
Expand All @@ -74,34 +73,45 @@ export class Inline extends Range implements Printable {
public attr(): InlineAttributes {
const attr: InlineAttributes = {};
const point = this.start as OverlayPoint;
const slices: Slice[] = this.texts.length ? point.layers : point.markers;
const length = slices.length;
for (let i = 0; i < length; i++) {
const slice = slices[i];
const type = slice.type as PathStep;
switch (slice.behavior) {
case SliceBehavior.Cursor:
case SliceBehavior.Stack: {
let dataList: unknown[] = (attr[type] as unknown[]) || (attr[type] = []);
if (!Array.isArray(dataList)) dataList = attr[type] = [dataList];
let data = slice.data();
if (data === undefined) data = 1;
dataList.push(data);
break;
}
case SliceBehavior.Overwrite: {
let data = slice.data();
if (data === undefined) data = 1;
attr[type] = data;
break;
}
case SliceBehavior.Erase: {
delete attr[type];
break;
const slices1 = point.layers;
const slices2 = point.markers;
const length1 = slices1.length;
const length2 = slices2.length;
const length3 = length1 + length2;
for (let i = 0; i < length3; i++) {
const slice = i >= length1 ? slices2[i - length1] : slices1[i];
if (slice instanceof Range) {
const type = slice.type as PathStep;
switch (slice.behavior) {
case SliceBehavior.Cursor: {
const dataList: unknown[] = (attr[SliceTypes.Cursor] as unknown[]) || (attr[SliceTypes.Cursor] = []);
const data: unknown[] = [type];
const cursorData = slice.data();
if (cursorData !== void 0) data.push(cursorData);
dataList.push(data);
break;
}
case SliceBehavior.Stack: {
let dataList: unknown[] = (attr[type] as unknown[]) || (attr[type] = []);
if (!Array.isArray(dataList)) dataList = attr[type] = [dataList];
let data = slice.data();
if (data === undefined) data = 1;
dataList.push(data);
break;
}
case SliceBehavior.Overwrite: {
let data = slice.data();
if (data === undefined) data = 1;
attr[type] = data;
break;
}
case SliceBehavior.Erase: {
delete attr[type];
break;
}
}
}
}
// TODO: Iterate over the markers...
return attr;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {Kit, setupKit, setupNumbersKit, setupNumbersWithTombstonesKit} from '../../__tests__/setup';
import {CursorAnchor, SliceTypes} from '../../slice/constants';
import {Inline} from '../Inline';

const runStrTests = (setup: () => Kit) => {
Expand Down Expand Up @@ -102,6 +103,35 @@ const runStrTests = (setup: () => Kit) => {
expect(attr['bold,very']).toEqual([1]);
expect(attr['bold,normal']).toEqual([2]);
});

test('returns collapsed slice (cursor) at marker position', () => {
const {peritext} = setup();
peritext.editor.cursor.setAt(3);
const [paragraph] = peritext.editor.saved.insMarker('p');
peritext.editor.cursor.set(paragraph.start);
peritext.refresh();
const block = peritext.blocks.root.children[1]!;
const inline = [...block.texts()][0];
const attr = inline.attr();
expect(attr).toEqual({
[SliceTypes.Cursor]: [[CursorAnchor.Start]],
});
});

test('returns collapsed slice (cursor) at markup slice start', () => {
const {peritext} = setup();
peritext.editor.cursor.setAt(2, 2);
const [slice] = peritext.editor.saved.insStack('bold', 123);
peritext.editor.cursor.set(slice.start);
peritext.refresh();
const block = peritext.blocks.root.children[0]!;
const inline = [...block.texts()][1];
const attr = inline.attr();
expect(attr).toEqual({
[SliceTypes.Cursor]: [[CursorAnchor.Start]],
bold: [123],
});
});
});
};

Expand Down
8 changes: 6 additions & 2 deletions src/json-crdt-extensions/peritext/slice/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ export const enum CursorAnchor {
End = 1,
}

export const enum Tags {
Cursor = 0,
/**
* Built-in slice types.
*/
export const enum SliceTypes {
Cursor = -1,
Paragraph = 0,
}

export const enum SliceHeaderMask {
Expand Down

0 comments on commit 3ef2fe6

Please sign in to comment.