@monstermann/delta 0.0.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.
- package/LICENSE +21 -0
- package/README.md +695 -0
- package/dist/Delta/batch.d.mts +57 -0
- package/dist/Delta/batch.mjs +61 -0
- package/dist/Delta/chop.d.mts +56 -0
- package/dist/Delta/chop.mjs +60 -0
- package/dist/Delta/clean.d.mts +57 -0
- package/dist/Delta/clean.mjs +61 -0
- package/dist/Delta/compose.d.mts +58 -0
- package/dist/Delta/compose.mjs +100 -0
- package/dist/Delta/concat.d.mts +50 -0
- package/dist/Delta/concat.mjs +51 -0
- package/dist/Delta/diff.d.mts +73 -0
- package/dist/Delta/diff.mjs +124 -0
- package/dist/Delta/equals.d.mts +43 -0
- package/dist/Delta/equals.mjs +50 -0
- package/dist/Delta/index.d.mts +26 -0
- package/dist/Delta/index.mjs +37 -0
- package/dist/Delta/insert.d.mts +52 -0
- package/dist/Delta/insert.mjs +57 -0
- package/dist/Delta/invert.d.mts +54 -0
- package/dist/Delta/invert.mjs +77 -0
- package/dist/Delta/length.d.mts +51 -0
- package/dist/Delta/length.mjs +51 -0
- package/dist/Delta/push.d.mts +51 -0
- package/dist/Delta/push.mjs +87 -0
- package/dist/Delta/remove.d.mts +41 -0
- package/dist/Delta/remove.mjs +46 -0
- package/dist/Delta/retain.d.mts +70 -0
- package/dist/Delta/retain.mjs +76 -0
- package/dist/Delta/slice.d.mts +64 -0
- package/dist/Delta/slice.mjs +77 -0
- package/dist/Delta/transform.d.mts +63 -0
- package/dist/Delta/transform.mjs +91 -0
- package/dist/Op/index.d.mts +21 -0
- package/dist/OpAttributes/compose.d.mts +6 -0
- package/dist/OpAttributes/compose.mjs +25 -0
- package/dist/OpAttributes/diff.d.mts +6 -0
- package/dist/OpAttributes/diff.mjs +14 -0
- package/dist/OpAttributes/index.d.mts +15 -0
- package/dist/OpAttributes/invert.d.mts +6 -0
- package/dist/OpAttributes/invert.mjs +16 -0
- package/dist/OpAttributes/isEqual.d.mts +6 -0
- package/dist/OpAttributes/isEqual.mjs +16 -0
- package/dist/OpAttributes/transform.d.mts +6 -0
- package/dist/OpAttributes/transform.mjs +13 -0
- package/dist/OpIterator/create.mjs +11 -0
- package/dist/OpIterator/hasNext.mjs +9 -0
- package/dist/OpIterator/next.mjs +36 -0
- package/dist/OpIterator/peek.mjs +7 -0
- package/dist/OpIterator/peekLength.mjs +9 -0
- package/dist/OpIterator/peekType.mjs +7 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +3 -0
- package/dist/internals/hasKeys.mjs +8 -0
- package/package.json +42 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) Michael Ostermann
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,695 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<h1>delta</h1>
|
|
4
|
+
|
|
5
|
+
 
|
|
6
|
+
|
|
7
|
+
**Functional operational-transform.**
|
|
8
|
+
|
|
9
|
+
[Documentation](https://MichaelOstermann.github.io/delta)
|
|
10
|
+
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
> [!WARNING]
|
|
14
|
+
> Due to the many footguns and pitalls present in collaborative applications based on operational transform, this library should only be used for ad-hoc string manipulation. Please consider using [conflict-free replicated data types](https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type) for serious applications.
|
|
15
|
+
|
|
16
|
+
## Differences from quill-delta
|
|
17
|
+
|
|
18
|
+
This library has been largely ported from [quill-delta](https://github.com/slab/delta), some differences:
|
|
19
|
+
|
|
20
|
+
- Immutable with optional transient mutations
|
|
21
|
+
- Functional data-first/data-last API acting upon plain arrays
|
|
22
|
+
- Higher fidelity type definitions
|
|
23
|
+
- Operations have been migrated to a monomorphic, tagged union
|
|
24
|
+
- The `delete` operation has been renamed to `remove`, as `delete` is a reserved keyword
|
|
25
|
+
- Support for embeds has been removed
|
|
26
|
+
- Support for nested attributes has been removed
|
|
27
|
+
- Cloning is only done when the data actually changes
|
|
28
|
+
- Deep-cloning has been replaced with shallow-cloning
|
|
29
|
+
- Around 50% smaller
|
|
30
|
+
|
|
31
|
+
## Example
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
```sh [npm]
|
|
36
|
+
npm install @monstermann/delta
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
```sh [pnpm]
|
|
40
|
+
pnpm add @monstermann/delta
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```sh [yarn]
|
|
44
|
+
yarn add @monstermann/delta
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```sh [bun]
|
|
48
|
+
bun add @monstermann/delta
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Delta
|
|
52
|
+
|
|
53
|
+
### batch
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
function Delta.batch<T>(
|
|
57
|
+
ops: Delta<T>,
|
|
58
|
+
transform: (delta: Delta<T>) => Delta<T>,
|
|
59
|
+
): Delta<T>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Batches multiple delta operations together for improved performance.
|
|
63
|
+
|
|
64
|
+
#### Example
|
|
65
|
+
|
|
66
|
+
```ts [data-first]
|
|
67
|
+
import { Delta } from "@monstermann/delta";
|
|
68
|
+
|
|
69
|
+
Delta.batch([], (delta) => {
|
|
70
|
+
// First change copies:
|
|
71
|
+
delta = Delta.insert(delta, "Hello", { bold: true });
|
|
72
|
+
// Other changes mutate:
|
|
73
|
+
delta = Delta.insert(delta, " world");
|
|
74
|
+
return delta;
|
|
75
|
+
});
|
|
76
|
+
// [{ type: "insert", value: "Hello", attributes: { bold: true } },
|
|
77
|
+
// { type: "insert", value: " world" }]
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```ts [data-last]
|
|
81
|
+
import { Delta } from "@monstermann/delta";
|
|
82
|
+
|
|
83
|
+
pipe(
|
|
84
|
+
[],
|
|
85
|
+
Delta.batch((delta) => {
|
|
86
|
+
// First change copies:
|
|
87
|
+
delta = Delta.insert(delta, "Hello", { bold: true });
|
|
88
|
+
// Other changes mutate:
|
|
89
|
+
delta = Delta.insert(delta, " world");
|
|
90
|
+
return delta;
|
|
91
|
+
}),
|
|
92
|
+
);
|
|
93
|
+
// [{ type: "insert", value: "Hello", attributes: { bold: true } },
|
|
94
|
+
// { type: "insert", value: " world" }]
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### chop
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
function Delta.chop<T>(ops: Delta<T>): Delta<T>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Removes a trailing retain operation if it has no attributes.
|
|
104
|
+
|
|
105
|
+
#### Example
|
|
106
|
+
|
|
107
|
+
<!-- prettier-ignore -->
|
|
108
|
+
```ts [data-first]
|
|
109
|
+
import { Delta } from "@monstermann/delta";
|
|
110
|
+
|
|
111
|
+
Delta.chop(pipe(
|
|
112
|
+
[],
|
|
113
|
+
Delta.insert("Hello"),
|
|
114
|
+
Delta.retain(5)
|
|
115
|
+
));
|
|
116
|
+
// [{ type: "insert", value: "Hello" }]
|
|
117
|
+
|
|
118
|
+
Delta.chop(pipe(
|
|
119
|
+
[],
|
|
120
|
+
Delta.insert("Hello"),
|
|
121
|
+
Delta.retain(5, { bold: true })
|
|
122
|
+
));
|
|
123
|
+
// [{ type: "insert", value: "Hello" },
|
|
124
|
+
// { type: "retain", value: 5, attributes: { bold: true } }]
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
<!-- prettier-ignore -->
|
|
128
|
+
```ts [data-last]
|
|
129
|
+
import { Delta } from "@monstermann/delta";
|
|
130
|
+
|
|
131
|
+
pipe(
|
|
132
|
+
[],
|
|
133
|
+
Delta.insert("Hello"),
|
|
134
|
+
Delta.retain(5),
|
|
135
|
+
Delta.chop()
|
|
136
|
+
);
|
|
137
|
+
// [{ type: "insert", value: "Hello" }]
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### clean
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
function Delta.clean<T>(ops: Delta<T>): Delta<T>
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Normalizes the delta by merging consecutive operations of the same type and attributes.
|
|
147
|
+
|
|
148
|
+
#### Example
|
|
149
|
+
|
|
150
|
+
<!-- prettier-ignore -->
|
|
151
|
+
```ts [data-first]
|
|
152
|
+
import { Delta } from "@monstermann/delta";
|
|
153
|
+
|
|
154
|
+
Delta.clean(pipe(
|
|
155
|
+
[],
|
|
156
|
+
Delta.insert("Hello"),
|
|
157
|
+
Delta.insert(" world")
|
|
158
|
+
));
|
|
159
|
+
// [{ type: "insert", value: "Hello world" }]
|
|
160
|
+
|
|
161
|
+
Delta.clean(
|
|
162
|
+
pipe(
|
|
163
|
+
[],
|
|
164
|
+
Delta.insert("Hello", { bold: true }),
|
|
165
|
+
Delta.insert(" world", { bold: true }),
|
|
166
|
+
),
|
|
167
|
+
);
|
|
168
|
+
// [{ type: "insert", value: "Hello world", attributes: { bold: true } }]
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
<!-- prettier-ignore -->
|
|
172
|
+
```ts [data-last]
|
|
173
|
+
import { Delta } from "@monstermann/delta";
|
|
174
|
+
|
|
175
|
+
pipe(
|
|
176
|
+
[],
|
|
177
|
+
Delta.insert("Hello"),
|
|
178
|
+
Delta.insert(" world"),
|
|
179
|
+
Delta.clean()
|
|
180
|
+
);
|
|
181
|
+
// [{ type: "insert", value: "Hello world" }]
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### compose
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
function Delta.compose<T>(a: Delta<T>, b: Delta<T>): Delta<T>
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Composes two deltas into a single delta that represents applying `a` then `b`.
|
|
191
|
+
|
|
192
|
+
#### Example
|
|
193
|
+
|
|
194
|
+
<!-- prettier-ignore -->
|
|
195
|
+
```ts [data-first]
|
|
196
|
+
import { Delta } from "@monstermann/delta";
|
|
197
|
+
|
|
198
|
+
const a = Delta.insert([], "Hello");
|
|
199
|
+
const b = pipe(
|
|
200
|
+
[],
|
|
201
|
+
Delta.retain(5),
|
|
202
|
+
Delta.insert(" world")
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
Delta.compose(a, b);
|
|
206
|
+
// [{ type: "insert", value: "Hello world" }]
|
|
207
|
+
|
|
208
|
+
const format = Delta.retain([], 5, { bold: true });
|
|
209
|
+
|
|
210
|
+
Delta.compose(a, format);
|
|
211
|
+
// [{ type: "insert", value: "Hello", attributes: { bold: true } }]
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
<!-- prettier-ignore -->
|
|
215
|
+
```ts [data-last]
|
|
216
|
+
import { Delta } from "@monstermann/delta";
|
|
217
|
+
|
|
218
|
+
const a = Delta.insert([], "Hello");
|
|
219
|
+
const b = pipe(
|
|
220
|
+
[],
|
|
221
|
+
Delta.retain(5),
|
|
222
|
+
Delta.insert(" world")
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
pipe(a, Delta.compose(b));
|
|
226
|
+
// [{ type: "insert", value: "Hello world" }]
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### concat
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
function Delta.concat<T>(a: Delta<T>, b: Delta<T>): Delta<T>
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Concatenates two deltas together, merging adjacent operations if possible.
|
|
236
|
+
|
|
237
|
+
#### Example
|
|
238
|
+
|
|
239
|
+
```ts [data-first]
|
|
240
|
+
import { Delta } from "@monstermann/delta";
|
|
241
|
+
|
|
242
|
+
const a = Delta.insert([], "Hello");
|
|
243
|
+
const b = Delta.insert([], " world");
|
|
244
|
+
|
|
245
|
+
Delta.concat(a, b);
|
|
246
|
+
// [{ type: "insert", value: "Hello world" }]
|
|
247
|
+
|
|
248
|
+
const bold = Delta.insert([], "Hello", { bold: true });
|
|
249
|
+
const italic = Delta.insert([], " world", { italic: true });
|
|
250
|
+
|
|
251
|
+
Delta.concat(bold, italic);
|
|
252
|
+
// [{ type: "insert", value: "Hello", attributes: { bold: true } },
|
|
253
|
+
// { type: "insert", value: " world", attributes: { italic: true } }]
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
```ts [data-last]
|
|
257
|
+
import { Delta } from "@monstermann/delta";
|
|
258
|
+
|
|
259
|
+
const a = Delta.insert([], "Hello");
|
|
260
|
+
const b = Delta.insert([], " world");
|
|
261
|
+
|
|
262
|
+
pipe(a, Delta.concat(b));
|
|
263
|
+
// [{ type: "insert", value: "Hello world" }]
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### diff
|
|
267
|
+
|
|
268
|
+
```ts
|
|
269
|
+
function Delta.diff<T>(a: Delta<T>, b: Delta<T>, cursor?: number): Delta<T>
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
Computes the difference between two document deltas, returning a delta that transforms `a` into `b`.
|
|
273
|
+
|
|
274
|
+
The optional `cursor` parameter provides a hint about where the user's cursor is positioned. This helps produce more intuitive diffs when there are multiple valid ways to represent the same change.
|
|
275
|
+
|
|
276
|
+
#### Example
|
|
277
|
+
|
|
278
|
+
```ts [data-first]
|
|
279
|
+
import { Delta } from "@monstermann/delta";
|
|
280
|
+
|
|
281
|
+
const a = Delta.insert([], "Hello");
|
|
282
|
+
const b = Delta.insert([], "Hello world");
|
|
283
|
+
|
|
284
|
+
Delta.diff(a, b);
|
|
285
|
+
// [{ type: "retain", value: 5 },
|
|
286
|
+
// { type: "insert", value: " world" }]
|
|
287
|
+
|
|
288
|
+
const plain = Delta.insert([], "Hello");
|
|
289
|
+
const bold = Delta.insert([], "Hello", { bold: true });
|
|
290
|
+
|
|
291
|
+
Delta.diff(plain, bold);
|
|
292
|
+
// [{ type: "retain", value: 5, attributes: { bold: true } }]
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
```ts [data-last]
|
|
296
|
+
import { Delta } from "@monstermann/delta";
|
|
297
|
+
|
|
298
|
+
const a = Delta.insert([], "Hello");
|
|
299
|
+
const b = Delta.insert([], "Hello world");
|
|
300
|
+
|
|
301
|
+
pipe(a, Delta.diff(b));
|
|
302
|
+
// [{ type: "retain", value: 5 },
|
|
303
|
+
// { type: "insert", value: " world" }]
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
#### Cursor hint
|
|
307
|
+
|
|
308
|
+
When text changes are ambiguous, the cursor position determines where the change is placed:
|
|
309
|
+
|
|
310
|
+
```ts
|
|
311
|
+
import { Delta } from "@monstermann/delta";
|
|
312
|
+
|
|
313
|
+
const a = Delta.insert([], "foo");
|
|
314
|
+
const b = Delta.insert([], "foo bar foo");
|
|
315
|
+
|
|
316
|
+
// cursor=3: user typed " bar foo" at the end
|
|
317
|
+
Delta.diff(a, b, 3);
|
|
318
|
+
// [{ type: "retain", value: 3 },
|
|
319
|
+
// { type: "insert", value: " bar foo" }]
|
|
320
|
+
|
|
321
|
+
// cursor=0: user typed "foo bar " at the beginning
|
|
322
|
+
Delta.diff(a, b, 0);
|
|
323
|
+
// [{ type: "insert", value: "foo bar " }]
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### equals
|
|
327
|
+
|
|
328
|
+
```ts
|
|
329
|
+
function Delta.equals<T>(a: Delta<T>, b: Delta<T>): boolean
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
Checks if two deltas are equal by comparing their operations and attributes.
|
|
333
|
+
|
|
334
|
+
#### Example
|
|
335
|
+
|
|
336
|
+
```ts [data-first]
|
|
337
|
+
import { Delta } from "@monstermann/delta";
|
|
338
|
+
|
|
339
|
+
const a = Delta.insert([], "Hello", { bold: true });
|
|
340
|
+
const b = Delta.insert([], "Hello", { bold: true });
|
|
341
|
+
const c = Delta.insert([], "Hello", { italic: true });
|
|
342
|
+
|
|
343
|
+
Delta.equals(a, b); // true
|
|
344
|
+
Delta.equals(a, c); // false
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
```ts [data-last]
|
|
348
|
+
import { Delta } from "@monstermann/delta";
|
|
349
|
+
|
|
350
|
+
const a = Delta.insert([], "Hello", { bold: true });
|
|
351
|
+
const b = Delta.insert([], "Hello", { bold: true });
|
|
352
|
+
|
|
353
|
+
pipe(a, Delta.equals(b)); // true
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### insert
|
|
357
|
+
|
|
358
|
+
```ts
|
|
359
|
+
function Delta.insert<T>(
|
|
360
|
+
ops: Delta<T>,
|
|
361
|
+
content: string,
|
|
362
|
+
attributes?: T | null,
|
|
363
|
+
): Delta<T>
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
Adds an insert operation to the delta.
|
|
367
|
+
|
|
368
|
+
#### Example
|
|
369
|
+
|
|
370
|
+
```ts [data-first]
|
|
371
|
+
import { Delta } from "@monstermann/delta";
|
|
372
|
+
|
|
373
|
+
Delta.insert([], "Hello");
|
|
374
|
+
// [{ type: "insert", value: "Hello" }]
|
|
375
|
+
|
|
376
|
+
Delta.insert([], "Hello", { bold: true });
|
|
377
|
+
// [{ type: "insert", value: "Hello", attributes: { bold: true } }]
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
```ts [data-last]
|
|
381
|
+
import { Delta } from "@monstermann/delta";
|
|
382
|
+
|
|
383
|
+
pipe([], Delta.insert("Hello"));
|
|
384
|
+
// [{ type: "insert", value: "Hello" }]
|
|
385
|
+
|
|
386
|
+
pipe(
|
|
387
|
+
[],
|
|
388
|
+
Delta.insert("Hello", { bold: true }),
|
|
389
|
+
Delta.insert(" world", { italic: true }),
|
|
390
|
+
);
|
|
391
|
+
// [{ type: "insert", value: "Hello", attributes: { bold: true } },
|
|
392
|
+
// { type: "insert", value: " world", attributes: { italic: true } }]
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
### invert
|
|
396
|
+
|
|
397
|
+
```ts
|
|
398
|
+
function Delta.invert<T>(a: Delta<T>, b: Delta<T>): Delta<T>
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
Returns the inverse of a delta against a base document. Applying the inverted delta undoes the original change.
|
|
402
|
+
|
|
403
|
+
#### Example
|
|
404
|
+
|
|
405
|
+
<!-- prettier-ignore -->
|
|
406
|
+
```ts [data-first]
|
|
407
|
+
import { Delta } from "@monstermann/delta";
|
|
408
|
+
|
|
409
|
+
const base = Delta.insert([], "Hello");
|
|
410
|
+
const change = Delta.retain([], 5, { bold: true });
|
|
411
|
+
|
|
412
|
+
Delta.invert(change, base);
|
|
413
|
+
// [{ type: "retain", value: 5, attributes: { bold: null } }]
|
|
414
|
+
|
|
415
|
+
const insert = pipe(
|
|
416
|
+
[],
|
|
417
|
+
Delta.retain(5),
|
|
418
|
+
Delta.insert(" world")
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
Delta.invert(insert, base);
|
|
422
|
+
// [{ type: "retain", value: 5 },
|
|
423
|
+
// { type: "remove", value: 6 }]
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
```ts [data-last]
|
|
427
|
+
import { Delta } from "@monstermann/delta";
|
|
428
|
+
|
|
429
|
+
const base = Delta.insert([], "Hello");
|
|
430
|
+
const change = Delta.retain([], 5, { bold: true });
|
|
431
|
+
|
|
432
|
+
pipe(change, Delta.invert(base));
|
|
433
|
+
// [{ type: "retain", value: 5, attributes: { bold: null } }]
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### length
|
|
437
|
+
|
|
438
|
+
```ts
|
|
439
|
+
function Delta.length<T>(ops: Delta<T>): number
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
Returns the total length of the delta (sum of all operation lengths).
|
|
443
|
+
|
|
444
|
+
#### Example
|
|
445
|
+
|
|
446
|
+
<!-- prettier-ignore -->
|
|
447
|
+
```ts [data-first]
|
|
448
|
+
import { Delta } from "@monstermann/delta";
|
|
449
|
+
|
|
450
|
+
Delta.length(Delta.insert([], "Hello")); // 5
|
|
451
|
+
|
|
452
|
+
Delta.length(pipe(
|
|
453
|
+
[],
|
|
454
|
+
Delta.insert("Hello"),
|
|
455
|
+
Delta.retain(3),
|
|
456
|
+
Delta.remove(2)
|
|
457
|
+
)); // 10
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
```ts [data-last]
|
|
461
|
+
import { Delta } from "@monstermann/delta";
|
|
462
|
+
|
|
463
|
+
pipe([], Delta.insert("Hello"), Delta.length()); // 5
|
|
464
|
+
|
|
465
|
+
pipe(
|
|
466
|
+
[],
|
|
467
|
+
Delta.insert("Hello"),
|
|
468
|
+
Delta.retain(3),
|
|
469
|
+
Delta.remove(2),
|
|
470
|
+
Delta.length(),
|
|
471
|
+
); // 10
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
### push
|
|
475
|
+
|
|
476
|
+
```ts
|
|
477
|
+
function Delta.push<T>(ops: Delta<T>, op: Op<T>): Delta<T>
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
Pushes an operation onto the delta, merging with the previous operation if possible.
|
|
481
|
+
|
|
482
|
+
#### Example
|
|
483
|
+
|
|
484
|
+
```ts [data-first]
|
|
485
|
+
import { Delta } from "@monstermann/delta";
|
|
486
|
+
|
|
487
|
+
Delta.push([], { type: "insert", value: "Hello" });
|
|
488
|
+
// [{ type: "insert", value: "Hello" }]
|
|
489
|
+
|
|
490
|
+
Delta.push(Delta.push([], { type: "insert", value: "Hello" }), {
|
|
491
|
+
type: "insert",
|
|
492
|
+
value: " world",
|
|
493
|
+
});
|
|
494
|
+
// [{ type: "insert", value: "Hello world" }]
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
```ts [data-last]
|
|
498
|
+
import { Delta } from "@monstermann/delta";
|
|
499
|
+
|
|
500
|
+
pipe([], Delta.push({ type: "insert", value: "Hello" }));
|
|
501
|
+
// [{ type: "insert", value: "Hello" }]
|
|
502
|
+
|
|
503
|
+
pipe(
|
|
504
|
+
[],
|
|
505
|
+
Delta.push({ type: "insert", value: "Hello" }),
|
|
506
|
+
Delta.push({ type: "insert", value: " world" }),
|
|
507
|
+
);
|
|
508
|
+
// [{ type: "insert", value: "Hello world" }]
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
### remove
|
|
512
|
+
|
|
513
|
+
```ts
|
|
514
|
+
function Delta.remove<T>(ops: Delta<T>, length: number): Delta<T>
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
Adds a remove operation to the delta.
|
|
518
|
+
|
|
519
|
+
#### Example
|
|
520
|
+
|
|
521
|
+
```ts [data-first]
|
|
522
|
+
import { Delta } from "@monstermann/delta";
|
|
523
|
+
|
|
524
|
+
Delta.remove([], 5);
|
|
525
|
+
// [{ type: "remove", value: 5 }]
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
```ts [data-last]
|
|
529
|
+
import { Delta } from "@monstermann/delta";
|
|
530
|
+
|
|
531
|
+
pipe([], Delta.remove(5));
|
|
532
|
+
// [{ type: "remove", value: 5 }]
|
|
533
|
+
|
|
534
|
+
pipe([], Delta.retain(3), Delta.remove(5));
|
|
535
|
+
// [{ type: "retain", value: 3 },
|
|
536
|
+
// { type: "remove", value: 5 }]
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
### retain
|
|
540
|
+
|
|
541
|
+
```ts
|
|
542
|
+
function Delta.retain<T>(
|
|
543
|
+
ops: Delta<T>,
|
|
544
|
+
length: number,
|
|
545
|
+
attributes?: T | null,
|
|
546
|
+
): Delta<T>
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
Adds a retain operation to the delta, optionally with attributes to apply formatting.
|
|
550
|
+
|
|
551
|
+
#### Example
|
|
552
|
+
|
|
553
|
+
```ts [data-first]
|
|
554
|
+
import { Delta } from "@monstermann/delta";
|
|
555
|
+
|
|
556
|
+
Delta.retain([], 5);
|
|
557
|
+
// [{ type: "retain", value: 5 }]
|
|
558
|
+
|
|
559
|
+
Delta.retain([], 5, { bold: true });
|
|
560
|
+
// [{ type: "retain", value: 5, attributes: { bold: true } }]
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
<!-- prettier-ignore -->
|
|
564
|
+
```ts [data-last]
|
|
565
|
+
import { Delta } from "@monstermann/delta";
|
|
566
|
+
|
|
567
|
+
pipe([], Delta.retain(5));
|
|
568
|
+
// [{ type: "retain", value: 5 }]
|
|
569
|
+
|
|
570
|
+
pipe(
|
|
571
|
+
[],
|
|
572
|
+
Delta.retain(3),
|
|
573
|
+
Delta.retain(2, { italic: true })
|
|
574
|
+
);
|
|
575
|
+
// [{ type: "retain", value: 3 },
|
|
576
|
+
// { type: "retain", value: 2, attributes: { italic: true } }]
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
#### Removing attributes
|
|
580
|
+
|
|
581
|
+
Use `null` to remove an attribute when composing deltas:
|
|
582
|
+
|
|
583
|
+
```ts
|
|
584
|
+
import { Delta } from "@monstermann/delta";
|
|
585
|
+
|
|
586
|
+
const doc = Delta.insert([], "Hello", { bold: true });
|
|
587
|
+
// [{ type: "insert", value: "Hello", attributes: { bold: true } }]
|
|
588
|
+
|
|
589
|
+
const removeBold = Delta.retain([], 5, { bold: null });
|
|
590
|
+
// [{ type: "retain", value: 5, attributes: { bold: null } }]
|
|
591
|
+
|
|
592
|
+
Delta.compose(doc, removeBold);
|
|
593
|
+
// [{ type: "insert", value: "Hello" }]
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
### slice
|
|
597
|
+
|
|
598
|
+
```ts
|
|
599
|
+
function Delta.slice<T>(ops: Delta<T>, start: number, end?: number): Delta<T>
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
Returns a portion of the delta from `start` to `end`.
|
|
603
|
+
|
|
604
|
+
#### Example
|
|
605
|
+
|
|
606
|
+
```ts [data-first]
|
|
607
|
+
import { Delta } from "@monstermann/delta";
|
|
608
|
+
|
|
609
|
+
const delta = Delta.insert([], "Hello world");
|
|
610
|
+
|
|
611
|
+
Delta.slice(delta, 0, 5);
|
|
612
|
+
// [{ type: "insert", value: "Hello" }]
|
|
613
|
+
|
|
614
|
+
Delta.slice(delta, 6);
|
|
615
|
+
// [{ type: "insert", value: "world" }]
|
|
616
|
+
|
|
617
|
+
const formatted = pipe(
|
|
618
|
+
[],
|
|
619
|
+
Delta.insert("Hello", { bold: true }),
|
|
620
|
+
Delta.insert(" world", { italic: true }),
|
|
621
|
+
);
|
|
622
|
+
|
|
623
|
+
Delta.slice(formatted, 3, 8);
|
|
624
|
+
// [{ type: "insert", value: "lo", attributes: { bold: true } },
|
|
625
|
+
// { type: "insert", value: " wo", attributes: { italic: true } }]
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
<!-- prettier-ignore -->
|
|
629
|
+
```ts [data-last]
|
|
630
|
+
import { Delta } from "@monstermann/delta";
|
|
631
|
+
|
|
632
|
+
pipe(
|
|
633
|
+
[],
|
|
634
|
+
Delta.insert("Hello world"),
|
|
635
|
+
Delta.slice(0, 5)
|
|
636
|
+
);
|
|
637
|
+
// [{ type: "insert", value: "Hello" }]
|
|
638
|
+
|
|
639
|
+
pipe(
|
|
640
|
+
[],
|
|
641
|
+
Delta.insert("Hello world"),
|
|
642
|
+
Delta.slice(6)
|
|
643
|
+
);
|
|
644
|
+
// [{ type: "insert", value: "world" }]
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
### transform
|
|
648
|
+
|
|
649
|
+
```ts
|
|
650
|
+
function Delta.transform<T>(
|
|
651
|
+
a: Delta<T>,
|
|
652
|
+
b: Delta<T>,
|
|
653
|
+
priority?: boolean,
|
|
654
|
+
): Delta<T>
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
Transforms delta `b` to account for delta `a` having been applied first. When both deltas insert at the same position, `priority` determines which insert comes first.
|
|
658
|
+
|
|
659
|
+
#### Example
|
|
660
|
+
|
|
661
|
+
<!-- prettier-ignore -->
|
|
662
|
+
```ts [data-first]
|
|
663
|
+
import { Delta } from "@monstermann/delta";
|
|
664
|
+
|
|
665
|
+
const a = Delta.insert([], "Hello");
|
|
666
|
+
const b = Delta.insert([], "World");
|
|
667
|
+
|
|
668
|
+
Delta.transform(a, b, true);
|
|
669
|
+
// [{ type: "retain", value: 5 },
|
|
670
|
+
// { type: "insert", value: "World" }]
|
|
671
|
+
|
|
672
|
+
Delta.transform(a, b, false);
|
|
673
|
+
// [{ type: "insert", value: "World" }]
|
|
674
|
+
|
|
675
|
+
const format = Delta.retain([], 5, { bold: true });
|
|
676
|
+
const insert = pipe(
|
|
677
|
+
[],
|
|
678
|
+
Delta.retain(2),
|
|
679
|
+
Delta.insert("XXX")
|
|
680
|
+
);
|
|
681
|
+
|
|
682
|
+
Delta.transform(insert, format);
|
|
683
|
+
// [{ type: "retain", value: 8, attributes: { bold: true } }]
|
|
684
|
+
```
|
|
685
|
+
|
|
686
|
+
```ts [data-last]
|
|
687
|
+
import { Delta } from "@monstermann/delta";
|
|
688
|
+
|
|
689
|
+
const a = Delta.insert([], "Hello");
|
|
690
|
+
const b = Delta.insert([], "World");
|
|
691
|
+
|
|
692
|
+
pipe(a, Delta.transform(b, true));
|
|
693
|
+
// [{ type: "retain", value: 5 },
|
|
694
|
+
// { type: "insert", value: "World" }]
|
|
695
|
+
```
|