@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
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { isEqual } from "../OpAttributes/isEqual.mjs";
|
|
2
|
+
import { dfdlT } from "@monstermann/dfdl";
|
|
3
|
+
import { cloneArray, endMutations, startMutations } from "@monstermann/remmi";
|
|
4
|
+
|
|
5
|
+
//#region src/Delta/push.ts
|
|
6
|
+
/**
|
|
7
|
+
* # push
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* function Delta.push<T>(ops: Delta<T>, op: Op<T>): Delta<T>
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* Pushes an operation onto the delta, merging with the previous operation if possible.
|
|
14
|
+
*
|
|
15
|
+
* ## Example
|
|
16
|
+
*
|
|
17
|
+
* ```ts [data-first]
|
|
18
|
+
* import { Delta } from "@monstermann/delta";
|
|
19
|
+
*
|
|
20
|
+
* Delta.push([], { type: "insert", value: "Hello" });
|
|
21
|
+
* // [{ type: "insert", value: "Hello" }]
|
|
22
|
+
*
|
|
23
|
+
* Delta.push(Delta.push([], { type: "insert", value: "Hello" }), {
|
|
24
|
+
* type: "insert",
|
|
25
|
+
* value: " world",
|
|
26
|
+
* });
|
|
27
|
+
* // [{ type: "insert", value: "Hello world" }]
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* ```ts [data-last]
|
|
31
|
+
* import { Delta } from "@monstermann/delta";
|
|
32
|
+
*
|
|
33
|
+
* pipe([], Delta.push({ type: "insert", value: "Hello" }));
|
|
34
|
+
* // [{ type: "insert", value: "Hello" }]
|
|
35
|
+
*
|
|
36
|
+
* pipe(
|
|
37
|
+
* [],
|
|
38
|
+
* Delta.push({ type: "insert", value: "Hello" }),
|
|
39
|
+
* Delta.push({ type: "insert", value: " world" }),
|
|
40
|
+
* );
|
|
41
|
+
* // [{ type: "insert", value: "Hello world" }]
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
*/
|
|
45
|
+
const push = dfdlT((ops, op) => {
|
|
46
|
+
if (!ops.length) return [op];
|
|
47
|
+
const length = ops.length;
|
|
48
|
+
const lastOp = ops[length - 1];
|
|
49
|
+
let copy = cloneArray(ops);
|
|
50
|
+
if (lastOp.type === "remove" && op.type === "remove") {
|
|
51
|
+
copy[length - 1] = {
|
|
52
|
+
attributes: void 0,
|
|
53
|
+
type: "remove",
|
|
54
|
+
value: lastOp.value + op.value
|
|
55
|
+
};
|
|
56
|
+
return copy;
|
|
57
|
+
}
|
|
58
|
+
if (lastOp.type === "remove" && op.type === "insert") {
|
|
59
|
+
startMutations();
|
|
60
|
+
copy.pop();
|
|
61
|
+
copy = push(copy, op);
|
|
62
|
+
copy.push(lastOp);
|
|
63
|
+
endMutations();
|
|
64
|
+
return copy;
|
|
65
|
+
}
|
|
66
|
+
if (lastOp.type === "insert" && op.type === "insert" && isEqual(lastOp.attributes, op.attributes)) {
|
|
67
|
+
copy[length - 1] = {
|
|
68
|
+
attributes: op.attributes,
|
|
69
|
+
type: "insert",
|
|
70
|
+
value: lastOp.value + op.value
|
|
71
|
+
};
|
|
72
|
+
return copy;
|
|
73
|
+
}
|
|
74
|
+
if (lastOp.type === "retain" && op.type === "retain" && isEqual(lastOp.attributes, op.attributes)) {
|
|
75
|
+
copy[length - 1] = {
|
|
76
|
+
attributes: op.attributes,
|
|
77
|
+
type: "retain",
|
|
78
|
+
value: lastOp.value + op.value
|
|
79
|
+
};
|
|
80
|
+
return copy;
|
|
81
|
+
}
|
|
82
|
+
copy.push(op);
|
|
83
|
+
return copy;
|
|
84
|
+
}, 2);
|
|
85
|
+
|
|
86
|
+
//#endregion
|
|
87
|
+
export { push };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { OpAttributes } from "../OpAttributes/index.mjs";
|
|
2
|
+
import { Delta } from "./index.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/Delta/remove.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* # remove
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* function Delta.remove<T>(ops: Delta<T>, length: number): Delta<T>
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* Adds a remove operation to the delta.
|
|
14
|
+
*
|
|
15
|
+
* ## Example
|
|
16
|
+
*
|
|
17
|
+
* ```ts [data-first]
|
|
18
|
+
* import { Delta } from "@monstermann/delta";
|
|
19
|
+
*
|
|
20
|
+
* Delta.remove([], 5);
|
|
21
|
+
* // [{ type: "remove", value: 5 }]
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* ```ts [data-last]
|
|
25
|
+
* import { Delta } from "@monstermann/delta";
|
|
26
|
+
*
|
|
27
|
+
* pipe([], Delta.remove(5));
|
|
28
|
+
* // [{ type: "remove", value: 5 }]
|
|
29
|
+
*
|
|
30
|
+
* pipe([], Delta.retain(3), Delta.remove(5));
|
|
31
|
+
* // [{ type: "retain", value: 3 },
|
|
32
|
+
* // { type: "remove", value: 5 }]
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
*/
|
|
36
|
+
declare const remove: {
|
|
37
|
+
<T extends OpAttributes>(length: number): (ops: Delta<T>) => Delta<T>;
|
|
38
|
+
<T extends OpAttributes>(ops: Delta<T>, length: number): Delta<T>;
|
|
39
|
+
};
|
|
40
|
+
//#endregion
|
|
41
|
+
export { remove };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { push } from "./push.mjs";
|
|
2
|
+
import { dfdlT } from "@monstermann/dfdl";
|
|
3
|
+
|
|
4
|
+
//#region src/Delta/remove.ts
|
|
5
|
+
/**
|
|
6
|
+
* # remove
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* function Delta.remove<T>(ops: Delta<T>, length: number): Delta<T>
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* Adds a remove operation to the delta.
|
|
13
|
+
*
|
|
14
|
+
* ## Example
|
|
15
|
+
*
|
|
16
|
+
* ```ts [data-first]
|
|
17
|
+
* import { Delta } from "@monstermann/delta";
|
|
18
|
+
*
|
|
19
|
+
* Delta.remove([], 5);
|
|
20
|
+
* // [{ type: "remove", value: 5 }]
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* ```ts [data-last]
|
|
24
|
+
* import { Delta } from "@monstermann/delta";
|
|
25
|
+
*
|
|
26
|
+
* pipe([], Delta.remove(5));
|
|
27
|
+
* // [{ type: "remove", value: 5 }]
|
|
28
|
+
*
|
|
29
|
+
* pipe([], Delta.retain(3), Delta.remove(5));
|
|
30
|
+
* // [{ type: "retain", value: 3 },
|
|
31
|
+
* // { type: "remove", value: 5 }]
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
*/
|
|
35
|
+
const remove = dfdlT((ops, length) => {
|
|
36
|
+
if (!Number.isInteger(length)) return ops;
|
|
37
|
+
if (length <= 0) return ops;
|
|
38
|
+
return push(ops, {
|
|
39
|
+
attributes: void 0,
|
|
40
|
+
type: "remove",
|
|
41
|
+
value: length
|
|
42
|
+
});
|
|
43
|
+
}, 2);
|
|
44
|
+
|
|
45
|
+
//#endregion
|
|
46
|
+
export { remove };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { NullableOpAttributes, OpAttributes } from "../OpAttributes/index.mjs";
|
|
2
|
+
import { Delta } from "./index.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/Delta/retain.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* # retain
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* function Delta.retain<T>(
|
|
11
|
+
* ops: Delta<T>,
|
|
12
|
+
* length: number,
|
|
13
|
+
* attributes?: T | null,
|
|
14
|
+
* ): Delta<T>
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* Adds a retain operation to the delta, optionally with attributes to apply formatting.
|
|
18
|
+
*
|
|
19
|
+
* ## Example
|
|
20
|
+
*
|
|
21
|
+
* ```ts [data-first]
|
|
22
|
+
* import { Delta } from "@monstermann/delta";
|
|
23
|
+
*
|
|
24
|
+
* Delta.retain([], 5);
|
|
25
|
+
* // [{ type: "retain", value: 5 }]
|
|
26
|
+
*
|
|
27
|
+
* Delta.retain([], 5, { bold: true });
|
|
28
|
+
* // [{ type: "retain", value: 5, attributes: { bold: true } }]
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* <!-- prettier-ignore -->
|
|
32
|
+
* ```ts [data-last]
|
|
33
|
+
* import { Delta } from "@monstermann/delta";
|
|
34
|
+
*
|
|
35
|
+
* pipe([], Delta.retain(5));
|
|
36
|
+
* // [{ type: "retain", value: 5 }]
|
|
37
|
+
*
|
|
38
|
+
* pipe(
|
|
39
|
+
* [],
|
|
40
|
+
* Delta.retain(3),
|
|
41
|
+
* Delta.retain(2, { italic: true })
|
|
42
|
+
* );
|
|
43
|
+
* // [{ type: "retain", value: 3 },
|
|
44
|
+
* // { type: "retain", value: 2, attributes: { italic: true } }]
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* ## Removing attributes
|
|
48
|
+
*
|
|
49
|
+
* Use `null` to remove an attribute when composing deltas:
|
|
50
|
+
*
|
|
51
|
+
* ```ts
|
|
52
|
+
* import { Delta } from "@monstermann/delta";
|
|
53
|
+
*
|
|
54
|
+
* const doc = Delta.insert([], "Hello", { bold: true });
|
|
55
|
+
* // [{ type: "insert", value: "Hello", attributes: { bold: true } }]
|
|
56
|
+
*
|
|
57
|
+
* const removeBold = Delta.retain([], 5, { bold: null });
|
|
58
|
+
* // [{ type: "retain", value: 5, attributes: { bold: null } }]
|
|
59
|
+
*
|
|
60
|
+
* Delta.compose(doc, removeBold);
|
|
61
|
+
* // [{ type: "insert", value: "Hello" }]
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
*/
|
|
65
|
+
declare const retain: {
|
|
66
|
+
<T extends OpAttributes>(length: number, attributes?: NullableOpAttributes<NoInfer<T>> | null): (ops: Delta<T>) => Delta<T>;
|
|
67
|
+
<T extends OpAttributes>(ops: Delta<T>, length: number, attributes?: NullableOpAttributes<NoInfer<T>> | null): Delta<T>;
|
|
68
|
+
};
|
|
69
|
+
//#endregion
|
|
70
|
+
export { retain };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { push } from "./push.mjs";
|
|
2
|
+
import { hasKeys } from "../internals/hasKeys.mjs";
|
|
3
|
+
import { dfdlT } from "@monstermann/dfdl";
|
|
4
|
+
|
|
5
|
+
//#region src/Delta/retain.ts
|
|
6
|
+
/**
|
|
7
|
+
* # retain
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* function Delta.retain<T>(
|
|
11
|
+
* ops: Delta<T>,
|
|
12
|
+
* length: number,
|
|
13
|
+
* attributes?: T | null,
|
|
14
|
+
* ): Delta<T>
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* Adds a retain operation to the delta, optionally with attributes to apply formatting.
|
|
18
|
+
*
|
|
19
|
+
* ## Example
|
|
20
|
+
*
|
|
21
|
+
* ```ts [data-first]
|
|
22
|
+
* import { Delta } from "@monstermann/delta";
|
|
23
|
+
*
|
|
24
|
+
* Delta.retain([], 5);
|
|
25
|
+
* // [{ type: "retain", value: 5 }]
|
|
26
|
+
*
|
|
27
|
+
* Delta.retain([], 5, { bold: true });
|
|
28
|
+
* // [{ type: "retain", value: 5, attributes: { bold: true } }]
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* <!-- prettier-ignore -->
|
|
32
|
+
* ```ts [data-last]
|
|
33
|
+
* import { Delta } from "@monstermann/delta";
|
|
34
|
+
*
|
|
35
|
+
* pipe([], Delta.retain(5));
|
|
36
|
+
* // [{ type: "retain", value: 5 }]
|
|
37
|
+
*
|
|
38
|
+
* pipe(
|
|
39
|
+
* [],
|
|
40
|
+
* Delta.retain(3),
|
|
41
|
+
* Delta.retain(2, { italic: true })
|
|
42
|
+
* );
|
|
43
|
+
* // [{ type: "retain", value: 3 },
|
|
44
|
+
* // { type: "retain", value: 2, attributes: { italic: true } }]
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* ## Removing attributes
|
|
48
|
+
*
|
|
49
|
+
* Use `null` to remove an attribute when composing deltas:
|
|
50
|
+
*
|
|
51
|
+
* ```ts
|
|
52
|
+
* import { Delta } from "@monstermann/delta";
|
|
53
|
+
*
|
|
54
|
+
* const doc = Delta.insert([], "Hello", { bold: true });
|
|
55
|
+
* // [{ type: "insert", value: "Hello", attributes: { bold: true } }]
|
|
56
|
+
*
|
|
57
|
+
* const removeBold = Delta.retain([], 5, { bold: null });
|
|
58
|
+
* // [{ type: "retain", value: 5, attributes: { bold: null } }]
|
|
59
|
+
*
|
|
60
|
+
* Delta.compose(doc, removeBold);
|
|
61
|
+
* // [{ type: "insert", value: "Hello" }]
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
*/
|
|
65
|
+
const retain = dfdlT((ops, length, attributes) => {
|
|
66
|
+
if (!Number.isInteger(length)) return ops;
|
|
67
|
+
if (length <= 0) return ops;
|
|
68
|
+
return push(ops, {
|
|
69
|
+
attributes: attributes && hasKeys(attributes) ? attributes : void 0,
|
|
70
|
+
type: "retain",
|
|
71
|
+
value: length
|
|
72
|
+
});
|
|
73
|
+
}, (args) => typeof args[0] !== "number");
|
|
74
|
+
|
|
75
|
+
//#endregion
|
|
76
|
+
export { retain };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { OpAttributes } from "../OpAttributes/index.mjs";
|
|
2
|
+
import { Delta } from "./index.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/Delta/slice.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* # slice
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* function Delta.slice<T>(ops: Delta<T>, start: number, end?: number): Delta<T>
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* Returns a portion of the delta from `start` to `end`.
|
|
14
|
+
*
|
|
15
|
+
* ## Example
|
|
16
|
+
*
|
|
17
|
+
* ```ts [data-first]
|
|
18
|
+
* import { Delta } from "@monstermann/delta";
|
|
19
|
+
*
|
|
20
|
+
* const delta = Delta.insert([], "Hello world");
|
|
21
|
+
*
|
|
22
|
+
* Delta.slice(delta, 0, 5);
|
|
23
|
+
* // [{ type: "insert", value: "Hello" }]
|
|
24
|
+
*
|
|
25
|
+
* Delta.slice(delta, 6);
|
|
26
|
+
* // [{ type: "insert", value: "world" }]
|
|
27
|
+
*
|
|
28
|
+
* const formatted = pipe(
|
|
29
|
+
* [],
|
|
30
|
+
* Delta.insert("Hello", { bold: true }),
|
|
31
|
+
* Delta.insert(" world", { italic: true }),
|
|
32
|
+
* );
|
|
33
|
+
*
|
|
34
|
+
* Delta.slice(formatted, 3, 8);
|
|
35
|
+
* // [{ type: "insert", value: "lo", attributes: { bold: true } },
|
|
36
|
+
* // { type: "insert", value: " wo", attributes: { italic: true } }]
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* <!-- prettier-ignore -->
|
|
40
|
+
* ```ts [data-last]
|
|
41
|
+
* import { Delta } from "@monstermann/delta";
|
|
42
|
+
*
|
|
43
|
+
* pipe(
|
|
44
|
+
* [],
|
|
45
|
+
* Delta.insert("Hello world"),
|
|
46
|
+
* Delta.slice(0, 5)
|
|
47
|
+
* );
|
|
48
|
+
* // [{ type: "insert", value: "Hello" }]
|
|
49
|
+
*
|
|
50
|
+
* pipe(
|
|
51
|
+
* [],
|
|
52
|
+
* Delta.insert("Hello world"),
|
|
53
|
+
* Delta.slice(6)
|
|
54
|
+
* );
|
|
55
|
+
* // [{ type: "insert", value: "world" }]
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
*/
|
|
59
|
+
declare const slice: {
|
|
60
|
+
(start: number, end?: number): <T extends OpAttributes>(ops: Delta<T>) => Delta<T>;
|
|
61
|
+
<T extends OpAttributes>(ops: Delta<T>, start: number, end?: number): Delta<T>;
|
|
62
|
+
};
|
|
63
|
+
//#endregion
|
|
64
|
+
export { slice };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { create } from "../OpIterator/create.mjs";
|
|
2
|
+
import { next } from "../OpIterator/next.mjs";
|
|
3
|
+
import { hasNext } from "../OpIterator/hasNext.mjs";
|
|
4
|
+
import { dfdlT } from "@monstermann/dfdl";
|
|
5
|
+
|
|
6
|
+
//#region src/Delta/slice.ts
|
|
7
|
+
/**
|
|
8
|
+
* # slice
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* function Delta.slice<T>(ops: Delta<T>, start: number, end?: number): Delta<T>
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* Returns a portion of the delta from `start` to `end`.
|
|
15
|
+
*
|
|
16
|
+
* ## Example
|
|
17
|
+
*
|
|
18
|
+
* ```ts [data-first]
|
|
19
|
+
* import { Delta } from "@monstermann/delta";
|
|
20
|
+
*
|
|
21
|
+
* const delta = Delta.insert([], "Hello world");
|
|
22
|
+
*
|
|
23
|
+
* Delta.slice(delta, 0, 5);
|
|
24
|
+
* // [{ type: "insert", value: "Hello" }]
|
|
25
|
+
*
|
|
26
|
+
* Delta.slice(delta, 6);
|
|
27
|
+
* // [{ type: "insert", value: "world" }]
|
|
28
|
+
*
|
|
29
|
+
* const formatted = pipe(
|
|
30
|
+
* [],
|
|
31
|
+
* Delta.insert("Hello", { bold: true }),
|
|
32
|
+
* Delta.insert(" world", { italic: true }),
|
|
33
|
+
* );
|
|
34
|
+
*
|
|
35
|
+
* Delta.slice(formatted, 3, 8);
|
|
36
|
+
* // [{ type: "insert", value: "lo", attributes: { bold: true } },
|
|
37
|
+
* // { type: "insert", value: " wo", attributes: { italic: true } }]
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* <!-- prettier-ignore -->
|
|
41
|
+
* ```ts [data-last]
|
|
42
|
+
* import { Delta } from "@monstermann/delta";
|
|
43
|
+
*
|
|
44
|
+
* pipe(
|
|
45
|
+
* [],
|
|
46
|
+
* Delta.insert("Hello world"),
|
|
47
|
+
* Delta.slice(0, 5)
|
|
48
|
+
* );
|
|
49
|
+
* // [{ type: "insert", value: "Hello" }]
|
|
50
|
+
*
|
|
51
|
+
* pipe(
|
|
52
|
+
* [],
|
|
53
|
+
* Delta.insert("Hello world"),
|
|
54
|
+
* Delta.slice(6)
|
|
55
|
+
* );
|
|
56
|
+
* // [{ type: "insert", value: "world" }]
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
*/
|
|
60
|
+
const slice = dfdlT((ops, start, end = Infinity) => {
|
|
61
|
+
const newOps = [];
|
|
62
|
+
const iter = create(ops);
|
|
63
|
+
let index = 0;
|
|
64
|
+
while (index < end && hasNext(iter)) {
|
|
65
|
+
let nextOp;
|
|
66
|
+
if (index < start) nextOp = next(iter, start - index);
|
|
67
|
+
else {
|
|
68
|
+
nextOp = next(iter, end - index);
|
|
69
|
+
newOps.push(nextOp);
|
|
70
|
+
}
|
|
71
|
+
index += nextOp.type === "insert" ? nextOp.value.length : nextOp.value;
|
|
72
|
+
}
|
|
73
|
+
return newOps;
|
|
74
|
+
}, (args) => typeof args[0] !== "number");
|
|
75
|
+
|
|
76
|
+
//#endregion
|
|
77
|
+
export { slice };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { OpAttributes } from "../OpAttributes/index.mjs";
|
|
2
|
+
import { Delta } from "./index.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/Delta/transform.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* # transform
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* function Delta.transform<T>(
|
|
11
|
+
* a: Delta<T>,
|
|
12
|
+
* b: Delta<T>,
|
|
13
|
+
* priority?: boolean,
|
|
14
|
+
* ): Delta<T>
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* 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.
|
|
18
|
+
*
|
|
19
|
+
* ## Example
|
|
20
|
+
*
|
|
21
|
+
* <!-- prettier-ignore -->
|
|
22
|
+
* ```ts [data-first]
|
|
23
|
+
* import { Delta } from "@monstermann/delta";
|
|
24
|
+
*
|
|
25
|
+
* const a = Delta.insert([], "Hello");
|
|
26
|
+
* const b = Delta.insert([], "World");
|
|
27
|
+
*
|
|
28
|
+
* Delta.transform(a, b, true);
|
|
29
|
+
* // [{ type: "retain", value: 5 },
|
|
30
|
+
* // { type: "insert", value: "World" }]
|
|
31
|
+
*
|
|
32
|
+
* Delta.transform(a, b, false);
|
|
33
|
+
* // [{ type: "insert", value: "World" }]
|
|
34
|
+
*
|
|
35
|
+
* const format = Delta.retain([], 5, { bold: true });
|
|
36
|
+
* const insert = pipe(
|
|
37
|
+
* [],
|
|
38
|
+
* Delta.retain(2),
|
|
39
|
+
* Delta.insert("XXX")
|
|
40
|
+
* );
|
|
41
|
+
*
|
|
42
|
+
* Delta.transform(insert, format);
|
|
43
|
+
* // [{ type: "retain", value: 8, attributes: { bold: true } }]
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* ```ts [data-last]
|
|
47
|
+
* import { Delta } from "@monstermann/delta";
|
|
48
|
+
*
|
|
49
|
+
* const a = Delta.insert([], "Hello");
|
|
50
|
+
* const b = Delta.insert([], "World");
|
|
51
|
+
*
|
|
52
|
+
* pipe(a, Delta.transform(b, true));
|
|
53
|
+
* // [{ type: "retain", value: 5 },
|
|
54
|
+
* // { type: "insert", value: "World" }]
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
*/
|
|
58
|
+
declare const transform: {
|
|
59
|
+
<T extends OpAttributes>(b: Delta<NoInfer<T>>, priority?: boolean): (a: Delta<T>) => Delta<T>;
|
|
60
|
+
<T extends OpAttributes>(a: Delta<T>, b: Delta<NoInfer<T>>, priority?: boolean): Delta<T>;
|
|
61
|
+
};
|
|
62
|
+
//#endregion
|
|
63
|
+
export { transform };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { chop } from "./chop.mjs";
|
|
2
|
+
import { push } from "./push.mjs";
|
|
3
|
+
import { create } from "../OpIterator/create.mjs";
|
|
4
|
+
import { peekType } from "../OpIterator/peekType.mjs";
|
|
5
|
+
import { peekLength } from "../OpIterator/peekLength.mjs";
|
|
6
|
+
import { next } from "../OpIterator/next.mjs";
|
|
7
|
+
import { hasNext } from "../OpIterator/hasNext.mjs";
|
|
8
|
+
import { retain } from "./retain.mjs";
|
|
9
|
+
import { transform as transform$1 } from "../OpAttributes/transform.mjs";
|
|
10
|
+
import { dfdlT } from "@monstermann/dfdl";
|
|
11
|
+
import { endMutations, markAsMutable, startMutations } from "@monstermann/remmi";
|
|
12
|
+
|
|
13
|
+
//#region src/Delta/transform.ts
|
|
14
|
+
/**
|
|
15
|
+
* # transform
|
|
16
|
+
*
|
|
17
|
+
* ```ts
|
|
18
|
+
* function Delta.transform<T>(
|
|
19
|
+
* a: Delta<T>,
|
|
20
|
+
* b: Delta<T>,
|
|
21
|
+
* priority?: boolean,
|
|
22
|
+
* ): Delta<T>
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* 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.
|
|
26
|
+
*
|
|
27
|
+
* ## Example
|
|
28
|
+
*
|
|
29
|
+
* <!-- prettier-ignore -->
|
|
30
|
+
* ```ts [data-first]
|
|
31
|
+
* import { Delta } from "@monstermann/delta";
|
|
32
|
+
*
|
|
33
|
+
* const a = Delta.insert([], "Hello");
|
|
34
|
+
* const b = Delta.insert([], "World");
|
|
35
|
+
*
|
|
36
|
+
* Delta.transform(a, b, true);
|
|
37
|
+
* // [{ type: "retain", value: 5 },
|
|
38
|
+
* // { type: "insert", value: "World" }]
|
|
39
|
+
*
|
|
40
|
+
* Delta.transform(a, b, false);
|
|
41
|
+
* // [{ type: "insert", value: "World" }]
|
|
42
|
+
*
|
|
43
|
+
* const format = Delta.retain([], 5, { bold: true });
|
|
44
|
+
* const insert = pipe(
|
|
45
|
+
* [],
|
|
46
|
+
* Delta.retain(2),
|
|
47
|
+
* Delta.insert("XXX")
|
|
48
|
+
* );
|
|
49
|
+
*
|
|
50
|
+
* Delta.transform(insert, format);
|
|
51
|
+
* // [{ type: "retain", value: 8, attributes: { bold: true } }]
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* ```ts [data-last]
|
|
55
|
+
* import { Delta } from "@monstermann/delta";
|
|
56
|
+
*
|
|
57
|
+
* const a = Delta.insert([], "Hello");
|
|
58
|
+
* const b = Delta.insert([], "World");
|
|
59
|
+
*
|
|
60
|
+
* pipe(a, Delta.transform(b, true));
|
|
61
|
+
* // [{ type: "retain", value: 5 },
|
|
62
|
+
* // { type: "insert", value: "World" }]
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
*/
|
|
66
|
+
const transform = dfdlT((a, b, priority = false) => {
|
|
67
|
+
const aIter = create(a);
|
|
68
|
+
const bIter = create(b);
|
|
69
|
+
startMutations();
|
|
70
|
+
let ops = markAsMutable([]);
|
|
71
|
+
while (hasNext(aIter) || hasNext(bIter)) if (peekType(aIter) === "insert" && (priority || peekType(bIter) !== "insert")) {
|
|
72
|
+
const aOp = next(aIter);
|
|
73
|
+
ops = retain(ops, aOp.value.length);
|
|
74
|
+
} else if (peekType(bIter) === "insert") ops = push(ops, next(bIter));
|
|
75
|
+
else {
|
|
76
|
+
const length = Math.min(peekLength(aIter), peekLength(bIter));
|
|
77
|
+
const aOp = next(aIter, length);
|
|
78
|
+
const bOp = next(bIter, length);
|
|
79
|
+
if (aOp.type === "remove") continue;
|
|
80
|
+
if (bOp.type === "remove") ops = push(ops, bOp);
|
|
81
|
+
else ops = retain(ops, length, transform$1(aOp.attributes, bOp.attributes, priority));
|
|
82
|
+
}
|
|
83
|
+
ops = chop(ops);
|
|
84
|
+
endMutations();
|
|
85
|
+
return ops;
|
|
86
|
+
}, (args) => {
|
|
87
|
+
return Array.isArray(args[0]) && Array.isArray(args[1]);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
//#endregion
|
|
91
|
+
export { transform };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { NullableOpAttributes, OpAttributes } from "../OpAttributes/index.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/Op/index.d.ts
|
|
4
|
+
type InsertOp<T extends OpAttributes> = {
|
|
5
|
+
attributes: NullableOpAttributes<T> | undefined;
|
|
6
|
+
type: "insert";
|
|
7
|
+
value: string;
|
|
8
|
+
};
|
|
9
|
+
type RetainOp<T extends OpAttributes> = {
|
|
10
|
+
attributes: NullableOpAttributes<T> | undefined;
|
|
11
|
+
type: "retain";
|
|
12
|
+
value: number;
|
|
13
|
+
};
|
|
14
|
+
type RemoveOp = {
|
|
15
|
+
attributes: undefined;
|
|
16
|
+
type: "remove";
|
|
17
|
+
value: number;
|
|
18
|
+
};
|
|
19
|
+
type Op<T extends OpAttributes = OpAttributes> = InsertOp<T> | RetainOp<T> | RemoveOp;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { Op };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { NullableOpAttributes, OpAttributes } from "./index.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/OpAttributes/compose.d.ts
|
|
4
|
+
declare function compose<T extends OpAttributes>(a: NullableOpAttributes<T> | undefined, b: NullableOpAttributes<NoInfer<T>> | undefined, keepNull?: boolean): NullableOpAttributes<T> | undefined;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { compose };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region src/OpAttributes/compose.ts
|
|
2
|
+
function compose(a, b, keepNull = false) {
|
|
3
|
+
if (!b) return a;
|
|
4
|
+
if (!a) return keepNull ? b : stripNulls(b);
|
|
5
|
+
const result = {};
|
|
6
|
+
for (const key of unionKeys(a, b)) {
|
|
7
|
+
if (key in a && !(key in b)) {
|
|
8
|
+
result[key] = a[key];
|
|
9
|
+
continue;
|
|
10
|
+
}
|
|
11
|
+
if (b[key] !== null || keepNull) result[key] = b[key];
|
|
12
|
+
}
|
|
13
|
+
return Object.keys(result).length ? result : void 0;
|
|
14
|
+
}
|
|
15
|
+
function stripNulls(attrs) {
|
|
16
|
+
const result = {};
|
|
17
|
+
for (const key of Object.keys(attrs)) if (attrs[key] !== null) result[key] = attrs[key];
|
|
18
|
+
return Object.keys(result).length ? result : void 0;
|
|
19
|
+
}
|
|
20
|
+
function unionKeys(a, b) {
|
|
21
|
+
return new Set([...Object.keys(a), ...Object.keys(b)]);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
export { compose };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { NullableOpAttributes, OpAttributes } from "./index.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/OpAttributes/diff.d.ts
|
|
4
|
+
declare function diff<T extends OpAttributes>(a: NullableOpAttributes<T> | undefined, b?: NullableOpAttributes<NoInfer<T>> | undefined): NullableOpAttributes<T> | undefined;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { diff };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/OpAttributes/diff.ts
|
|
2
|
+
function diff(a, b = {}) {
|
|
3
|
+
if (!a) return b;
|
|
4
|
+
const result = {};
|
|
5
|
+
const keys = new Set([...Object.keys(a), ...Object.keys(b)]);
|
|
6
|
+
for (const key of keys) {
|
|
7
|
+
if (a[key] === b[key]) continue;
|
|
8
|
+
result[key] = key in b ? b[key] : null;
|
|
9
|
+
}
|
|
10
|
+
return Object.keys(result).length ? result : void 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
export { diff };
|