Skip to content

Commit 4c92831

Browse files
committed
fix(json-crdt-extensions): 🐛 return all cursors even in presence of other slice types
1 parent 79651ef commit 4c92831

File tree

1 file changed

+22
-14
lines changed
  • src/json-crdt-extensions/peritext/editor

1 file changed

+22
-14
lines changed

src/json-crdt-extensions/peritext/editor/Editor.ts

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,11 @@ export class Editor<T = string> implements Printable {
107107
public cursors0(): UndefIterator<Cursor<T>> {
108108
const iterator = this.txt.localSlices.iterator0();
109109
return () => {
110-
const slice = iterator();
111-
return slice instanceof Cursor ? slice : void 0;
110+
while (true) {
111+
const slice = iterator();
112+
if (slice instanceof Cursor) return slice;
113+
if (!slice) return;
114+
}
112115
};
113116
}
114117

@@ -197,37 +200,42 @@ export class Editor<T = string> implements Printable {
197200
* Insert inline text at current cursor position. If cursor selects a range,
198201
* the range is removed and the text is inserted at the start of the range.
199202
*/
200-
public insert0(cursor: Cursor<T>, text: string): ITimespanStruct | undefined {
203+
public insert0(range: Range<T>, text: string): ITimespanStruct | undefined {
201204
if (!text) return;
202-
if (!cursor.isCollapsed()) this.delRange(cursor);
203-
const after = cursor.start.clone();
205+
if (!range.isCollapsed()) this.delRange(range);
206+
const after = range.start.clone();
204207
after.refAfter();
205208
const txt = this.txt;
206209
const textId = txt.ins(after.id, text);
207210
const span = new Timespan(textId.sid, textId.time, text.length);
208211
const shift = text.length - 1;
209212
const point = txt.point(shift ? tick(textId, shift) : textId, Anchor.After);
210-
cursor.set(point, point, CursorAnchor.Start);
213+
if (range instanceof Cursor) range.set(point, point, CursorAnchor.Start);
214+
else range.set(point);
211215
return span;
212216
}
213217

214218
/**
215219
* Inserts text at the cursor positions and collapses cursors, if necessary.
216-
* The applies any pending inline formatting to the inserted text.
220+
* Then applies any pending inline formatting to the inserted text.
217221
*/
218-
public insert(text: string): ITimespanStruct[] {
222+
public insert(text: string, ranges?: IterableIterator<Range<T>> | Range<T>[]): ITimespanStruct[] {
219223
const spans: ITimespanStruct[] = [];
220-
if (!this.hasCursor()) this.addCursor();
221-
for (let cursor: Cursor<T> | undefined, i = this.cursors0(); (cursor = i()); ) {
222-
const span = this.insert0(cursor, text);
224+
if (!ranges) {
225+
if (!this.hasCursor()) this.addCursor();
226+
ranges = this.cursors();
227+
}
228+
if (!ranges) return [];
229+
for (const range of ranges) {
230+
const span = this.insert0(range, text);
223231
if (span) spans.push(span);
224232
const pending = this.pending.value;
225233
if (pending.size) {
226234
this.pending.next(new Map());
227-
const start = cursor.start.clone();
235+
const start = range.start.clone();
228236
start.step(-text.length);
229-
const range = this.txt.range(start, cursor.end.clone());
230-
for (const [type, data] of pending) this.toggleRangeExclFmt(range, type, data);
237+
const toggleRange = this.txt.range(start, range.end.clone());
238+
for (const [type, data] of pending) this.toggleRangeExclFmt(toggleRange, type, data);
231239
}
232240
}
233241
return spans;

0 commit comments

Comments
 (0)