@thomasfosterau/effect-richtext 0.0.0-stage → 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 +118 -2
  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 +206 -3
@@ -0,0 +1,305 @@
1
+ import { attempt } from "../internal/attempt.js";
2
+ import { PositionError } from "./errors.js";
3
+ import { Mark } from "./mark.js";
4
+ import * as Option from "effect/Option";
5
+ // src/model/resolvedpos.ts
6
+ const isPositionError = (u) => u instanceof PositionError;
7
+ /**
8
+ * You can resolve a position to get more information about it. Objects
9
+ * of this class represent such a resolved position, providing various
10
+ * pieces of context information, and some helper methods.
11
+ *
12
+ * Throughout this interface, methods that take an optional `depth`
13
+ * parameter will interpret `undefined` as `this.depth` and negative
14
+ * numbers as `this.depth + value`.
15
+ *
16
+ * @since 0.1.0
17
+ * @category models
18
+ */
19
+ var ResolvedPos = class ResolvedPos {
20
+ /** @internal */
21
+ constructor(pos, path, parentOffset) {
22
+ this.pos = pos;
23
+ this.path = path;
24
+ this.parentOffset = parentOffset;
25
+ this.depth = path.length / 3 - 1;
26
+ }
27
+ /** @internal */
28
+ resolveDepth(val) {
29
+ if (val == null) return this.depth;
30
+ if (val < 0) return this.depth + val;
31
+ return val;
32
+ }
33
+ /**
34
+ * The parent node that the position points into. Note that even if a
35
+ * position points into a text node, that node is not considered the
36
+ * parent—text nodes are ‘flat’ in this model, and have no content.
37
+ */
38
+ get parent() {
39
+ return this.node(this.depth);
40
+ }
41
+ /** The root node in which the position was resolved. */
42
+ get doc() {
43
+ return this.node(0);
44
+ }
45
+ /** The ancestor node at the given level. `p.node(p.depth)` is the same as `p.parent`. */
46
+ node(depth) {
47
+ return this.path[this.resolveDepth(depth) * 3];
48
+ }
49
+ /**
50
+ * The index into the ancestor at the given level. If this points at
51
+ * the 3rd node in the 2nd paragraph on the top level, for example,
52
+ * `p.index(0)` is 1 and `p.index(1)` is 2.
53
+ */
54
+ index(depth) {
55
+ return this.path[this.resolveDepth(depth) * 3 + 1];
56
+ }
57
+ /** The index pointing after this position into the ancestor at the given level. */
58
+ indexAfter(depth) {
59
+ depth = this.resolveDepth(depth);
60
+ return this.index(depth) + (depth === this.depth && !this.textOffset ? 0 : 1);
61
+ }
62
+ /** The (absolute) position at the start of the node at the given level. */
63
+ start(depth) {
64
+ depth = this.resolveDepth(depth);
65
+ return depth === 0 ? 0 : this.path[depth * 3 - 1] + 1;
66
+ }
67
+ /** The (absolute) position at the end of the node at the given level. */
68
+ end(depth) {
69
+ depth = this.resolveDepth(depth);
70
+ return this.start(depth) + this.node(depth).content.size;
71
+ }
72
+ /**
73
+ * The (absolute) position directly before the wrapping node at the
74
+ * given level, or, when `depth` is `this.depth + 1`, the original
75
+ * position. Fails for depth 0, since there is no position before the
76
+ * top-level node.
77
+ */
78
+ before(depth) {
79
+ return attempt(() => this.beforeUnsafe(depth), isPositionError);
80
+ }
81
+ /** Like `before`, but throws a `PositionError` for depth 0. */
82
+ beforeUnsafe(depth) {
83
+ depth = this.resolveDepth(depth);
84
+ if (!depth) throw new PositionError({ message: "There is no position before the top-level node" });
85
+ return depth === this.depth + 1 ? this.pos : this.path[depth * 3 - 1];
86
+ }
87
+ /**
88
+ * The (absolute) position directly after the wrapping node at the
89
+ * given level, or the original position when `depth` is
90
+ * `this.depth + 1`. Fails for depth 0.
91
+ */
92
+ after(depth) {
93
+ return attempt(() => this.afterUnsafe(depth), isPositionError);
94
+ }
95
+ /** Like `after`, but throws a `PositionError` for depth 0. */
96
+ afterUnsafe(depth) {
97
+ depth = this.resolveDepth(depth);
98
+ if (!depth) throw new PositionError({ message: "There is no position after the top-level node" });
99
+ return depth === this.depth + 1 ? this.pos : this.path[depth * 3 - 1] + this.path[depth * 3].nodeSize;
100
+ }
101
+ /**
102
+ * When this position points into a text node, this returns the
103
+ * distance between the position and the start of the text node. Will
104
+ * be zero for positions that point between nodes.
105
+ */
106
+ get textOffset() {
107
+ return this.pos - this.path[this.path.length - 1];
108
+ }
109
+ /**
110
+ * Get the node directly after the position, if any. If the position
111
+ * points into a text node, only the part of that node after the
112
+ * position is returned.
113
+ */
114
+ get nodeAfter() {
115
+ return Option.fromNullishOr(this.nodeAfterOrNull);
116
+ }
117
+ /** @internal */
118
+ get nodeAfterOrNull() {
119
+ const parent = this.parent, index = this.index(this.depth);
120
+ if (index === parent.childCount) return null;
121
+ const dOff = this.pos - this.path[this.path.length - 1], child = parent.content.content[index];
122
+ return dOff ? child.cut(dOff) : child;
123
+ }
124
+ /**
125
+ * Get the node directly before the position, if any. If the position
126
+ * points into a text node, only the part of that node before the
127
+ * position is returned.
128
+ */
129
+ get nodeBefore() {
130
+ return Option.fromNullishOr(this.nodeBeforeOrNull);
131
+ }
132
+ /** @internal */
133
+ get nodeBeforeOrNull() {
134
+ const index = this.index(this.depth);
135
+ const dOff = this.pos - this.path[this.path.length - 1];
136
+ if (dOff) return this.parent.content.content[index].cut(0, dOff);
137
+ return index === 0 ? null : this.parent.content.content[index - 1];
138
+ }
139
+ /** Get the position at the given index in the parent node at the given depth (which defaults to `this.depth`). */
140
+ posAtIndex(index, depth) {
141
+ depth = this.resolveDepth(depth);
142
+ const node = this.path[depth * 3];
143
+ let pos = depth === 0 ? 0 : this.path[depth * 3 - 1] + 1;
144
+ for (let i = 0; i < index; i++) pos += node.content.content[i].nodeSize;
145
+ return pos;
146
+ }
147
+ /**
148
+ * Get the marks at this position, factoring in the surrounding marks'
149
+ * `inclusive` property. If the position is at the start of a
150
+ * non-empty node, the marks of the node after it (if any) are
151
+ * returned.
152
+ */
153
+ marks() {
154
+ const parent = this.parent, index = this.index();
155
+ if (parent.content.size === 0) return Mark.none;
156
+ if (this.textOffset) return parent.content.content[index].marks;
157
+ let main = parent.content.content[index - 1], other = parent.content.content[index];
158
+ if (!main) {
159
+ const tmp = main;
160
+ main = other;
161
+ other = tmp;
162
+ }
163
+ let marks = main.marks;
164
+ for (let i = 0; i < marks.length; i++) if (marks[i].type.spec.inclusive === false && (!other || !marks[i].isInSet(other.marks))) marks = marks[i--].removeFromSet(marks);
165
+ return marks;
166
+ }
167
+ /**
168
+ * Get the marks after the current position, if any, except those that
169
+ * are non-inclusive and not present at position `$end`. This is
170
+ * mostly useful for getting the set of marks to preserve after a
171
+ * deletion. Will return `None` if this position is at the end of its
172
+ * parent node or its parent node isn't a textblock (in which case no
173
+ * marks should be preserved).
174
+ */
175
+ marksAcross($end) {
176
+ return Option.fromNullishOr(this.marksAcrossOrNull($end));
177
+ }
178
+ /** @internal */
179
+ marksAcrossOrNull($end) {
180
+ const after = this.parent.content.content[this.index()];
181
+ if (!after || !after.isInline) return null;
182
+ let marks = after.marks;
183
+ const next = $end.parent.content.content[$end.index()];
184
+ for (let i = 0; i < marks.length; i++) if (marks[i].type.spec.inclusive === false && (!next || !marks[i].isInSet(next.marks))) marks = marks[i--].removeFromSet(marks);
185
+ return marks;
186
+ }
187
+ /** The depth up to which this position and the given (non-resolved) position share the same parent nodes. */
188
+ sharedDepth(pos) {
189
+ for (let depth = this.depth; depth > 0; depth--) if (this.start(depth) <= pos && this.end(depth) >= pos) return depth;
190
+ return 0;
191
+ }
192
+ /**
193
+ * Returns a range based on the place where this position and the given
194
+ * position diverge around block content. If both point into the same
195
+ * textblock, for example, a range around that textblock will be
196
+ * returned. If they point into different blocks, the range around
197
+ * those blocks in their shared ancestor is returned. You can pass in
198
+ * an optional predicate that will be called with a parent node to see
199
+ * if a range into that parent is acceptable.
200
+ */
201
+ blockRange(other = this, pred) {
202
+ return Option.fromNullishOr(this.blockRangeOrNull(other, pred));
203
+ }
204
+ /** @internal */
205
+ blockRangeOrNull(other = this, pred) {
206
+ if (other.pos < this.pos) return other.blockRangeOrNull(this);
207
+ for (let d = this.depth - (this.parent.inlineContent || this.pos === other.pos ? 1 : 0); d >= 0; d--) if (other.pos <= this.end(d) && (!pred || pred(this.node(d)))) return new NodeRange(this, other, d);
208
+ return null;
209
+ }
210
+ /** Query whether the given position shares the same parent node. */
211
+ sameParent(other) {
212
+ return this.pos - this.parentOffset === other.pos - other.parentOffset;
213
+ }
214
+ /** Return the greater of this and the given position. */
215
+ max(other) {
216
+ return other.pos > this.pos ? other : this;
217
+ }
218
+ /** Return the smaller of this and the given position. */
219
+ min(other) {
220
+ return other.pos < this.pos ? other : this;
221
+ }
222
+ /** @internal */
223
+ toString() {
224
+ let str = "";
225
+ for (let i = 1; i <= this.depth; i++) str += (str ? "/" : "") + this.node(i).type.name + "_" + this.index(i - 1);
226
+ return str + ":" + this.parentOffset;
227
+ }
228
+ /** @internal */
229
+ static resolve(doc, pos) {
230
+ if (!(pos >= 0 && pos <= doc.content.size)) throw new PositionError({ message: "Position " + pos + " out of range" });
231
+ const path = [];
232
+ let start = 0, parentOffset = pos;
233
+ for (let node = doc;;) {
234
+ const { index, offset } = node.content.findIndex(parentOffset);
235
+ const rem = parentOffset - offset;
236
+ path.push(node, index, start + offset);
237
+ if (!rem) break;
238
+ node = node.content.content[index];
239
+ if (node.isText) break;
240
+ parentOffset = rem - 1;
241
+ start += offset + 1;
242
+ }
243
+ return new ResolvedPos(pos, path, parentOffset);
244
+ }
245
+ /** @internal */
246
+ static resolveCached(doc, pos) {
247
+ let cache = resolveCache.get(doc);
248
+ if (cache) for (let i = 0; i < cache.elts.length; i++) {
249
+ const elt = cache.elts[i];
250
+ if (elt.pos === pos) return elt;
251
+ }
252
+ else resolveCache.set(doc, cache = new ResolveCache());
253
+ const result = cache.elts[cache.i] = ResolvedPos.resolve(doc, pos);
254
+ cache.i = (cache.i + 1) % resolveCacheSize;
255
+ return result;
256
+ }
257
+ };
258
+ var ResolveCache = class {
259
+ constructor() {
260
+ this.elts = [];
261
+ this.i = 0;
262
+ }
263
+ };
264
+ const resolveCacheSize = 12;
265
+ const resolveCache = /* @__PURE__ */ new WeakMap();
266
+ /**
267
+ * Represents a flat range of content, i.e. one that starts and ends in
268
+ * the same node.
269
+ *
270
+ * @since 0.1.0
271
+ * @category models
272
+ */
273
+ var NodeRange = class {
274
+ /**
275
+ * Construct a node range. `$from` and `$to` should point into the
276
+ * same node until at least the given `depth`, since a node range
277
+ * denotes an adjacent set of nodes in a single parent node.
278
+ */
279
+ constructor($from, $to, depth) {
280
+ this.$from = $from;
281
+ this.$to = $to;
282
+ this.depth = depth;
283
+ }
284
+ /** The position at the start of the range. */
285
+ get start() {
286
+ return this.$from.beforeUnsafe(this.depth + 1);
287
+ }
288
+ /** The position at the end of the range. */
289
+ get end() {
290
+ return this.$to.afterUnsafe(this.depth + 1);
291
+ }
292
+ /** The parent node that the range points into. */
293
+ get parent() {
294
+ return this.$from.node(this.depth);
295
+ }
296
+ /** The start index of the range in the parent node. */
297
+ get startIndex() {
298
+ return this.$from.index(this.depth);
299
+ }
300
+ /** The end index of the range in the parent node. */
301
+ get endIndex() {
302
+ return this.$to.indexAfter(this.depth);
303
+ }
304
+ };
305
+ export { NodeRange, ResolvedPos };