From c6c5b621e9f934903cc5b6393c73708c2afac752 Mon Sep 17 00:00:00 2001 From: streamich Date: Sat, 11 May 2024 13:44:03 +0200 Subject: [PATCH] =?UTF-8?q?feat(json-crdt-extensions):=20=F0=9F=8E=B8=20im?= =?UTF-8?q?prove=20Inline.attr()=20implementation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../peritext/block/Inline.ts | 6 ++ .../block/__tests__/Inline.str.spec.ts | 61 +++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/src/json-crdt-extensions/peritext/block/Inline.ts b/src/json-crdt-extensions/peritext/block/Inline.ts index db9c4fd4e5..3296e99238 100644 --- a/src/json-crdt-extensions/peritext/block/Inline.ts +++ b/src/json-crdt-extensions/peritext/block/Inline.ts @@ -77,6 +77,10 @@ export class Inline extends Range implements Printable { return pos + chunkSlice.off; } + /** + * @returns Returns the attributes of the inline, which are the slice + * annotations and formatting applied to the inline. + */ public attr(): InlineAttributes { const attr: InlineAttributes = {}; const point = this.start as OverlayPoint; @@ -86,6 +90,7 @@ export class Inline extends Range implements Printable { 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]; @@ -106,6 +111,7 @@ export class Inline extends Range implements Printable { } } } + // TODO: Iterate over the markers... return attr; } diff --git a/src/json-crdt-extensions/peritext/block/__tests__/Inline.str.spec.ts b/src/json-crdt-extensions/peritext/block/__tests__/Inline.str.spec.ts index 79e26dd992..62ee4f634f 100644 --- a/src/json-crdt-extensions/peritext/block/__tests__/Inline.str.spec.ts +++ b/src/json-crdt-extensions/peritext/block/__tests__/Inline.str.spec.ts @@ -42,6 +42,67 @@ const runStrTests = (setup: () => Kit) => { } }); }); + + describe('.attr()', () => { + test('returns all STACK annotations of a slice', () => { + const {peritext} = setup(); + const overlay = peritext.overlay; + peritext.editor.cursor.setAt(3, 3); + peritext.editor.saved.insStack('bold', 1); + peritext.editor.saved.insStack('bold', 2); + peritext.editor.saved.insStack('em', 1); + overlay.refresh(); + const [start, end] = [...overlay.points()]; + const inline = Inline.create(peritext, start, end); + const attr = inline.attr(); + expect(attr.bold).toEqual([1, 2]); + expect(attr.em).toEqual([1]); + }); + + test('returns latest OVERWRITE annotation', () => { + const {peritext} = setup(); + const overlay = peritext.overlay; + peritext.editor.cursor.setAt(3, 3); + peritext.editor.saved.insOverwrite('bold', 1); + peritext.editor.saved.insOverwrite('bold', 2); + peritext.editor.saved.insOverwrite('em', 1); + overlay.refresh(); + const [start, end] = [...overlay.points()]; + const inline = Inline.create(peritext, start, end); + const attr = inline.attr(); + expect(attr.bold).toBe(2); + expect(attr.em).toBe(1); + }); + + test('hides annotation hidden with another ERASE annotation', () => { + const {peritext} = setup(); + const overlay = peritext.overlay; + peritext.editor.cursor.setAt(3, 3); + peritext.editor.saved.insOverwrite('bold'); + peritext.editor.saved.insErase('bold'); + peritext.editor.saved.insOverwrite('em'); + overlay.refresh(); + const [start, end] = [...overlay.points()]; + const inline = Inline.create(peritext, start, end); + const attr = inline.attr(); + expect(attr.bold).toBe(undefined); + expect(attr.em).toBe(1); + }); + + test('concatenates with "," steps of nested Path type annotations', () => { + const {peritext} = setup(); + const overlay = peritext.overlay; + peritext.editor.cursor.setAt(3, 3); + peritext.editor.saved.insStack(['bold', 'very'], 1); + peritext.editor.saved.insStack(['bold', 'normal'], 2); + overlay.refresh(); + const [start, end] = [...overlay.points()]; + const inline = Inline.create(peritext, start, end); + const attr = inline.attr(); + expect(attr['bold,very']).toEqual([1]); + expect(attr['bold,normal']).toEqual([2]); + }); + }); }; describe('Inline', () => {