From 0e66aa63821963d67b56b4ed412897270cf1e775 Mon Sep 17 00:00:00 2001 From: streamich Date: Fri, 7 Jun 2024 21:54:44 +0200 Subject: [PATCH] =?UTF-8?q?feat(json-crdt-extensions):=20=F0=9F=8E=B8=20ca?= =?UTF-8?q?n=20return=20block=20marker=20when=20iterating?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../peritext/block/Block.ts | 10 ++-- .../block/__tests__/Block.iteration.spec.ts | 46 ++++++++++++++++++- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/json-crdt-extensions/peritext/block/Block.ts b/src/json-crdt-extensions/peritext/block/Block.ts index f47c540c87..b9d72d6861 100644 --- a/src/json-crdt-extensions/peritext/block/Block.ts +++ b/src/json-crdt-extensions/peritext/block/Block.ts @@ -50,12 +50,16 @@ export class Block implements IBlock, Printable, Stateful { * Iterate through all overlay points of this block, until the next marker * (regardless if that marker is a child or not). */ - public points0(): UndefIterator> { + public points0(withMarker: boolean = false): UndefIterator> { const txt = this.txt; const overlay = txt.overlay; const iterator = overlay.points0(this.marker); let closed = false; return () => { + if (withMarker) { + withMarker = false; + return this.marker ?? overlay.START; + } if (closed) return; const point = iterator(); if (!point) return; @@ -67,8 +71,8 @@ export class Block implements IBlock, Printable, Stateful { }; } - public points(): IterableIterator> { - return new UndefEndIter(this.points0()); + public points(withMarker?: boolean): IterableIterator> { + return new UndefEndIter(this.points0(withMarker)); } // ----------------------------------------------------------------- Stateful diff --git a/src/json-crdt-extensions/peritext/block/__tests__/Block.iteration.spec.ts b/src/json-crdt-extensions/peritext/block/__tests__/Block.iteration.spec.ts index 956b0ef6c8..f04ed46122 100644 --- a/src/json-crdt-extensions/peritext/block/__tests__/Block.iteration.spec.ts +++ b/src/json-crdt-extensions/peritext/block/__tests__/Block.iteration.spec.ts @@ -1,4 +1,5 @@ import {setupHelloWorldKit} from '../../__tests__/setup'; +import {MarkerOverlayPoint} from '../../overlay/MarkerOverlayPoint'; import {OverlayPoint} from '../../overlay/OverlayPoint'; describe('points', () => { @@ -11,6 +12,16 @@ describe('points', () => { expect(iterator()).toBe(undefined); }); + test('using flag, can receive START marker in empty document', () => { + const {peritext} = setupHelloWorldKit(); + peritext.refresh(); + const blocks = peritext.blocks; + const block = blocks.root.children[0]!; + const iterator = block.points0(true); + expect(iterator()).toBeInstanceOf(OverlayPoint); + expect(iterator()).toBe(undefined); + }); + test('returns all overlay points in single block document', () => { const {peritext} = setupHelloWorldKit(); peritext.editor.cursor.setAt(3, 3); @@ -26,8 +37,22 @@ describe('points', () => { expect(point3).toBe(undefined); }); - test('returns only points within that block, in two-block document', () => { + test('returns all overlay points in single block document, including start marker', () => { const {peritext} = setupHelloWorldKit(); + peritext.editor.cursor.setAt(3, 3); + peritext.editor.saved.insStack('bold'); + peritext.refresh(); + const block = peritext.blocks.root.children[0]!; + const iterator = block.points0(true); + expect(iterator()).toBeInstanceOf(OverlayPoint); + expect(iterator()).toBeInstanceOf(OverlayPoint); + expect(iterator()).toBeInstanceOf(OverlayPoint); + expect(iterator()).toBe(undefined); + }); + + const setupTwoBlockDocument = () => { + const kit = setupHelloWorldKit(); + const {peritext} = kit; peritext.editor.cursor.setAt(1, 2); peritext.editor.saved.insStack('bold'); peritext.editor.cursor.setAt(7, 2); @@ -38,6 +63,11 @@ describe('points', () => { peritext.editor.saved.insMarker('p'); peritext.editor.delCursors(); peritext.refresh(); + return kit; + }; + + test('returns only points within that block, in two-block document', () => { + const {peritext} = setupTwoBlockDocument(); expect(peritext.blocks.root.children.length).toBe(2); const block1 = peritext.blocks.root.children[0]!; const block2 = peritext.blocks.root.children[1]!; @@ -46,4 +76,18 @@ describe('points', () => { expect(points1.length).toBe(2); expect(points2.length).toBe(4); }); + + test('can iterate including marker points, in two-block document', () => { + const {peritext} = setupTwoBlockDocument(); + expect(peritext.blocks.root.children.length).toBe(2); + const block1 = peritext.blocks.root.children[0]!; + const block2 = peritext.blocks.root.children[1]!; + const points1 = [...block1.points(true)]; + const points2 = [...block2.points(true)]; + expect(points1.length).toBe(3); + expect(points2.length).toBe(5); + expect(points1[0]).toBeInstanceOf(OverlayPoint); + expect(points1[0]).toBe(peritext.overlay.START); + expect(points2[0]).toBeInstanceOf(MarkerOverlayPoint); + }); });