Skip to content

Commit 03ccf42

Browse files
committed
feat(json-crdt-extensions): 🎸 make Range generic and remove Peritext from its scope
1 parent 01cf965 commit 03ccf42

File tree

4 files changed

+42
-47
lines changed

4 files changed

+42
-47
lines changed

‎src/json-crdt-extensions/peritext/Peritext.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export class Peritext implements Printable {
9292
* @returns A range with points in correct order.
9393
*/
9494
public rangeFromPoints(p1: Point, p2: Point): Range {
95-
return Range.from(this, p1, p2);
95+
return Range.from(this.str, p1, p2);
9696
}
9797

9898
/**
@@ -103,7 +103,7 @@ export class Peritext implements Printable {
103103
* @returns A range with the given start and end points.
104104
*/
105105
public range(start: Point, end: Point): Range {
106-
return new Range(this, start, end);
106+
return new Range(this.str, start, end);
107107
}
108108

109109
/**
@@ -115,7 +115,7 @@ export class Peritext implements Printable {
115115
* @returns A range from the given position with the given length.
116116
*/
117117
public rangeAt(start: number, length: number = 0): Range {
118-
return Range.at(this, start, length);
118+
return Range.at(this.str, start, length);
119119
}
120120

121121
// --------------------------------------------------------------- Insertions

‎src/json-crdt-extensions/peritext/slice/Cursor.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type {ITimestampStruct} from '../../../json-crdt-patch/clock';
66
import type {Peritext} from '../Peritext';
77
import type {Slice} from './types';
88

9-
export class Cursor extends Range implements Slice {
9+
export class Cursor extends Range<string> implements Slice {
1010
public readonly behavior = SliceBehavior.Overwrite;
1111
public readonly type = Tags.Cursor;
1212

@@ -26,7 +26,7 @@ export class Cursor extends Range implements Slice {
2626
public start: Point,
2727
public end: Point,
2828
) {
29-
super(txt, start, end);
29+
super(txt.str, start, end);
3030
}
3131

3232
public anchor(): Point {

‎src/json-crdt-extensions/peritext/slice/PersistedSlice.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export class PersistedSlice extends Range implements Slice, Printable, Stateful
2525
public end: Point,
2626
public type: SliceType,
2727
) {
28-
super(txt, start, end);
28+
super(txt.str, start, end);
2929
this.id = this.chunk.id;
3030
}
3131

‎src/json-crdt-extensions/peritext/slice/Range.ts‎

Lines changed: 36 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,26 @@
11
import {Point} from '../point/Point';
22
import {Anchor} from '../constants';
3-
import {StringChunk} from '../util/types';
43
import {type ITimestampStruct, tick} from '../../../json-crdt-patch/clock';
5-
import type {Peritext} from '../Peritext';
64
import type {Printable} from '../../../util/print/types';
5+
import type {AbstractRga, Chunk} from '../../../json-crdt/nodes/rga';
76

87
/**
98
* A range is a pair of points that represent a selection in the text. A range
109
* can be collapsed to a single point, then it is called a *marker*
1110
* (if it is stored in the text), or *caret* (if it is a cursor position).
1211
*/
13-
export class Range implements Printable {
12+
export class Range<T = string> implements Printable {
1413
/**
1514
* Creates a range from two points. The points are ordered so that the
1615
* start point is before or equal to the end point.
1716
*
18-
* @param txt Peritext context.
17+
* @param rga Peritext context.
1918
* @param p1 Some point.
2019
* @param p2 Another point.
2120
* @returns Range with points in correct order.
2221
*/
23-
public static from(txt: Peritext, p1: Point, p2: Point) {
24-
return p1.compareSpatial(p2) > 0 ? new Range(txt, p2, p1) : new Range(txt, p1, p2);
22+
public static from<T = string>(rga: AbstractRga<T>, p1: Point<T>, p2: Point<T>): Range<T> {
23+
return p1.compareSpatial(p2) > 0 ? new Range(rga, p2, p1) : new Range(rga, p1, p2);
2524
}
2625

2726
/**
@@ -38,20 +37,19 @@ export class Range implements Printable {
3837
* The `size` argument can be negative, in which case the range is selected
3938
* backwards.
4039
*
41-
* @param txt Peritext context.
40+
* @param rga Peritext context.
4241
* @param start Position in the text between characters.
4342
* @param size Length of the range. Can be negative, in which case the range
4443
* is selected backwards.
4544
* @returns A range from the given position with the given length.
4645
*/
47-
public static at(txt: Peritext, start: number, size: number = 0): Range {
48-
const str = txt.str;
49-
const length = str.length();
46+
public static at<T = string>(rga: AbstractRga<T>, start: number, size: number = 0): Range<T> {
47+
const length = rga.length();
5048
if (!size) {
5149
if (start > length) start = length;
52-
const startId = !start ? str.id : str.find(start - 1) || str.id;
53-
const point = txt.point(startId, Anchor.After);
54-
return new Range(txt, point, point.clone());
50+
const startId = !start ? rga.id : rga.find(start - 1) || rga.id;
51+
const point = new Point(rga, startId, Anchor.After);
52+
return new Range<T>(rga, point, point.clone());
5553
}
5654
if (size < 0) {
5755
size = -size;
@@ -60,38 +58,38 @@ export class Range implements Printable {
6058
if (start < 0) {
6159
size += start;
6260
start = 0;
63-
if (size < 0) return Range.at(txt, start, 0);
61+
if (size < 0) return Range.at(rga, start, 0);
6462
}
6563
if (start >= length) {
6664
start = length;
6765
size = 0;
6866
}
6967
if (start + size > length) size = length - start;
70-
const startId = str.find(start) || str.id;
71-
const endId = str.find(start + size - 1) || startId;
72-
const startEndpoint = txt.point(startId, Anchor.Before);
73-
const endEndpoint = txt.point(endId, Anchor.After);
74-
return new Range(txt, startEndpoint, endEndpoint);
68+
const startId = rga.find(start) || rga.id;
69+
const endId = rga.find(start + size - 1) || startId;
70+
const startEndpoint = new Point(rga, startId, Anchor.Before);
71+
const endEndpoint = new Point(rga, endId, Anchor.After);
72+
return new Range(rga, startEndpoint, endEndpoint);
7573
}
7674

7775
/**
78-
* @param txt Peritext context.
76+
* @param rga Peritext context.
7977
* @param start Start point of the range, must be before or equal to end.
8078
* @param end End point of the range, must be after or equal to start.
8179
*/
8280
constructor(
83-
protected readonly txt: Peritext,
84-
public start: Point,
85-
public end: Point,
81+
protected readonly rga: AbstractRga<T>,
82+
public start: Point<T>,
83+
public end: Point<T>,
8684
) {}
8785

8886
/**
8987
* Clones the range.
9088
*
9189
* @returns A new range with the same start and end points.
9290
*/
93-
public clone(): Range {
94-
return new Range(this.txt, this.start.clone(), this.end.clone());
91+
public clone(): Range<T> {
92+
return new Range(this.rga, this.start.clone(), this.end.clone());
9593
}
9694

9795
/**
@@ -131,33 +129,32 @@ export class Range implements Printable {
131129
this.start = this.end.clone();
132130
}
133131

134-
public set(start: Point, end: Point = start): void {
132+
public set(start: Point<T>, end: Point<T> = start): void {
135133
this.start = start;
136134
this.end = end === start ? end.clone() : end;
137135
}
138136

139-
public setRange(range: Range): void {
137+
public setRange(range: Range<T>): void {
140138
this.set(range.start, range.end);
141139
}
142140

143141
public setAt(start: number, length: number = 0): void {
144-
const range = Range.at(this.txt, start, length);
142+
const range = Range.at<T>(this.rga, start, length);
145143
this.setRange(range);
146144
}
147145

148146
/** @todo Can this be moved to Cursor? */
149147
public setCaret(after: ITimestampStruct, shift: number = 0): void {
150148
const id = shift ? tick(after, shift) : after;
151-
const txt = this.txt;
152-
const caretAfter = new Point(txt.str, id, Anchor.After);
149+
const caretAfter = new Point(this.rga, id, Anchor.After);
153150
this.set(caretAfter);
154151
}
155152

156-
public contains(range: Range): boolean {
153+
public contains(range: Range<T>): boolean {
157154
return this.start.compareSpatial(range.start) <= 0 && this.end.compareSpatial(range.end) >= 0;
158155
}
159156

160-
public containsPoint(range: Point): boolean {
157+
public containsPoint(range: Point<T>): boolean {
161158
return this.start.compareSpatial(range) <= 0 && this.end.compareSpatial(range) >= 0;
162159
}
163160

@@ -171,8 +168,7 @@ export class Range implements Printable {
171168
}
172169

173170
public expandStart(): void {
174-
const start = this.start;
175-
const str = this.txt.str;
171+
const {start, rga: rga} = this;
176172
let chunk = start.chunk();
177173
if (!chunk) return;
178174
if (!chunk.del) {
@@ -185,7 +181,7 @@ export class Range implements Printable {
185181
}
186182
}
187183
while (chunk) {
188-
const prev = str.prev(chunk);
184+
const prev = rga.prev(chunk);
189185
if (!prev) {
190186
start.id = chunk.id;
191187
start.anchor = Anchor.Before;
@@ -204,8 +200,7 @@ export class Range implements Printable {
204200
}
205201

206202
public expandEnd(): void {
207-
const end = this.end;
208-
const str = this.txt.str;
203+
const {end, rga: rga} = this;
209204
let chunk = end.chunk();
210205
if (!chunk) return;
211206
if (!chunk.del) {
@@ -218,7 +213,7 @@ export class Range implements Printable {
218213
}
219214
}
220215
while (chunk) {
221-
const next = str.next(chunk);
216+
const next = rga.next(chunk);
222217
if (!next) {
223218
end.id = chunk.span > 1 ? tick(chunk.id, chunk.span - 1) : chunk.id;
224219
end.anchor = Anchor.After;
@@ -266,13 +261,13 @@ export class Range implements Printable {
266261
const isCaret = this.isCollapsed();
267262
if (isCaret) return '';
268263
const {start, end} = this;
269-
const str = this.txt.str;
264+
const rga = this.rga;
270265
const startId = start.anchor === Anchor.Before ? start.id : start.nextId();
271266
const endId = end.anchor === Anchor.After ? end.id : end.prevId();
272267
if (!startId || !endId) return '';
273268
let result = '';
274-
str.range0(undefined, startId, endId, (chunk: StringChunk, from: number, length: number) => {
275-
if (chunk.data) result += chunk.data.slice(from, from + length);
269+
rga.range0(undefined, startId, endId, (chunk: Chunk<T>, from: number, length: number) => {
270+
if (chunk.data) result += chunk.view().slice(from, from + length);
276271
});
277272
return result;
278273
}

0 commit comments

Comments
 (0)