jazz-tools 0.9.8 → 0.9.10-jazz-bridge-preview.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,20 +1,20 @@
1
1
 
2
- > jazz-tools@0.9.8 build /home/runner/work/jazz/jazz/packages/jazz-tools
2
+ > jazz-tools@0.9.9 build /vercel/path0/packages/jazz-tools
3
3
  > tsup
4
4
 
5
5
  CLI Building entry: {"index.web":"src/index.web.ts","index.native":"src/index.native.ts","testing":"src/testing.ts"}
6
6
  CLI Using tsconfig: tsconfig.json
7
7
  CLI tsup v8.3.5
8
- CLI Using tsup config: /home/runner/work/jazz/jazz/packages/jazz-tools/tsup.config.ts
8
+ CLI Using tsup config: /vercel/path0/packages/jazz-tools/tsup.config.ts
9
9
  CLI Target: es2021
10
10
  CLI Cleaning output folder
11
11
  ESM Build start
12
12
  ESM dist/index.web.js 1.15 KB
13
13
  ESM dist/index.native.js 1.14 KB
14
14
  ESM dist/testing.js 2.30 KB
15
- ESM dist/chunk-YD32FKHW.js 93.48 KB
15
+ ESM dist/chunk-VQZOWIPU.js 96.39 KB
16
16
  ESM dist/index.web.js.map 273.00 B
17
17
  ESM dist/index.native.js.map 283.00 B
18
18
  ESM dist/testing.js.map 4.89 KB
19
- ESM dist/chunk-YD32FKHW.js.map 231.35 KB
20
- ESM ⚡️ Build success in 115ms
19
+ ESM dist/chunk-VQZOWIPU.js.map 238.27 KB
20
+ ESM ⚡️ Build success in 90ms
@@ -0,0 +1,4 @@
1
+
2
+ > jazz-tools@0.7.35-guest-auth.5 lint /Users/anselm/jazz/jazz/packages/jazz-tools
3
+ > eslint . --ext ts,tsx
4
+
@@ -0,0 +1,144 @@
1
+
2
+ > jazz-tools@0.7.35-unique.2 test /Users/anselm/jazz/jazz/packages/jazz-tools
3
+ > vitest --run
4
+
5
+
6
+ RUN v0.34.6 /Users/anselm/jazz/jazz/packages/jazz-tools
7
+
8
+ ✓ src/tests/groupsAndAccounts.test.ts (1 test) 64ms
9
+ stdout | unknown test
10
+ TestMap schema undefined
11
+
12
+ ✓ src/tests/deepLoading.test.ts (3 tests) 83ms
13
+ stdout | src/tests/coList.test.ts > Simple CoList operations > Mutation > splice
14
+ [ 'bread', 'onion' ] 0
15
+ [ 'bread', 'salt', 'onion' ] 1
16
+
17
+ stdout | src/tests/coList.test.ts > CoList resolution > Subscription & auto-resolution
18
+ subscribedList?.[0]?.[0]?.[0] undefined
19
+ subscribedList?.[0]?.[0]?.[0] undefined
20
+ subscribedList?.[0]?.[0]?.[0] a
21
+ subscribedList?.[0]?.[0]?.[0] x
22
+ subscribedList?.[0]?.[0]?.[0] y
23
+ subscribedList?.[0]?.[0]?.[0] w
24
+
25
+ ✓ src/tests/coList.test.ts (10 tests) 190ms
26
+ stdout | src/tests/coStream.test.ts > CoStream resolution > Subscription & auto-resolution
27
+ subscribedStream[me.id] {
28
+ value: [Getter],
29
+ ref: [Getter],
30
+ by: [Getter],
31
+ madeAt: 2024-09-05T17:35:38.414Z,
32
+ tx: {
33
+ sessionID: 'co_zURWEpvoH1e35FGHVxadgXKU8Ri_session_ziAMdGVstAxF',
34
+ txIndex: 0
35
+ }
36
+ }
37
+ subscribedStream[me.id]?.value?.[me.id]?.value undefined
38
+ subscribedStream[me.id]?.value?.[me.id]?.value?.[me.id]?.value undefined
39
+ subscribedStream[me.id] {
40
+ value: [Getter],
41
+ ref: [Getter],
42
+ by: [Getter],
43
+ madeAt: 2024-09-05T17:35:38.414Z,
44
+ tx: {
45
+ sessionID: 'co_zURWEpvoH1e35FGHVxadgXKU8Ri_session_ziAMdGVstAxF',
46
+ txIndex: 0
47
+ }
48
+ }
49
+ subscribedStream[me.id]?.value?.[me.id]?.value null
50
+ subscribedStream[me.id]?.value?.[me.id]?.value?.[me.id]?.value undefined
51
+ subscribedStream[me.id] {
52
+ value: [Getter],
53
+ ref: [Getter],
54
+ by: [Getter],
55
+ madeAt: 2024-09-05T17:35:38.414Z,
56
+ tx: {
57
+ sessionID: 'co_zURWEpvoH1e35FGHVxadgXKU8Ri_session_ziAMdGVstAxF',
58
+ txIndex: 0
59
+ }
60
+ }
61
+ subscribedStream[me.id]?.value?.[me.id]?.value {
62
+ id: 'co_zHELVqRmAN6YuGDpKqVrSXJ5qe1',
63
+ _type: 'CoStream',
64
+ perSession: undefined,
65
+ co_zURWEpvoH1e35FGHVxadgXKU8Ri: 'milk',
66
+ in: { co_zURWEpvoH1e35FGHVxadgXKU8Ri_session_ziAMdGVstAxF: 'milk' }
67
+ }
68
+ subscribedStream[me.id]?.value?.[me.id]?.value?.[me.id]?.value milk
69
+ subscribedStream[me.id] {
70
+ value: [Getter],
71
+ ref: [Getter],
72
+ by: [Getter],
73
+ madeAt: 2024-09-05T17:35:38.414Z,
74
+ tx: {
75
+ sessionID: 'co_zURWEpvoH1e35FGHVxadgXKU8Ri_session_ziAMdGVstAxF',
76
+ txIndex: 0
77
+ }
78
+ }
79
+ subscribedStream[me.id]?.value?.[me.id]?.value {
80
+ id: 'co_zHELVqRmAN6YuGDpKqVrSXJ5qe1',
81
+ _type: 'CoStream',
82
+ perSession: undefined,
83
+ co_zURWEpvoH1e35FGHVxadgXKU8Ri: 'bread',
84
+ in: {
85
+ co_zURWEpvoH1e35FGHVxadgXKU8Ri_session_ziAMdGVstAxF: 'milk',
86
+ co_zURWEpvoH1e35FGHVxadgXKU8Ri_session_zgik2JjD86Qa: 'bread'
87
+ }
88
+ }
89
+ subscribedStream[me.id]?.value?.[me.id]?.value?.[me.id]?.value bread
90
+ subscribedStream[me.id] {
91
+ value: [Getter],
92
+ ref: [Getter],
93
+ by: [Getter],
94
+ madeAt: 2024-09-05T17:35:38.424Z,
95
+ tx: {
96
+ sessionID: 'co_zURWEpvoH1e35FGHVxadgXKU8Ri_session_zgik2JjD86Qa',
97
+ txIndex: 0
98
+ }
99
+ }
100
+ subscribedStream[me.id]?.value?.[me.id]?.value {
101
+ id: 'co_zJmdvJY15XJkWF3n3rwPgGfebxa',
102
+ _type: 'CoStream',
103
+ perSession: undefined,
104
+ co_zURWEpvoH1e35FGHVxadgXKU8Ri: 'butter',
105
+ in: { co_zURWEpvoH1e35FGHVxadgXKU8Ri_session_zgik2JjD86Qa: 'butter' }
106
+ }
107
+ subscribedStream[me.id]?.value?.[me.id]?.value?.[me.id]?.value butter
108
+ subscribedStream[me.id] {
109
+ value: [Getter],
110
+ ref: [Getter],
111
+ by: [Getter],
112
+ madeAt: 2024-09-05T17:35:38.424Z,
113
+ tx: {
114
+ sessionID: 'co_zURWEpvoH1e35FGHVxadgXKU8Ri_session_zgik2JjD86Qa',
115
+ txIndex: 0
116
+ }
117
+ }
118
+ subscribedStream[me.id]?.value?.[me.id]?.value {
119
+ id: 'co_zJmdvJY15XJkWF3n3rwPgGfebxa',
120
+ _type: 'CoStream',
121
+ perSession: undefined,
122
+ co_zURWEpvoH1e35FGHVxadgXKU8Ri: 'jam',
123
+ in: { co_zURWEpvoH1e35FGHVxadgXKU8Ri_session_zgik2JjD86Qa: 'jam' }
124
+ }
125
+ subscribedStream[me.id]?.value?.[me.id]?.value?.[me.id]?.value jam
126
+
127
+ ✓ src/tests/coStream.test.ts (10 tests) 205ms
128
+ stdout | src/tests/coMap.test.ts > CoMap resolution > Subscription & auto-resolution
129
+ subscribedMap.nested?.twiceNested?.taste undefined
130
+ subscribedMap.nested?.twiceNested?.taste undefined
131
+ subscribedMap.nested?.twiceNested?.taste sour
132
+ subscribedMap.nested?.twiceNested?.taste sour
133
+ subscribedMap.nested?.twiceNested?.taste sweet
134
+ subscribedMap.nested?.twiceNested?.taste sweet
135
+ subscribedMap.nested?.twiceNested?.taste salty
136
+ subscribedMap.nested?.twiceNested?.taste umami
137
+
138
+ ✓ src/tests/coMap.test.ts (20 tests) 257ms
139
+
140
+ Test Files 5 passed (5)
141
+ Tests 44 passed (44)
142
+ Start at 18:35:37
143
+ Duration 929ms (transform 419ms, setup 0ms, collect 2.29s, tests 799ms, environment 0ms, prepare 298ms)
144
+
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # jazz-tools
2
2
 
3
+ ## 0.9.10-jazz-bridge-preview.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 5f43fbf: Implement applyDiff for CoLists
8
+
9
+ ## 0.9.9
10
+
11
+ ### Patch Changes
12
+
13
+ - 8eb9247: Add CoRichText support
14
+ - Updated dependencies [8eb9247]
15
+ - cojson@0.9.9
16
+
3
17
  ## 0.9.8
4
18
 
5
19
  ### Patch Changes
@@ -36,13 +36,61 @@ var AnonymousJazzAgent = class {
36
36
  // src/coValues/interfaces.ts
37
37
  import { RawAccount as RawAccount2 } from "cojson";
38
38
 
39
+ // src/implementation/inspect.ts
40
+ var inspect = Symbol.for("nodejs.util.inspect.custom");
41
+
39
42
  // src/implementation/symbols.ts
40
43
  var SchemaInit = Symbol.for("SchemaInit");
41
44
  var ItemsSym = Symbol.for("items");
42
45
  var MembersSym = Symbol.for("members");
43
46
 
44
- // src/implementation/inspect.ts
45
- var inspect = Symbol.for("nodejs.util.inspect.custom");
47
+ // src/coValues/deepLoading.ts
48
+ function fulfillsDepth(depth, value) {
49
+ if (value._type === "CoMap" || value._type === "Group" || value._type === "Account") {
50
+ if (Array.isArray(depth) && depth.length === 1) {
51
+ return Object.entries(value).every(([key, item]) => {
52
+ return value._refs[key] ? item && fulfillsDepth(depth[0], item) : value._schema[ItemsSym].optional;
53
+ });
54
+ } else {
55
+ for (const key of Object.keys(depth)) {
56
+ const map = value;
57
+ if (!map._refs[key] && map._schema[key].optional) {
58
+ continue;
59
+ }
60
+ if (!map[key]) {
61
+ return false;
62
+ }
63
+ if (!fulfillsDepth(depth[key], map[key])) {
64
+ return false;
65
+ }
66
+ }
67
+ return true;
68
+ }
69
+ } else if (value._type === "CoList") {
70
+ if (depth.length === 0) {
71
+ return true;
72
+ } else {
73
+ const itemDepth = depth[0];
74
+ return value.every(
75
+ (item, i) => value._refs[i] ? item && fulfillsDepth(itemDepth, item) : value._schema[ItemsSym].optional
76
+ );
77
+ }
78
+ } else if (value._type === "CoStream") {
79
+ if (depth.length === 0) {
80
+ return true;
81
+ } else {
82
+ const itemDepth = depth[0];
83
+ return Object.values(value.perSession).every(
84
+ (entry) => entry.ref ? entry.value && fulfillsDepth(itemDepth, entry.value) : value._schema[ItemsSym].optional
85
+ );
86
+ }
87
+ } else if (value._type === "BinaryCoStream" || value._type === "CoPlainText") {
88
+ return true;
89
+ } else {
90
+ console.error(value);
91
+ throw new Error("Unexpected value type: " + value._type);
92
+ }
93
+ }
46
94
 
47
95
  // src/lib/cache.ts
48
96
  var weakMap = /* @__PURE__ */ new WeakMap();
@@ -356,54 +404,6 @@ var SubscriptionScope = class {
356
404
  }
357
405
  };
358
406
 
359
- // src/coValues/deepLoading.ts
360
- function fulfillsDepth(depth, value) {
361
- if (value._type === "CoMap" || value._type === "Group" || value._type === "Account") {
362
- if (Array.isArray(depth) && depth.length === 1) {
363
- return Object.entries(value).every(([key, item]) => {
364
- return value._refs[key] ? item && fulfillsDepth(depth[0], item) : value._schema[ItemsSym].optional;
365
- });
366
- } else {
367
- for (const key of Object.keys(depth)) {
368
- const map = value;
369
- if (!map._refs[key] && map._schema[key].optional) {
370
- continue;
371
- }
372
- if (!map[key]) {
373
- return false;
374
- }
375
- if (!fulfillsDepth(depth[key], map[key])) {
376
- return false;
377
- }
378
- }
379
- return true;
380
- }
381
- } else if (value._type === "CoList") {
382
- if (depth.length === 0) {
383
- return true;
384
- } else {
385
- const itemDepth = depth[0];
386
- return value.every(
387
- (item, i) => value._refs[i] ? item && fulfillsDepth(itemDepth, item) : value._schema[ItemsSym].optional
388
- );
389
- }
390
- } else if (value._type === "CoStream") {
391
- if (depth.length === 0) {
392
- return true;
393
- } else {
394
- const itemDepth = depth[0];
395
- return Object.values(value.perSession).every(
396
- (entry) => entry.ref ? entry.value && fulfillsDepth(itemDepth, entry.value) : value._schema[ItemsSym].optional
397
- );
398
- }
399
- } else if (value._type === "BinaryCoStream" || value._type === "CoPlainText") {
400
- return true;
401
- } else {
402
- console.error(value);
403
- throw new Error("Unexpected value type: " + value._type);
404
- }
405
- }
406
-
407
407
  // src/implementation/createContext.ts
408
408
  import {
409
409
  ControlledAgent,
@@ -1121,6 +1121,7 @@ function getAccountIDfromSessionID(sessionID) {
1121
1121
 
1122
1122
  // src/coValues/coMap.ts
1123
1123
  import {
1124
+ CoValueCore,
1124
1125
  cojsonInternals
1125
1126
  } from "cojson";
1126
1127
  var _CoMap = class _CoMap extends CoValueBase {
@@ -1375,6 +1376,43 @@ var _CoMap = class _CoMap extends CoValueBase {
1375
1376
  const crypto = as._type === "Anonymous" ? as.node.crypto : as._raw.core.crypto;
1376
1377
  return cojsonInternals.idforHeader(header, crypto);
1377
1378
  }
1379
+ static async getUnique(unique, ownerID, as) {
1380
+ as ||= activeAccountContext.get();
1381
+ const header = {
1382
+ type: "comap",
1383
+ ruleset: {
1384
+ type: "ownedByGroup",
1385
+ group: ownerID
1386
+ },
1387
+ meta: null,
1388
+ uniqueness: unique
1389
+ };
1390
+ const crypto = as._raw.core.crypto;
1391
+ const id = cojsonInternals.idforHeader(header, crypto);
1392
+ const existingEntry = as._raw.core.node.coValuesStore.get(id);
1393
+ if (existingEntry) {
1394
+ if (existingEntry.state.type === "available") {
1395
+ return this.fromRaw(
1396
+ existingEntry.state.coValue.getCurrentContent()
1397
+ );
1398
+ } else if (existingEntry.state.type !== "unknown") {
1399
+ throw new Error(
1400
+ `Can't handle intermediate state for unique CoMap: ${existingEntry.state.type}`
1401
+ );
1402
+ }
1403
+ }
1404
+ as._raw.core.node.coValuesStore.setAsAvailable(
1405
+ id,
1406
+ new CoValueCore(header, as._raw.core.node)
1407
+ );
1408
+ const entry = as._raw.core.node.coValuesStore.get(id);
1409
+ if (entry.state.type !== "available") {
1410
+ throw new Error("CoValue not found");
1411
+ }
1412
+ return this.fromRaw(
1413
+ entry.state.coValue.getCurrentContent()
1414
+ );
1415
+ }
1378
1416
  /**
1379
1417
  * Given an already loaded `CoMap`, ensure that the specified fields are loaded to the specified depth.
1380
1418
  *
@@ -2314,6 +2352,7 @@ var FileStream = class extends CoValueBase {
2314
2352
 
2315
2353
  // src/coValues/coList.ts
2316
2354
  import { RawAccount as RawAccount5 } from "cojson";
2355
+ import { calcPatch } from "fast-myers-diff";
2317
2356
  var _CoList = class _CoList extends Array {
2318
2357
  /**
2319
2358
  * Declare a `CoList` by subclassing `CoList.Of(...)` and passing the item schema using `co`.
@@ -2478,12 +2517,20 @@ var _CoList = class _CoList extends Array {
2478
2517
  }
2479
2518
  let appendAfter = Math.max(start - 1, 0);
2480
2519
  for (const item of toRawItems(items, this._schema[ItemsSym])) {
2481
- console.log(this._raw.asArray(), appendAfter);
2482
2520
  this._raw.append(item, appendAfter);
2483
2521
  appendAfter++;
2484
2522
  }
2485
2523
  return deleted;
2486
2524
  }
2525
+ applyDiff(other) {
2526
+ const current = this._raw.asArray();
2527
+ const cmp = isRefEncoded(this._schema[ItemsSym]) ? (aIdx, bIdx) => current[aIdx].id === other[bIdx].id : void 0;
2528
+ for (const [from, to, insert] of [
2529
+ ...calcPatch(current, other, cmp)
2530
+ ].reverse()) {
2531
+ this.splice(from, to - from, ...insert);
2532
+ }
2533
+ }
2487
2534
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
2488
2535
  toJSON(_key, seenAbove) {
2489
2536
  const itemDescriptor = this._schema[ItemsSym];
@@ -2798,6 +2845,9 @@ var CoPlainText = class extends String {
2798
2845
  static create(text, options) {
2799
2846
  return new this({ text, owner: options.owner });
2800
2847
  }
2848
+ get length() {
2849
+ return this._raw.toString().length;
2850
+ }
2801
2851
  toString() {
2802
2852
  return this._raw.toString();
2803
2853
  }
@@ -2834,22 +2884,6 @@ var CoPlainText = class extends String {
2834
2884
  /**
2835
2885
  * Load a `CoPlainText` with a given ID, as a given account.
2836
2886
  *
2837
- * `depth` specifies which (if any) fields that reference other CoValues to load as well before resolving.
2838
- * The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth.
2839
- *
2840
- * You can pass `[]` or `{}` for shallowly loading only this CoPlainText, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues.
2841
- *
2842
- * Check out the `load` methods on `CoMap`/`CoList`/`CoStream`/`Group`/`Account` to see which depth structures are valid to nest.
2843
- *
2844
- * @example
2845
- * ```ts
2846
- * const person = await Person.load(
2847
- * "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax",
2848
- * me,
2849
- * { pet: {} }
2850
- * );
2851
- * ```
2852
- *
2853
2887
  * @category Subscription & Loading
2854
2888
  */
2855
2889
  static load(id, as) {
@@ -2881,9 +2915,9 @@ var CoPlainText = class extends String {
2881
2915
  // return subscribeToCoValueEf(this, id, []);
2882
2916
  // }
2883
2917
  /**
2884
- * Given an already loaded `CoMap`, subscribe to updates to the `CoMap` and ensure that the specified fields are loaded to the specified depth.
2918
+ * Given an already loaded `CoPlainText`, subscribe to updates to the `CoPlainText` and ensure that the specified fields are loaded to the specified depth.
2885
2919
  *
2886
- * Works like `CoMap.subscribe()`, but you don't need to pass the ID or the account to load as again.
2920
+ * Works like `CoPlainText.subscribe()`, but you don't need to pass the ID or the account to load as again.
2887
2921
  *
2888
2922
  * Returns an unsubscribe function that you should call when you no longer need updates.
2889
2923
  *
@@ -2904,6 +2938,28 @@ var Mark = class extends CoMap {
2904
2938
  this.endBefore = co.json();
2905
2939
  this.tag = co.string;
2906
2940
  }
2941
+ /**
2942
+ * Validates and clamps mark positions to ensure they are in the correct order
2943
+ * @returns Normalized positions or null if invalid
2944
+ */
2945
+ validatePositions(textLength, idxAfter, idxBefore) {
2946
+ if (!textLength) {
2947
+ console.error("Cannot validate positions for empty text");
2948
+ return null;
2949
+ }
2950
+ const positions = {
2951
+ startAfter: this.startAfter ? idxBefore(this.startAfter) ?? 0 : 0,
2952
+ startBefore: this.startBefore ? idxAfter(this.startBefore) ?? 0 : 0,
2953
+ endAfter: this.endAfter ? idxBefore(this.endAfter) ?? textLength : textLength,
2954
+ endBefore: this.endBefore ? idxAfter(this.endBefore) ?? textLength : textLength
2955
+ };
2956
+ return {
2957
+ startAfter: Math.max(0, positions.startAfter),
2958
+ startBefore: Math.max(positions.startAfter + 1, positions.startBefore),
2959
+ endAfter: Math.min(textLength - 1, positions.endAfter),
2960
+ endBefore: Math.min(textLength, positions.endBefore)
2961
+ };
2962
+ }
2907
2963
  };
2908
2964
  var CoRichText = class extends CoMap {
2909
2965
  constructor() {
@@ -2993,9 +3049,16 @@ var CoRichText = class extends CoMap {
2993
3049
  * Insert a mark at a specific range.
2994
3050
  */
2995
3051
  insertMark(start, end, RangeClass, extraArgs, options) {
2996
- if (!this.marks) {
3052
+ if (!this.text || !this.marks) {
2997
3053
  throw new Error("Cannot insert a range without loaded ranges");
2998
3054
  }
3055
+ const textLength = this.length;
3056
+ start = Math.max(start, 0);
3057
+ end = Math.min(end, textLength);
3058
+ const owner = options?.markOwner || this._owner;
3059
+ if (!owner) {
3060
+ throw new Error("No owner specified for mark");
3061
+ }
2999
3062
  const range = RangeClass.create(
3000
3063
  {
3001
3064
  ...extraArgs,
@@ -3004,10 +3067,71 @@ var CoRichText = class extends CoMap {
3004
3067
  endAfter: this.posBefore(end),
3005
3068
  endBefore: this.posAfter(end)
3006
3069
  },
3007
- { owner: options?.markOwner || this._owner }
3070
+ { owner }
3008
3071
  );
3009
3072
  this.marks.push(range);
3010
3073
  }
3074
+ /**
3075
+ * Remove a mark at a specific range.
3076
+ */
3077
+ removeMark(start, end, RangeClass, options) {
3078
+ if (!this.marks) {
3079
+ throw new Error("Cannot remove marks without loaded marks");
3080
+ }
3081
+ const resolvedMarks = this.resolveMarks();
3082
+ for (const mark of resolvedMarks) {
3083
+ if (mark.endBefore < start || mark.startAfter > end) {
3084
+ continue;
3085
+ }
3086
+ if (options.tag && mark.sourceMark.tag !== options.tag) {
3087
+ continue;
3088
+ }
3089
+ const markIndex = this.marks.findIndex((m) => m === mark.sourceMark);
3090
+ if (markIndex === -1) {
3091
+ continue;
3092
+ }
3093
+ if (mark.startBefore >= start && mark.endAfter <= end) {
3094
+ this.marks.splice(markIndex, 1);
3095
+ continue;
3096
+ }
3097
+ if (mark.startBefore < start && mark.endAfter >= start && mark.endAfter <= end) {
3098
+ const endAfterPos = this.posBefore(start);
3099
+ const endBeforePos = this.posBefore(start);
3100
+ if (endAfterPos && endBeforePos) {
3101
+ mark.sourceMark.endAfter = endAfterPos;
3102
+ mark.sourceMark.endBefore = endBeforePos;
3103
+ }
3104
+ continue;
3105
+ }
3106
+ if (mark.startBefore >= start && mark.startBefore <= end && mark.endAfter > end) {
3107
+ const startAfterPos = this.posAfter(end);
3108
+ const startBeforePos = this.posAfter(end);
3109
+ if (startAfterPos && startBeforePos) {
3110
+ mark.sourceMark.startAfter = startAfterPos;
3111
+ mark.sourceMark.startBefore = startBeforePos;
3112
+ }
3113
+ continue;
3114
+ }
3115
+ if (mark.startBefore <= start && mark.endAfter >= end) {
3116
+ const endAfterPos = this.posBefore(start);
3117
+ const endBeforePos = this.posBefore(start);
3118
+ if (endAfterPos && endBeforePos) {
3119
+ mark.sourceMark.endAfter = endAfterPos;
3120
+ mark.sourceMark.endBefore = endBeforePos;
3121
+ }
3122
+ this.insertMark(
3123
+ end + 1,
3124
+ mark.endBefore,
3125
+ RangeClass,
3126
+ {},
3127
+ {
3128
+ markOwner: mark.sourceMark._owner || this._owner
3129
+ }
3130
+ );
3131
+ continue;
3132
+ }
3133
+ }
3134
+ }
3011
3135
  /**
3012
3136
  * Resolve the positions of all marks.
3013
3137
  */
@@ -3015,31 +3139,23 @@ var CoRichText = class extends CoMap {
3015
3139
  if (!this.text || !this.marks) {
3016
3140
  throw new Error("Cannot resolve ranges without loaded text and ranges");
3017
3141
  }
3018
- const ranges = this.marks.flatMap((mark) => {
3142
+ const textLength = this.length;
3143
+ return this.marks.flatMap((mark) => {
3019
3144
  if (!mark) return [];
3020
- const startBefore = this.idxAfter(mark.startBefore);
3021
- const endAfter = this.idxAfter(mark.endAfter);
3022
- if (startBefore === void 0 || endAfter === void 0) {
3023
- return [];
3024
- }
3025
- const startAfter = mark.startAfter ? this.idxAfter(mark.startAfter) : startBefore - 1;
3026
- const endBefore = mark.endBefore ? this.idxAfter(mark.endBefore) : endAfter + 1;
3027
- if (startAfter === void 0 || endBefore === void 0) {
3028
- return [];
3029
- }
3145
+ const positions = mark.validatePositions(
3146
+ textLength,
3147
+ (pos) => this.idxAfter(pos),
3148
+ (pos) => this.idxBefore(pos)
3149
+ );
3150
+ if (!positions) return [];
3030
3151
  return [
3031
3152
  {
3032
3153
  sourceMark: mark,
3033
- startAfter,
3034
- startBefore,
3035
- endAfter,
3036
- endBefore,
3037
- tag: mark.tag,
3038
- from: mark
3154
+ ...positions,
3155
+ tag: mark.tag
3039
3156
  }
3040
3157
  ];
3041
3158
  });
3042
- return ranges;
3043
3159
  }
3044
3160
  /**
3045
3161
  * Resolve and diffuse the positions of all marks.
@@ -3124,6 +3240,9 @@ var CoRichText = class extends CoMap {
3124
3240
  children: currentNodes
3125
3241
  };
3126
3242
  }
3243
+ get length() {
3244
+ return this.text?.toString().length || 0;
3245
+ }
3127
3246
  /**
3128
3247
  * Convert a CoRichText to plain text.
3129
3248
  */
@@ -3329,4 +3448,4 @@ export {
3329
3448
  SchemaUnion
3330
3449
  };
3331
3450
  /* istanbul ignore file -- @preserve */
3332
- //# sourceMappingURL=chunk-YD32FKHW.js.map
3451
+ //# sourceMappingURL=chunk-YWGGIF2U.js.map