@thomasfosterau/effect-richtext 0.0.0 → 0.1.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 (176) hide show
  1. package/LICENSE +48 -0
  2. package/README.md +117 -1
  3. package/dist/_virtual/_rolldown/runtime.js +12 -0
  4. package/dist/commands/commands.d.ts +323 -0
  5. package/dist/commands/commands.js +722 -0
  6. package/dist/commands/internal.js +43 -0
  7. package/dist/commands/keymaps.d.ts +46 -0
  8. package/dist/commands/keymaps.js +64 -0
  9. package/dist/commands.d.ts +3 -0
  10. package/dist/commands.js +3 -0
  11. package/dist/compat/commands.d.ts +250 -0
  12. package/dist/compat/commands.js +275 -0
  13. package/dist/compat/internal/core.d.ts +20 -0
  14. package/dist/compat/internal/core.js +148 -0
  15. package/dist/compat/internal/props.js +82 -0
  16. package/dist/compat/keymap.d.ts +21 -0
  17. package/dist/compat/keymap.js +38 -0
  18. package/dist/compat/model.d.ts +893 -0
  19. package/dist/compat/model.js +1212 -0
  20. package/dist/compat/orderedmap.d.ts +74 -0
  21. package/dist/compat/orderedmap.js +124 -0
  22. package/dist/compat/schema-basic.d.ts +38 -0
  23. package/dist/compat/schema-basic.js +238 -0
  24. package/dist/compat/schema-list.d.ts +81 -0
  25. package/dist/compat/schema-list.js +156 -0
  26. package/dist/compat/state.d.ts +415 -0
  27. package/dist/compat/state.js +689 -0
  28. package/dist/compat/test-builder.d.ts +98 -0
  29. package/dist/compat/test-builder.js +197 -0
  30. package/dist/compat/transform.d.ts +458 -0
  31. package/dist/compat/transform.js +803 -0
  32. package/dist/compat/view.d.ts +411 -0
  33. package/dist/compat/view.js +409 -0
  34. package/dist/dropcursor.d.ts +46 -0
  35. package/dist/dropcursor.js +176 -0
  36. package/dist/extensions/defaults.d.ts +716 -0
  37. package/dist/extensions/defaults.js +209 -0
  38. package/dist/extensions/editor.d.ts +246 -0
  39. package/dist/extensions/editor.js +271 -0
  40. package/dist/extensions/extension.d.ts +375 -0
  41. package/dist/extensions/extension.js +233 -0
  42. package/dist/extensions.d.ts +4 -0
  43. package/dist/extensions.js +4 -0
  44. package/dist/gapcursor.d.ts +66 -0
  45. package/dist/gapcursor.js +273 -0
  46. package/dist/history.d.ts +178 -0
  47. package/dist/history.js +412 -0
  48. package/dist/html.d.ts +158 -0
  49. package/dist/html.js +164 -0
  50. package/dist/inputrules.d.ts +271 -0
  51. package/dist/inputrules.js +321 -0
  52. package/dist/internal/attempt.js +15 -0
  53. package/dist/internal/json.js +29 -0
  54. package/dist/keymap/keymap.d.ts +130 -0
  55. package/dist/keymap/keymap.js +159 -0
  56. package/dist/keymap.d.ts +2 -0
  57. package/dist/keymap.js +1 -0
  58. package/dist/markdown/errors.d.ts +23 -0
  59. package/dist/markdown/errors.js +26 -0
  60. package/dist/markdown/from_markdown.d.ts +185 -0
  61. package/dist/markdown/from_markdown.js +266 -0
  62. package/dist/markdown/schema.d.ts +522 -0
  63. package/dist/markdown/schema.js +292 -0
  64. package/dist/markdown/to_markdown.d.ts +251 -0
  65. package/dist/markdown/to_markdown.js +413 -0
  66. package/dist/markdown.d.ts +5 -0
  67. package/dist/markdown.js +5 -0
  68. package/dist/model/attrsCodec.js +48 -0
  69. package/dist/model/comparedeep.js +17 -0
  70. package/dist/model/content.d.ts +232 -0
  71. package/dist/model/content.js +630 -0
  72. package/dist/model/diff.js +66 -0
  73. package/dist/model/dom.d.ts +3 -0
  74. package/dist/model/errors.d.ts +90 -0
  75. package/dist/model/errors.js +76 -0
  76. package/dist/model/fragment.d.ts +131 -0
  77. package/dist/model/fragment.js +262 -0
  78. package/dist/model/from_dom.d.ts +299 -0
  79. package/dist/model/from_dom.js +618 -0
  80. package/dist/model/json.d.ts +37 -0
  81. package/dist/model/json.js +126 -0
  82. package/dist/model/mark.d.ts +73 -0
  83. package/dist/model/mark.js +121 -0
  84. package/dist/model/node.d.ts +267 -0
  85. package/dist/model/node.js +434 -0
  86. package/dist/model/replace.d.ts +78 -0
  87. package/dist/model/replace.js +207 -0
  88. package/dist/model/resolvedpos.d.ts +196 -0
  89. package/dist/model/resolvedpos.js +305 -0
  90. package/dist/model/schema.d.ts +740 -0
  91. package/dist/model/schema.js +451 -0
  92. package/dist/model/to_dom.d.ts +169 -0
  93. package/dist/model/to_dom.js +238 -0
  94. package/dist/model.d.ts +12 -0
  95. package/dist/model.js +12 -0
  96. package/dist/placeholder.d.ts +53 -0
  97. package/dist/placeholder.js +79 -0
  98. package/dist/reactive/observer.d.ts +54 -0
  99. package/dist/reactive/observer.js +61 -0
  100. package/dist/reactive/selectors.d.ts +22 -0
  101. package/dist/reactive/selectors.js +61 -0
  102. package/dist/reactive/stateref.d.ts +72 -0
  103. package/dist/reactive/stateref.js +71 -0
  104. package/dist/reactive/streams.d.ts +83 -0
  105. package/dist/reactive/streams.js +85 -0
  106. package/dist/reactive.d.ts +16 -0
  107. package/dist/reactive.js +26 -0
  108. package/dist/schema-basic.d.ts +448 -0
  109. package/dist/schema-basic.js +269 -0
  110. package/dist/schema-list/commands.d.ts +66 -0
  111. package/dist/schema-list/commands.js +203 -0
  112. package/dist/schema-list.d.ts +92 -0
  113. package/dist/schema-list.js +100 -0
  114. package/dist/state/errors.d.ts +39 -0
  115. package/dist/state/errors.js +32 -0
  116. package/dist/state/plugin.d.ts +232 -0
  117. package/dist/state/plugin.js +82 -0
  118. package/dist/state/selection.d.ts +297 -0
  119. package/dist/state/selection.js +486 -0
  120. package/dist/state/state.d.ts +212 -0
  121. package/dist/state/state.js +489 -0
  122. package/dist/state/transaction.d.ts +145 -0
  123. package/dist/state/transaction.js +195 -0
  124. package/dist/state.d.ts +6 -0
  125. package/dist/state.js +6 -0
  126. package/dist/test-builder.d.ts +3582 -0
  127. package/dist/test-builder.js +239 -0
  128. package/dist/transform/attr_step.d.ts +60 -0
  129. package/dist/transform/attr_step.js +105 -0
  130. package/dist/transform/errors.d.ts +50 -0
  131. package/dist/transform/errors.js +35 -0
  132. package/dist/transform/map.d.ts +182 -0
  133. package/dist/transform/map.js +280 -0
  134. package/dist/transform/mark.js +98 -0
  135. package/dist/transform/mark_set_step.js +69 -0
  136. package/dist/transform/mark_step.d.ts +113 -0
  137. package/dist/transform/mark_step.js +225 -0
  138. package/dist/transform/replace.d.ts +18 -0
  139. package/dist/transform/replace.js +381 -0
  140. package/dist/transform/replace_step.d.ts +109 -0
  141. package/dist/transform/replace_step.js +175 -0
  142. package/dist/transform/step.d.ts +157 -0
  143. package/dist/transform/step.js +168 -0
  144. package/dist/transform/structure.d.ts +89 -0
  145. package/dist/transform/structure.js +350 -0
  146. package/dist/transform/transform.d.ts +248 -0
  147. package/dist/transform/transform.js +373 -0
  148. package/dist/transform.d.ts +10 -0
  149. package/dist/transform.js +10 -0
  150. package/dist/view/browser.js +39 -0
  151. package/dist/view/capturekeys.js +282 -0
  152. package/dist/view/clipboard.d.ts +8 -0
  153. package/dist/view/clipboard.js +245 -0
  154. package/dist/view/decoration.d.ts +339 -0
  155. package/dist/view/decoration.js +566 -0
  156. package/dist/view/dom.d.ts +18 -0
  157. package/dist/view/dom.js +140 -0
  158. package/dist/view/domchange.js +295 -0
  159. package/dist/view/domcoords.d.ts +22 -0
  160. package/dist/view/domcoords.js +448 -0
  161. package/dist/view/domobserver.d.ts +47 -0
  162. package/dist/view/domobserver.js +328 -0
  163. package/dist/view/errors.d.ts +18 -0
  164. package/dist/view/errors.js +21 -0
  165. package/dist/view/input.d.ts +58 -0
  166. package/dist/view/input.js +704 -0
  167. package/dist/view/selection.js +198 -0
  168. package/dist/view/view.d.ts +699 -0
  169. package/dist/view/view.js +623 -0
  170. package/dist/view/viewdesc.d.ts +236 -0
  171. package/dist/view/viewdesc.js +1205 -0
  172. package/dist/view-css.d.ts +43 -0
  173. package/dist/view-css.js +124 -0
  174. package/dist/view.d.ts +6 -0
  175. package/dist/view.js +4 -0
  176. package/package.json +200 -4
@@ -0,0 +1,248 @@
1
+ import { AttributeError, PositionError } from "../model/errors.js";
2
+ import { NodeRange } from "../model/resolvedpos.js";
3
+ import { Slice } from "../model/replace.js";
4
+ import { AnySchema, MarkType, NodeAttrsInput, NodeNames, NodeType } from "../model/schema.js";
5
+ import { Mark } from "../model/mark.js";
6
+ import { Node } from "../model/node.js";
7
+ import { Fragment } from "../model/fragment.js";
8
+ import { ContentMatch } from "../model/content.js";
9
+ import "../model.js";
10
+ import { StepError, TransformError } from "./errors.js";
11
+ import { Mapping } from "./map.js";
12
+ import { Step, StepResult } from "./step.js";
13
+ import { NodeTypeWithAttrs } from "./structure.js";
14
+ import * as Effect from "effect/Effect";
15
+ import * as Option from "effect/Option";
16
+ /**
17
+ * Content accepted by `replaceWith` and `insert`.
18
+ *
19
+ * @since 0.1.0
20
+ * @category models
21
+ */
22
+ export type ContentInput<Sc extends AnySchema = AnySchema> = Fragment<Sc> | Node<Sc> | ReadonlyArray<Node<Sc>>;
23
+ /**
24
+ * Errors that can occur when replacing content: invalid positions or a
25
+ * step that can't be applied.
26
+ *
27
+ * @since 0.1.0
28
+ * @category errors
29
+ */
30
+ export type ReplaceFailure = StepError | PositionError;
31
+ /**
32
+ * Errors that can occur in structural transforms (`lift`, `wrap`,
33
+ * `split`, `setBlockType`, …).
34
+ *
35
+ * @since 0.1.0
36
+ * @category errors
37
+ */
38
+ export type StructureFailure = TransformError | StepError | PositionError | AttributeError;
39
+ /**
40
+ * Abstraction to build up and track an array of steps representing a
41
+ * document transformation.
42
+ *
43
+ * Transforms are mutable builders: most transforming methods apply a
44
+ * change immediately and return the transform itself, so that they can
45
+ * be chained. Every method that can fail comes in two flavours:
46
+ *
47
+ * - `x(...)` returns an `Effect` that performs the change when run and
48
+ * succeeds with the transform (or fails with a tagged error, leaving
49
+ * any steps added before the failure in place).
50
+ * - `xUnsafe(...)` performs the change immediately, returning the
51
+ * transform, and throws the tagged error on failure.
52
+ *
53
+ * Methods that cannot fail for valid positions (`addMark`,
54
+ * `removeMark`) are plain chainable methods.
55
+ *
56
+ * @since 0.1.0
57
+ * @category models
58
+ */
59
+ export declare class Transform<Sc extends AnySchema = AnySchema> {
60
+ /** The steps in this transform. */
61
+ readonly steps: Array<Step<Sc>>;
62
+ /** The documents before each of the steps. */
63
+ readonly docs: Array<Node<Sc>>;
64
+ /** A mapping with the maps for each of the steps in this transform. */
65
+ readonly mapping: Mapping;
66
+ /** @internal */
67
+ protected currentDoc: Node<Sc>;
68
+ /** Create a transform that starts with the given document. */
69
+ constructor(doc: Node<Sc>);
70
+ /** The current document (the result of applying the steps in the transform). */
71
+ get doc(): Node<Sc>;
72
+ /** The starting document. */
73
+ get before(): Node<Sc>;
74
+ /**
75
+ * Apply a new step in this transform, saving the result. Fails with
76
+ * a `StepError` when the step can't be applied.
77
+ */
78
+ step(step: Step<Sc>): Effect.Effect<this, StepError>;
79
+ /** Like `step`, but throws a `StepError` when the step fails. */
80
+ stepUnsafe(step: Step<Sc>): this;
81
+ /**
82
+ * Try to apply a step in this transformation, ignoring it if it
83
+ * fails. Returns the step result.
84
+ */
85
+ maybeStep(step: Step<Sc>): StepResult<Sc>;
86
+ /** True when the document has been changed (when there are any steps). */
87
+ get docChanged(): boolean;
88
+ /**
89
+ * Return a single range, in post-transform document positions, that
90
+ * covers all content changed by this transform. Returns `None` if no
91
+ * replacements are made. Note that this will ignore changes that
92
+ * add/remove marks without replacing the underlying content.
93
+ */
94
+ changedRange(): Option.Option<{
95
+ readonly from: number;
96
+ readonly to: number;
97
+ }>;
98
+ /** @internal */
99
+ addStep(step: Step<Sc>, doc: Node<Sc>): void;
100
+ /** @internal */
101
+ protected effect<E>(f: () => unknown): Effect.Effect<this, E>;
102
+ /** Replace the part of the document between `from` and `to` with the given `slice`. */
103
+ replace(from: number, to?: number, slice?: Slice<Sc>): Effect.Effect<this, ReplaceFailure>;
104
+ /** Like `replace`, but throws on failure. */
105
+ replaceUnsafe(from: number, to?: number, slice?: Slice<Sc>): this;
106
+ /**
107
+ * Replace the given range with the given content, which may be a
108
+ * fragment, node, or array of nodes.
109
+ */
110
+ replaceWith(from: number, to: number, content: ContentInput<Sc>): Effect.Effect<this, ReplaceFailure>;
111
+ /** Like `replaceWith`, but throws on failure. */
112
+ replaceWithUnsafe(from: number, to: number, content: ContentInput<Sc>): this;
113
+ /** Delete the content between the given positions. */
114
+ delete(from: number, to: number): Effect.Effect<this, ReplaceFailure>;
115
+ /** Like `delete`, but throws on failure. */
116
+ deleteUnsafe(from: number, to: number): this;
117
+ /** Insert the given content at the given position. */
118
+ insert(pos: number, content: ContentInput<Sc>): Effect.Effect<this, ReplaceFailure>;
119
+ /** Like `insert`, but throws on failure. */
120
+ insertUnsafe(pos: number, content: ContentInput<Sc>): this;
121
+ /**
122
+ * Replace a range of the document with a given slice, using `from`,
123
+ * `to`, and the slice's `openStart` property as hints, rather than
124
+ * fixed start and end points. This method may grow the replaced area
125
+ * or close open nodes in the slice in order to get a fit that is
126
+ * more in line with WYSIWYG expectations, by dropping fully covered
127
+ * parent nodes of the replaced region when they are marked
128
+ * non-defining as context, or including an open parent node from the
129
+ * slice that _is_ marked as defining its content.
130
+ *
131
+ * This is the method, for example, to handle paste. The similar
132
+ * `replace` method is a more primitive tool which will _not_ move the
133
+ * start and end of its given range, and is useful in situations where
134
+ * you need more precise control over what happens.
135
+ */
136
+ replaceRange(from: number, to: number, slice: Slice<Sc>): Effect.Effect<this, ReplaceFailure>;
137
+ /** Like `replaceRange`, but throws on failure. */
138
+ replaceRangeUnsafe(from: number, to: number, slice: Slice<Sc>): this;
139
+ /**
140
+ * Replace the given range with a node, but use `from` and `to` as
141
+ * hints, rather than precise positions. When from and to are the same
142
+ * and are at the start or end of a parent node in which the given
143
+ * node doesn't fit, this method may _move_ them out towards a parent
144
+ * that does allow the given node to be placed. When the given range
145
+ * completely covers a parent node, this method may completely replace
146
+ * that parent node.
147
+ */
148
+ replaceRangeWith(from: number, to: number, node: Node<Sc>): Effect.Effect<this, ReplaceFailure>;
149
+ /** Like `replaceRangeWith`, but throws on failure. */
150
+ replaceRangeWithUnsafe(from: number, to: number, node: Node<Sc>): this;
151
+ /**
152
+ * Delete the given range, expanding it to cover fully covered parent
153
+ * nodes until a valid replace is found.
154
+ */
155
+ deleteRange(from: number, to: number): Effect.Effect<this, ReplaceFailure>;
156
+ /** Like `deleteRange`, but throws on failure. */
157
+ deleteRangeUnsafe(from: number, to: number): this;
158
+ /**
159
+ * Split the content in the given range off from its parent, if there
160
+ * is sibling content before or after it, and move it up the tree to
161
+ * the depth specified by `target`. You'll probably want to use
162
+ * `liftTarget` to compute `target`, to make sure the lift is valid.
163
+ */
164
+ lift(range: NodeRange<Sc>, target: number): Effect.Effect<this, StructureFailure>;
165
+ /** Like `lift`, but throws on failure. */
166
+ liftUnsafe(range: NodeRange<Sc>, target: number): this;
167
+ /**
168
+ * Join the blocks around the given position. If depth is 2, their
169
+ * last and first siblings are also joined, and so on.
170
+ */
171
+ join(pos: number, depth?: number): Effect.Effect<this, StructureFailure>;
172
+ /** Like `join`, but throws on failure. */
173
+ joinUnsafe(pos: number, depth?: number): this;
174
+ /**
175
+ * Wrap the given range in the given set of wrappers. The wrappers are
176
+ * assumed to be valid in this position, and should probably be
177
+ * computed with `findWrapping`.
178
+ */
179
+ wrap(range: NodeRange<Sc>, wrappers: ReadonlyArray<NodeTypeWithAttrs<Sc>>): Effect.Effect<this, StructureFailure>;
180
+ /** Like `wrap`, but throws on failure. */
181
+ wrapUnsafe(range: NodeRange<Sc>, wrappers: ReadonlyArray<NodeTypeWithAttrs<Sc>>): this;
182
+ /**
183
+ * Set the type of all textblocks (partly) between `from` and `to` to
184
+ * the given node type with the given attributes. `to` defaults to
185
+ * `from`.
186
+ */
187
+ setBlockType<N extends NodeNames<Sc>>(from: number, to: number | undefined, type: NodeType<Sc, N>, attrs?: NodeAttrsInput<Sc, N> | null | ((oldNode: Node<Sc>) => NodeAttrsInput<Sc, N>)): Effect.Effect<this, StructureFailure>;
188
+ /** Like `setBlockType`, but throws on failure. */
189
+ setBlockTypeUnsafe<N extends NodeNames<Sc>>(from: number, to: number | undefined, type: NodeType<Sc, N>, attrs?: NodeAttrsInput<Sc, N> | null | ((oldNode: Node<Sc>) => NodeAttrsInput<Sc, N>)): this;
190
+ /**
191
+ * Change the type, attributes, and/or marks of the node at `pos`.
192
+ * When `type` isn't given, the existing node type is preserved.
193
+ */
194
+ setNodeMarkup<N extends NodeNames<Sc>>(pos: number, type?: NodeType<Sc, N> | null, attrs?: NodeAttrsInput<Sc, N> | null, marks?: ReadonlyArray<Mark<Sc>>): Effect.Effect<this, StructureFailure>;
195
+ /** Like `setNodeMarkup`, but throws on failure. */
196
+ setNodeMarkupUnsafe<N extends NodeNames<Sc>>(pos: number, type?: NodeType<Sc, N> | null, attrs?: NodeAttrsInput<Sc, N> | null, marks?: ReadonlyArray<Mark<Sc>>): this;
197
+ /**
198
+ * Set a single attribute on a given node to a new value. The `pos`
199
+ * addresses the document content. Use `setDocAttribute` to set
200
+ * attributes on the document itself.
201
+ */
202
+ setNodeAttribute(pos: number, attr: string, value: unknown): Effect.Effect<this, StepError>;
203
+ /** Like `setNodeAttribute`, but throws on failure. */
204
+ setNodeAttributeUnsafe(pos: number, attr: string, value: unknown): this;
205
+ /** Set a single attribute on the document to a new value. */
206
+ setDocAttribute(attr: string, value: unknown): Effect.Effect<this, StepError>;
207
+ /** Like `setDocAttribute`, but throws on failure. */
208
+ setDocAttributeUnsafe(attr: string, value: unknown): this;
209
+ /** Add a mark to the node at position `pos`. */
210
+ addNodeMark(pos: number, mark: Mark<Sc>): Effect.Effect<this, StepError>;
211
+ /** Like `addNodeMark`, but throws on failure. */
212
+ addNodeMarkUnsafe(pos: number, mark: Mark<Sc>): this;
213
+ /**
214
+ * Remove a mark (or all marks of the given type) from the node at
215
+ * position `pos`. Fails with a `TransformError` when there is no node
216
+ * at that position.
217
+ */
218
+ removeNodeMark(pos: number, mark: Mark<Sc> | MarkType<Sc>): Effect.Effect<this, TransformError | StepError>;
219
+ /** Like `removeNodeMark`, but throws on failure. */
220
+ removeNodeMarkUnsafe(pos: number, mark: Mark<Sc> | MarkType<Sc>): this;
221
+ /**
222
+ * Split the node at the given position, and optionally, if `depth` is
223
+ * greater than one, any number of nodes above that. By default, the
224
+ * parts split off will inherit the node type of the original node.
225
+ * This can be changed by passing an array of types and attributes to
226
+ * use after the split (with the outermost nodes coming first).
227
+ */
228
+ split(pos: number, depth?: number, typesAfter?: ReadonlyArray<NodeTypeWithAttrs<Sc> | null | undefined>): Effect.Effect<this, StructureFailure>;
229
+ /** Like `split`, but throws on failure. */
230
+ splitUnsafe(pos: number, depth?: number, typesAfter?: ReadonlyArray<NodeTypeWithAttrs<Sc> | null | undefined>): this;
231
+ /** Add the given mark to the inline content between `from` and `to`. */
232
+ addMark(from: number, to: number, mark: Mark<Sc>): this;
233
+ /**
234
+ * Remove marks from inline nodes between `from` and `to`. When `mark`
235
+ * is a single mark, remove precisely that mark. When it is a mark
236
+ * type, remove all marks of that type. When it is null, remove all
237
+ * marks of any type.
238
+ */
239
+ removeMark(from: number, to: number, mark?: Mark<Sc> | MarkType<Sc> | null): this;
240
+ /**
241
+ * Removes all marks and nodes from the content of the node at `pos`
242
+ * that don't match the given new parent node type. Accepts an
243
+ * optional starting content match as third argument.
244
+ */
245
+ clearIncompatible(pos: number, parentType: NodeType<Sc, any>, match?: ContentMatch): Effect.Effect<this, TransformError | StepError | PositionError>;
246
+ /** Like `clearIncompatible`, but throws on failure. */
247
+ clearIncompatibleUnsafe(pos: number, parentType: NodeType<Sc, any>, match?: ContentMatch): this;
248
+ }
@@ -0,0 +1,373 @@
1
+ import { attempt } from "../internal/attempt.js";
2
+ import { Fragment } from "../model/fragment.js";
3
+ import { Mark } from "../model/mark.js";
4
+ import { Slice } from "../model/replace.js";
5
+ import { AttrStep, DocAttrStep } from "./attr_step.js";
6
+ import { TransformError, isTransformOrModelError } from "./errors.js";
7
+ import { Mapping } from "./map.js";
8
+ import { addMark, clearIncompatible, removeMark } from "./mark.js";
9
+ import { AddNodeMarkStep, RemoveNodeMarkStep } from "./mark_step.js";
10
+ import { deleteRange, replaceRange, replaceRangeWith, replaceStepOrNull } from "./replace.js";
11
+ import { applyStep } from "./step.js";
12
+ import { join, lift, setBlockType, setNodeMarkup, split, wrap } from "./structure.js";
13
+ import * as Arr from "effect/Array";
14
+ import * as Option from "effect/Option";
15
+ // src/transform/transform.ts
16
+ /**
17
+ * The `Transform` class: a mutable, chainable builder of document
18
+ * changes.
19
+ *
20
+ * @since 0.1.0
21
+ */
22
+ /**
23
+ * Abstraction to build up and track an array of steps representing a
24
+ * document transformation.
25
+ *
26
+ * Transforms are mutable builders: most transforming methods apply a
27
+ * change immediately and return the transform itself, so that they can
28
+ * be chained. Every method that can fail comes in two flavours:
29
+ *
30
+ * - `x(...)` returns an `Effect` that performs the change when run and
31
+ * succeeds with the transform (or fails with a tagged error, leaving
32
+ * any steps added before the failure in place).
33
+ * - `xUnsafe(...)` performs the change immediately, returning the
34
+ * transform, and throws the tagged error on failure.
35
+ *
36
+ * Methods that cannot fail for valid positions (`addMark`,
37
+ * `removeMark`) are plain chainable methods.
38
+ *
39
+ * @since 0.1.0
40
+ * @category models
41
+ */
42
+ var Transform = class {
43
+ /** Create a transform that starts with the given document. */
44
+ constructor(doc) {
45
+ this.steps = [];
46
+ this.docs = [];
47
+ this.mapping = new Mapping();
48
+ this.currentDoc = doc;
49
+ }
50
+ /** The current document (the result of applying the steps in the transform). */
51
+ get doc() {
52
+ return this.currentDoc;
53
+ }
54
+ /** The starting document. */
55
+ get before() {
56
+ return this.docs.length ? this.docs[0] : this.currentDoc;
57
+ }
58
+ /**
59
+ * Apply a new step in this transform, saving the result. Fails with
60
+ * a `StepError` when the step can't be applied.
61
+ */
62
+ step(step) {
63
+ return attempt(() => this.stepUnsafe(step), isTransformOrModelError);
64
+ }
65
+ /** Like `step`, but throws a `StepError` when the step fails. */
66
+ stepUnsafe(step) {
67
+ const result = this.maybeStep(step);
68
+ if (result.failedOrNull !== null) result.getUnsafe();
69
+ return this;
70
+ }
71
+ /**
72
+ * Try to apply a step in this transformation, ignoring it if it
73
+ * fails. Returns the step result.
74
+ */
75
+ maybeStep(step) {
76
+ const result = applyStep(step, this.currentDoc);
77
+ if (result.failedOrNull === null) this.addStep(step, result.docOrNull);
78
+ return result;
79
+ }
80
+ /** True when the document has been changed (when there are any steps). */
81
+ get docChanged() {
82
+ return Arr.isReadonlyArrayNonEmpty(this.steps);
83
+ }
84
+ /**
85
+ * Return a single range, in post-transform document positions, that
86
+ * covers all content changed by this transform. Returns `None` if no
87
+ * replacements are made. Note that this will ignore changes that
88
+ * add/remove marks without replacing the underlying content.
89
+ */
90
+ changedRange() {
91
+ let from = 1e9, to = -1e9;
92
+ for (let i = 0; i < this.mapping.maps.length; i++) {
93
+ const map = this.mapping.maps[i];
94
+ if (i) {
95
+ from = map.map(from, 1);
96
+ to = map.map(to, -1);
97
+ }
98
+ map.forEach((_f, _t, fromB, toB) => {
99
+ from = Math.min(from, fromB);
100
+ to = Math.max(to, toB);
101
+ });
102
+ }
103
+ return from === 1e9 ? Option.none() : Option.some({
104
+ from,
105
+ to
106
+ });
107
+ }
108
+ /** @internal */
109
+ addStep(step, doc) {
110
+ this.docs.push(this.currentDoc);
111
+ this.steps.push(step);
112
+ this.mapping.appendMap(step.getMap());
113
+ this.currentDoc = doc;
114
+ }
115
+ /** @internal */
116
+ effect(f) {
117
+ return attempt(() => {
118
+ f();
119
+ return this;
120
+ }, isTransformOrModelError);
121
+ }
122
+ /** Replace the part of the document between `from` and `to` with the given `slice`. */
123
+ replace(from, to = from, slice = Slice.empty) {
124
+ return this.effect(() => this.replaceUnsafe(from, to, slice));
125
+ }
126
+ /** Like `replace`, but throws on failure. */
127
+ replaceUnsafe(from, to = from, slice = Slice.empty) {
128
+ const step = replaceStepOrNull(this.currentDoc, from, to, slice);
129
+ if (step) this.stepUnsafe(step);
130
+ return this;
131
+ }
132
+ /**
133
+ * Replace the given range with the given content, which may be a
134
+ * fragment, node, or array of nodes.
135
+ */
136
+ replaceWith(from, to, content) {
137
+ return this.effect(() => this.replaceWithUnsafe(from, to, content));
138
+ }
139
+ /** Like `replaceWith`, but throws on failure. */
140
+ replaceWithUnsafe(from, to, content) {
141
+ return this.replaceUnsafe(from, to, new Slice(Fragment.from(content), 0, 0));
142
+ }
143
+ /** Delete the content between the given positions. */
144
+ delete(from, to) {
145
+ return this.effect(() => this.deleteUnsafe(from, to));
146
+ }
147
+ /** Like `delete`, but throws on failure. */
148
+ deleteUnsafe(from, to) {
149
+ return this.replaceUnsafe(from, to, Slice.empty);
150
+ }
151
+ /** Insert the given content at the given position. */
152
+ insert(pos, content) {
153
+ return this.effect(() => this.insertUnsafe(pos, content));
154
+ }
155
+ /** Like `insert`, but throws on failure. */
156
+ insertUnsafe(pos, content) {
157
+ return this.replaceWithUnsafe(pos, pos, content);
158
+ }
159
+ /**
160
+ * Replace a range of the document with a given slice, using `from`,
161
+ * `to`, and the slice's `openStart` property as hints, rather than
162
+ * fixed start and end points. This method may grow the replaced area
163
+ * or close open nodes in the slice in order to get a fit that is
164
+ * more in line with WYSIWYG expectations, by dropping fully covered
165
+ * parent nodes of the replaced region when they are marked
166
+ * non-defining as context, or including an open parent node from the
167
+ * slice that _is_ marked as defining its content.
168
+ *
169
+ * This is the method, for example, to handle paste. The similar
170
+ * `replace` method is a more primitive tool which will _not_ move the
171
+ * start and end of its given range, and is useful in situations where
172
+ * you need more precise control over what happens.
173
+ */
174
+ replaceRange(from, to, slice) {
175
+ return this.effect(() => this.replaceRangeUnsafe(from, to, slice));
176
+ }
177
+ /** Like `replaceRange`, but throws on failure. */
178
+ replaceRangeUnsafe(from, to, slice) {
179
+ replaceRange(this, from, to, slice);
180
+ return this;
181
+ }
182
+ /**
183
+ * Replace the given range with a node, but use `from` and `to` as
184
+ * hints, rather than precise positions. When from and to are the same
185
+ * and are at the start or end of a parent node in which the given
186
+ * node doesn't fit, this method may _move_ them out towards a parent
187
+ * that does allow the given node to be placed. When the given range
188
+ * completely covers a parent node, this method may completely replace
189
+ * that parent node.
190
+ */
191
+ replaceRangeWith(from, to, node) {
192
+ return this.effect(() => this.replaceRangeWithUnsafe(from, to, node));
193
+ }
194
+ /** Like `replaceRangeWith`, but throws on failure. */
195
+ replaceRangeWithUnsafe(from, to, node) {
196
+ replaceRangeWith(this, from, to, node);
197
+ return this;
198
+ }
199
+ /**
200
+ * Delete the given range, expanding it to cover fully covered parent
201
+ * nodes until a valid replace is found.
202
+ */
203
+ deleteRange(from, to) {
204
+ return this.effect(() => this.deleteRangeUnsafe(from, to));
205
+ }
206
+ /** Like `deleteRange`, but throws on failure. */
207
+ deleteRangeUnsafe(from, to) {
208
+ deleteRange(this, from, to);
209
+ return this;
210
+ }
211
+ /**
212
+ * Split the content in the given range off from its parent, if there
213
+ * is sibling content before or after it, and move it up the tree to
214
+ * the depth specified by `target`. You'll probably want to use
215
+ * `liftTarget` to compute `target`, to make sure the lift is valid.
216
+ */
217
+ lift(range, target) {
218
+ return this.effect(() => this.liftUnsafe(range, target));
219
+ }
220
+ /** Like `lift`, but throws on failure. */
221
+ liftUnsafe(range, target) {
222
+ lift(this, range, target);
223
+ return this;
224
+ }
225
+ /**
226
+ * Join the blocks around the given position. If depth is 2, their
227
+ * last and first siblings are also joined, and so on.
228
+ */
229
+ join(pos, depth = 1) {
230
+ return this.effect(() => this.joinUnsafe(pos, depth));
231
+ }
232
+ /** Like `join`, but throws on failure. */
233
+ joinUnsafe(pos, depth = 1) {
234
+ join(this, pos, depth);
235
+ return this;
236
+ }
237
+ /**
238
+ * Wrap the given range in the given set of wrappers. The wrappers are
239
+ * assumed to be valid in this position, and should probably be
240
+ * computed with `findWrapping`.
241
+ */
242
+ wrap(range, wrappers) {
243
+ return this.effect(() => this.wrapUnsafe(range, wrappers));
244
+ }
245
+ /** Like `wrap`, but throws on failure. */
246
+ wrapUnsafe(range, wrappers) {
247
+ wrap(this, range, wrappers);
248
+ return this;
249
+ }
250
+ /**
251
+ * Set the type of all textblocks (partly) between `from` and `to` to
252
+ * the given node type with the given attributes. `to` defaults to
253
+ * `from`.
254
+ */
255
+ setBlockType(from, to, type, attrs) {
256
+ return this.effect(() => this.setBlockTypeUnsafe(from, to, type, attrs));
257
+ }
258
+ /** Like `setBlockType`, but throws on failure. */
259
+ setBlockTypeUnsafe(from, to, type, attrs) {
260
+ setBlockType(this, from, to ?? from, type, attrs);
261
+ return this;
262
+ }
263
+ /**
264
+ * Change the type, attributes, and/or marks of the node at `pos`.
265
+ * When `type` isn't given, the existing node type is preserved.
266
+ */
267
+ setNodeMarkup(pos, type, attrs, marks) {
268
+ return this.effect(() => this.setNodeMarkupUnsafe(pos, type, attrs, marks));
269
+ }
270
+ /** Like `setNodeMarkup`, but throws on failure. */
271
+ setNodeMarkupUnsafe(pos, type, attrs, marks) {
272
+ setNodeMarkup(this, pos, type, attrs, marks);
273
+ return this;
274
+ }
275
+ /**
276
+ * Set a single attribute on a given node to a new value. The `pos`
277
+ * addresses the document content. Use `setDocAttribute` to set
278
+ * attributes on the document itself.
279
+ */
280
+ setNodeAttribute(pos, attr, value) {
281
+ return this.effect(() => this.setNodeAttributeUnsafe(pos, attr, value));
282
+ }
283
+ /** Like `setNodeAttribute`, but throws on failure. */
284
+ setNodeAttributeUnsafe(pos, attr, value) {
285
+ return this.stepUnsafe(new AttrStep(pos, attr, value));
286
+ }
287
+ /** Set a single attribute on the document to a new value. */
288
+ setDocAttribute(attr, value) {
289
+ return this.effect(() => this.setDocAttributeUnsafe(attr, value));
290
+ }
291
+ /** Like `setDocAttribute`, but throws on failure. */
292
+ setDocAttributeUnsafe(attr, value) {
293
+ return this.stepUnsafe(new DocAttrStep(attr, value));
294
+ }
295
+ /** Add a mark to the node at position `pos`. */
296
+ addNodeMark(pos, mark) {
297
+ return this.effect(() => this.addNodeMarkUnsafe(pos, mark));
298
+ }
299
+ /** Like `addNodeMark`, but throws on failure. */
300
+ addNodeMarkUnsafe(pos, mark) {
301
+ return this.stepUnsafe(new AddNodeMarkStep(pos, mark));
302
+ }
303
+ /**
304
+ * Remove a mark (or all marks of the given type) from the node at
305
+ * position `pos`. Fails with a `TransformError` when there is no node
306
+ * at that position.
307
+ */
308
+ removeNodeMark(pos, mark) {
309
+ return this.effect(() => this.removeNodeMarkUnsafe(pos, mark));
310
+ }
311
+ /** Like `removeNodeMark`, but throws on failure. */
312
+ removeNodeMarkUnsafe(pos, mark) {
313
+ const node = this.currentDoc.nodeAtOrNull(pos);
314
+ if (!node) throw new TransformError({ message: "No node at position " + pos });
315
+ if (mark instanceof Mark) {
316
+ if (mark.isInSet(node.marks)) this.stepUnsafe(new RemoveNodeMarkStep(pos, mark));
317
+ } else {
318
+ let set = node.marks, found;
319
+ const steps = [];
320
+ while (found = mark.findInSet(set)) {
321
+ steps.push(new RemoveNodeMarkStep(pos, found));
322
+ set = found.removeFromSet(set);
323
+ }
324
+ for (let i = steps.length - 1; i >= 0; i--) this.stepUnsafe(steps[i]);
325
+ }
326
+ return this;
327
+ }
328
+ /**
329
+ * Split the node at the given position, and optionally, if `depth` is
330
+ * greater than one, any number of nodes above that. By default, the
331
+ * parts split off will inherit the node type of the original node.
332
+ * This can be changed by passing an array of types and attributes to
333
+ * use after the split (with the outermost nodes coming first).
334
+ */
335
+ split(pos, depth = 1, typesAfter) {
336
+ return this.effect(() => this.splitUnsafe(pos, depth, typesAfter));
337
+ }
338
+ /** Like `split`, but throws on failure. */
339
+ splitUnsafe(pos, depth = 1, typesAfter) {
340
+ split(this, pos, depth, typesAfter);
341
+ return this;
342
+ }
343
+ /** Add the given mark to the inline content between `from` and `to`. */
344
+ addMark(from, to, mark) {
345
+ addMark(this, from, to, mark);
346
+ return this;
347
+ }
348
+ /**
349
+ * Remove marks from inline nodes between `from` and `to`. When `mark`
350
+ * is a single mark, remove precisely that mark. When it is a mark
351
+ * type, remove all marks of that type. When it is null, remove all
352
+ * marks of any type.
353
+ */
354
+ removeMark(from, to, mark) {
355
+ removeMark(this, from, to, mark);
356
+ return this;
357
+ }
358
+ /**
359
+ * Removes all marks and nodes from the content of the node at `pos`
360
+ * that don't match the given new parent node type. Accepts an
361
+ * optional starting content match as third argument.
362
+ */
363
+ clearIncompatible(pos, parentType, match) {
364
+ return this.effect(() => this.clearIncompatibleUnsafe(pos, parentType, match));
365
+ }
366
+ /** Like `clearIncompatible`, but throws on failure. */
367
+ clearIncompatibleUnsafe(pos, parentType, match) {
368
+ if (!this.currentDoc.nodeAtOrNull(pos)) throw new TransformError({ message: "No node at position " + pos });
369
+ clearIncompatible(this, pos, parentType, match);
370
+ return this;
371
+ }
372
+ };
373
+ export { Transform };
@@ -0,0 +1,10 @@
1
+ import { AttrStep, DocAttrStep } from "./transform/attr_step.js";
2
+ import { StepError, TransformError, TransformFailure, TransformOrModelError, isTransformFailure, isTransformOrModelError } from "./transform/errors.js";
3
+ import { MapResult, Mappable, Mapping, StepMap } from "./transform/map.js";
4
+ import { AddMarkStep, AddNodeMarkStep, RemoveMarkStep, RemoveNodeMarkStep } from "./transform/mark_step.js";
5
+ import { replaceStep } from "./transform/replace.js";
6
+ import { ReplaceAroundStep, ReplaceStep } from "./transform/replace_step.js";
7
+ import { Step, StepDeserializer, StepFromJSON, StepJSON, StepResult, applyStep } from "./transform/step.js";
8
+ import { NodeTypeWithAttrs, canJoin, canSplit, dropPoint, findWrapping, insertPoint, joinPoint, liftTarget } from "./transform/structure.js";
9
+ import { ContentInput, ReplaceFailure, StructureFailure, Transform } from "./transform/transform.js";
10
+ export { AddMarkStep, AddNodeMarkStep, AttrStep, ContentInput, DocAttrStep, MapResult, Mappable, Mapping, type NodeTypeWithAttrs, RemoveMarkStep, RemoveNodeMarkStep, ReplaceAroundStep, ReplaceFailure, ReplaceStep, Step, StepDeserializer, StepError, StepFromJSON, StepJSON, StepMap, StepResult, StructureFailure, Transform, TransformError, TransformFailure, TransformOrModelError, applyStep, canJoin, canSplit, dropPoint, findWrapping, insertPoint, isTransformFailure, isTransformOrModelError, joinPoint, liftTarget, replaceStep };
@@ -0,0 +1,10 @@
1
+ import { AttrStep, DocAttrStep } from "./transform/attr_step.js";
2
+ import { StepError, TransformError, isTransformFailure, isTransformOrModelError } from "./transform/errors.js";
3
+ import { MapResult, Mapping, StepMap } from "./transform/map.js";
4
+ import { AddMarkStep, AddNodeMarkStep, RemoveMarkStep, RemoveNodeMarkStep } from "./transform/mark_step.js";
5
+ import { replaceStep } from "./transform/replace.js";
6
+ import { ReplaceAroundStep, ReplaceStep } from "./transform/replace_step.js";
7
+ import { Step, StepFromJSON, StepResult, applyStep } from "./transform/step.js";
8
+ import { canJoin, canSplit, dropPoint, findWrapping, insertPoint, joinPoint, liftTarget } from "./transform/structure.js";
9
+ import { Transform } from "./transform/transform.js";
10
+ export { AddMarkStep, AddNodeMarkStep, AttrStep, DocAttrStep, MapResult, Mapping, RemoveMarkStep, RemoveNodeMarkStep, ReplaceAroundStep, ReplaceStep, Step, StepError, StepFromJSON, StepMap, StepResult, Transform, TransformError, applyStep, canJoin, canSplit, dropPoint, findWrapping, insertPoint, isTransformFailure, isTransformOrModelError, joinPoint, liftTarget, replaceStep };
@@ -0,0 +1,39 @@
1
+ // src/view/browser.ts
2
+ /**
3
+ * Browser detection.
4
+ *
5
+ * @internal
6
+ */
7
+ const nav = typeof navigator != "undefined" ? navigator : null;
8
+ const doc = typeof document != "undefined" ? document : null;
9
+ const agent = nav && nav.userAgent || "";
10
+ const ie_edge = /Edge\/(\d+)/.exec(agent);
11
+ const ie_upto10 = /MSIE \d/.exec(agent);
12
+ const ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(agent);
13
+ /** @internal */
14
+ const ie = !!(ie_upto10 || ie_11up || ie_edge);
15
+ /** @internal */
16
+ const ie_version = ie_upto10 ? document.documentMode : ie_11up ? +ie_11up[1] : ie_edge ? +ie_edge[1] : 0;
17
+ /** @internal */
18
+ const gecko = !ie && /gecko\/(\d+)/i.test(agent);
19
+ gecko && +(/Firefox\/(\d+)/.exec(agent) || [0, 0])[1];
20
+ const _chrome = !ie && /Chrome\/(\d+)/.exec(agent);
21
+ /** @internal */
22
+ const chrome = !!_chrome;
23
+ /** @internal */
24
+ const chrome_version = _chrome ? +_chrome[1] : 0;
25
+ /** @internal */
26
+ const safari = !ie && !!nav && /Apple Computer/.test(nav.vendor);
27
+ /** @internal */
28
+ const ios = safari && (/Mobile\/\w+/.test(agent) || !!nav && nav.maxTouchPoints > 2);
29
+ /** @internal */
30
+ const mac = ios || (nav ? /Mac/.test(nav.platform) : false);
31
+ /** @internal */
32
+ const windows = nav ? /Win/.test(nav.platform) : false;
33
+ /** @internal */
34
+ const android = /Android \d/.test(agent);
35
+ /** @internal */
36
+ const webkit = !!doc && "webkitFontSmoothing" in doc.documentElement.style;
37
+ /** @internal */
38
+ const webkit_version = webkit ? +(/\bAppleWebKit\/(\d+)/.exec(navigator.userAgent) || [0, 0])[1] : 0;
39
+ export { android, chrome, chrome_version, gecko, ie, ie_version, ios, mac, safari, webkit, webkit_version, windows };