@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.
Files changed (56) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +695 -0
  3. package/dist/Delta/batch.d.mts +57 -0
  4. package/dist/Delta/batch.mjs +61 -0
  5. package/dist/Delta/chop.d.mts +56 -0
  6. package/dist/Delta/chop.mjs +60 -0
  7. package/dist/Delta/clean.d.mts +57 -0
  8. package/dist/Delta/clean.mjs +61 -0
  9. package/dist/Delta/compose.d.mts +58 -0
  10. package/dist/Delta/compose.mjs +100 -0
  11. package/dist/Delta/concat.d.mts +50 -0
  12. package/dist/Delta/concat.mjs +51 -0
  13. package/dist/Delta/diff.d.mts +73 -0
  14. package/dist/Delta/diff.mjs +124 -0
  15. package/dist/Delta/equals.d.mts +43 -0
  16. package/dist/Delta/equals.mjs +50 -0
  17. package/dist/Delta/index.d.mts +26 -0
  18. package/dist/Delta/index.mjs +37 -0
  19. package/dist/Delta/insert.d.mts +52 -0
  20. package/dist/Delta/insert.mjs +57 -0
  21. package/dist/Delta/invert.d.mts +54 -0
  22. package/dist/Delta/invert.mjs +77 -0
  23. package/dist/Delta/length.d.mts +51 -0
  24. package/dist/Delta/length.mjs +51 -0
  25. package/dist/Delta/push.d.mts +51 -0
  26. package/dist/Delta/push.mjs +87 -0
  27. package/dist/Delta/remove.d.mts +41 -0
  28. package/dist/Delta/remove.mjs +46 -0
  29. package/dist/Delta/retain.d.mts +70 -0
  30. package/dist/Delta/retain.mjs +76 -0
  31. package/dist/Delta/slice.d.mts +64 -0
  32. package/dist/Delta/slice.mjs +77 -0
  33. package/dist/Delta/transform.d.mts +63 -0
  34. package/dist/Delta/transform.mjs +91 -0
  35. package/dist/Op/index.d.mts +21 -0
  36. package/dist/OpAttributes/compose.d.mts +6 -0
  37. package/dist/OpAttributes/compose.mjs +25 -0
  38. package/dist/OpAttributes/diff.d.mts +6 -0
  39. package/dist/OpAttributes/diff.mjs +14 -0
  40. package/dist/OpAttributes/index.d.mts +15 -0
  41. package/dist/OpAttributes/invert.d.mts +6 -0
  42. package/dist/OpAttributes/invert.mjs +16 -0
  43. package/dist/OpAttributes/isEqual.d.mts +6 -0
  44. package/dist/OpAttributes/isEqual.mjs +16 -0
  45. package/dist/OpAttributes/transform.d.mts +6 -0
  46. package/dist/OpAttributes/transform.mjs +13 -0
  47. package/dist/OpIterator/create.mjs +11 -0
  48. package/dist/OpIterator/hasNext.mjs +9 -0
  49. package/dist/OpIterator/next.mjs +36 -0
  50. package/dist/OpIterator/peek.mjs +7 -0
  51. package/dist/OpIterator/peekLength.mjs +9 -0
  52. package/dist/OpIterator/peekType.mjs +7 -0
  53. package/dist/index.d.mts +2 -0
  54. package/dist/index.mjs +3 -0
  55. package/dist/internals/hasKeys.mjs +8 -0
  56. 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 };