@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.
- package/LICENSE +48 -0
- package/README.md +117 -1
- package/dist/_virtual/_rolldown/runtime.js +12 -0
- package/dist/commands/commands.d.ts +323 -0
- package/dist/commands/commands.js +722 -0
- package/dist/commands/internal.js +43 -0
- package/dist/commands/keymaps.d.ts +46 -0
- package/dist/commands/keymaps.js +64 -0
- package/dist/commands.d.ts +3 -0
- package/dist/commands.js +3 -0
- package/dist/compat/commands.d.ts +250 -0
- package/dist/compat/commands.js +275 -0
- package/dist/compat/internal/core.d.ts +20 -0
- package/dist/compat/internal/core.js +148 -0
- package/dist/compat/internal/props.js +82 -0
- package/dist/compat/keymap.d.ts +21 -0
- package/dist/compat/keymap.js +38 -0
- package/dist/compat/model.d.ts +893 -0
- package/dist/compat/model.js +1212 -0
- package/dist/compat/orderedmap.d.ts +74 -0
- package/dist/compat/orderedmap.js +124 -0
- package/dist/compat/schema-basic.d.ts +38 -0
- package/dist/compat/schema-basic.js +238 -0
- package/dist/compat/schema-list.d.ts +81 -0
- package/dist/compat/schema-list.js +156 -0
- package/dist/compat/state.d.ts +415 -0
- package/dist/compat/state.js +689 -0
- package/dist/compat/test-builder.d.ts +98 -0
- package/dist/compat/test-builder.js +197 -0
- package/dist/compat/transform.d.ts +458 -0
- package/dist/compat/transform.js +803 -0
- package/dist/compat/view.d.ts +411 -0
- package/dist/compat/view.js +409 -0
- package/dist/dropcursor.d.ts +46 -0
- package/dist/dropcursor.js +176 -0
- package/dist/extensions/defaults.d.ts +716 -0
- package/dist/extensions/defaults.js +209 -0
- package/dist/extensions/editor.d.ts +246 -0
- package/dist/extensions/editor.js +271 -0
- package/dist/extensions/extension.d.ts +375 -0
- package/dist/extensions/extension.js +233 -0
- package/dist/extensions.d.ts +4 -0
- package/dist/extensions.js +4 -0
- package/dist/gapcursor.d.ts +66 -0
- package/dist/gapcursor.js +273 -0
- package/dist/history.d.ts +178 -0
- package/dist/history.js +412 -0
- package/dist/html.d.ts +158 -0
- package/dist/html.js +164 -0
- package/dist/inputrules.d.ts +271 -0
- package/dist/inputrules.js +321 -0
- package/dist/internal/attempt.js +15 -0
- package/dist/internal/json.js +29 -0
- package/dist/keymap/keymap.d.ts +130 -0
- package/dist/keymap/keymap.js +159 -0
- package/dist/keymap.d.ts +2 -0
- package/dist/keymap.js +1 -0
- package/dist/markdown/errors.d.ts +23 -0
- package/dist/markdown/errors.js +26 -0
- package/dist/markdown/from_markdown.d.ts +185 -0
- package/dist/markdown/from_markdown.js +266 -0
- package/dist/markdown/schema.d.ts +522 -0
- package/dist/markdown/schema.js +292 -0
- package/dist/markdown/to_markdown.d.ts +251 -0
- package/dist/markdown/to_markdown.js +413 -0
- package/dist/markdown.d.ts +5 -0
- package/dist/markdown.js +5 -0
- package/dist/model/attrsCodec.js +48 -0
- package/dist/model/comparedeep.js +17 -0
- package/dist/model/content.d.ts +232 -0
- package/dist/model/content.js +630 -0
- package/dist/model/diff.js +66 -0
- package/dist/model/dom.d.ts +3 -0
- package/dist/model/errors.d.ts +90 -0
- package/dist/model/errors.js +76 -0
- package/dist/model/fragment.d.ts +131 -0
- package/dist/model/fragment.js +262 -0
- package/dist/model/from_dom.d.ts +299 -0
- package/dist/model/from_dom.js +618 -0
- package/dist/model/json.d.ts +37 -0
- package/dist/model/json.js +126 -0
- package/dist/model/mark.d.ts +73 -0
- package/dist/model/mark.js +121 -0
- package/dist/model/node.d.ts +267 -0
- package/dist/model/node.js +434 -0
- package/dist/model/replace.d.ts +78 -0
- package/dist/model/replace.js +207 -0
- package/dist/model/resolvedpos.d.ts +196 -0
- package/dist/model/resolvedpos.js +305 -0
- package/dist/model/schema.d.ts +740 -0
- package/dist/model/schema.js +451 -0
- package/dist/model/to_dom.d.ts +169 -0
- package/dist/model/to_dom.js +238 -0
- package/dist/model.d.ts +12 -0
- package/dist/model.js +12 -0
- package/dist/placeholder.d.ts +53 -0
- package/dist/placeholder.js +79 -0
- package/dist/reactive/observer.d.ts +54 -0
- package/dist/reactive/observer.js +61 -0
- package/dist/reactive/selectors.d.ts +22 -0
- package/dist/reactive/selectors.js +61 -0
- package/dist/reactive/stateref.d.ts +72 -0
- package/dist/reactive/stateref.js +71 -0
- package/dist/reactive/streams.d.ts +83 -0
- package/dist/reactive/streams.js +85 -0
- package/dist/reactive.d.ts +16 -0
- package/dist/reactive.js +26 -0
- package/dist/schema-basic.d.ts +448 -0
- package/dist/schema-basic.js +269 -0
- package/dist/schema-list/commands.d.ts +66 -0
- package/dist/schema-list/commands.js +203 -0
- package/dist/schema-list.d.ts +92 -0
- package/dist/schema-list.js +100 -0
- package/dist/state/errors.d.ts +39 -0
- package/dist/state/errors.js +32 -0
- package/dist/state/plugin.d.ts +232 -0
- package/dist/state/plugin.js +82 -0
- package/dist/state/selection.d.ts +297 -0
- package/dist/state/selection.js +486 -0
- package/dist/state/state.d.ts +212 -0
- package/dist/state/state.js +489 -0
- package/dist/state/transaction.d.ts +145 -0
- package/dist/state/transaction.js +195 -0
- package/dist/state.d.ts +6 -0
- package/dist/state.js +6 -0
- package/dist/test-builder.d.ts +3582 -0
- package/dist/test-builder.js +239 -0
- package/dist/transform/attr_step.d.ts +60 -0
- package/dist/transform/attr_step.js +105 -0
- package/dist/transform/errors.d.ts +50 -0
- package/dist/transform/errors.js +35 -0
- package/dist/transform/map.d.ts +182 -0
- package/dist/transform/map.js +280 -0
- package/dist/transform/mark.js +98 -0
- package/dist/transform/mark_set_step.js +69 -0
- package/dist/transform/mark_step.d.ts +113 -0
- package/dist/transform/mark_step.js +225 -0
- package/dist/transform/replace.d.ts +18 -0
- package/dist/transform/replace.js +381 -0
- package/dist/transform/replace_step.d.ts +109 -0
- package/dist/transform/replace_step.js +175 -0
- package/dist/transform/step.d.ts +157 -0
- package/dist/transform/step.js +168 -0
- package/dist/transform/structure.d.ts +89 -0
- package/dist/transform/structure.js +350 -0
- package/dist/transform/transform.d.ts +248 -0
- package/dist/transform/transform.js +373 -0
- package/dist/transform.d.ts +10 -0
- package/dist/transform.js +10 -0
- package/dist/view/browser.js +39 -0
- package/dist/view/capturekeys.js +282 -0
- package/dist/view/clipboard.d.ts +8 -0
- package/dist/view/clipboard.js +245 -0
- package/dist/view/decoration.d.ts +339 -0
- package/dist/view/decoration.js +566 -0
- package/dist/view/dom.d.ts +18 -0
- package/dist/view/dom.js +140 -0
- package/dist/view/domchange.js +295 -0
- package/dist/view/domcoords.d.ts +22 -0
- package/dist/view/domcoords.js +448 -0
- package/dist/view/domobserver.d.ts +47 -0
- package/dist/view/domobserver.js +328 -0
- package/dist/view/errors.d.ts +18 -0
- package/dist/view/errors.js +21 -0
- package/dist/view/input.d.ts +58 -0
- package/dist/view/input.js +704 -0
- package/dist/view/selection.js +198 -0
- package/dist/view/view.d.ts +699 -0
- package/dist/view/view.js +623 -0
- package/dist/view/viewdesc.d.ts +236 -0
- package/dist/view/viewdesc.js +1205 -0
- package/dist/view-css.d.ts +43 -0
- package/dist/view-css.js +124 -0
- package/dist/view.d.ts +6 -0
- package/dist/view.js +4 -0
- package/package.json +200 -4
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import { Plugin } from "./state/plugin.js";
|
|
2
|
+
import { TextSelection } from "./state/selection.js";
|
|
3
|
+
import { canJoin, findWrappingOrNull } from "./transform/structure.js";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
import * as Option from "effect/Option";
|
|
6
|
+
import * as Predicate from "effect/Predicate";
|
|
7
|
+
// src/inputrules.ts
|
|
8
|
+
/**
|
|
9
|
+
* Input rules: regular expressions describing a piece of text that,
|
|
10
|
+
* when typed, causes something to happen. Ported from
|
|
11
|
+
* `prosemirror-inputrules`.
|
|
12
|
+
*
|
|
13
|
+
* ```ts skip-type-checking
|
|
14
|
+
* const plugin = inputRules({
|
|
15
|
+
* rules: [...smartQuotes, emDash, wrappingInputRule(/^\s*>\s$/, schema.nodes.blockquote)]
|
|
16
|
+
* })
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* Rule handlers may return a transaction (or `null`), like in
|
|
20
|
+
* ProseMirror, but also an `Option<Transaction>` or an
|
|
21
|
+
* `Effect<Option<Transaction>, E, R>`. The errors and requirements of
|
|
22
|
+
* effectful rules end up in the plugin's type.
|
|
23
|
+
*
|
|
24
|
+
* @since 0.1.0
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* @since 0.1.0
|
|
28
|
+
* @category symbols
|
|
29
|
+
*/
|
|
30
|
+
const InputRuleTypeId = Symbol.for("effect-richtext/inputrules/InputRule");
|
|
31
|
+
/**
|
|
32
|
+
* Input rules are regular expressions describing a piece of text that,
|
|
33
|
+
* when typed, causes something to happen. This might be changing two
|
|
34
|
+
* dashes into an emdash, wrapping a paragraph starting with `"> "` into
|
|
35
|
+
* a blockquote, or something entirely different.
|
|
36
|
+
*
|
|
37
|
+
* @since 0.1.0
|
|
38
|
+
* @category models
|
|
39
|
+
*/
|
|
40
|
+
var InputRule = class {
|
|
41
|
+
/**
|
|
42
|
+
* Create an input rule. The rule applies when the user typed something
|
|
43
|
+
* and the text directly in front of the cursor matches `match`, which
|
|
44
|
+
* should end with `$`.
|
|
45
|
+
*
|
|
46
|
+
* The `handler` can be a string, in which case the matched text, or
|
|
47
|
+
* the first matched group in the regexp, is replaced by that string.
|
|
48
|
+
*
|
|
49
|
+
* Or it can be a function, which will be called with the match array
|
|
50
|
+
* produced by `RegExp.exec`, as well as the start and end of the
|
|
51
|
+
* matched range, and which can return a transaction that describes the
|
|
52
|
+
* rule's effect, or `null` to indicate the input was not handled. It
|
|
53
|
+
* may also return an `Option` of a transaction, or an Effect producing
|
|
54
|
+
* one.
|
|
55
|
+
*/
|
|
56
|
+
constructor(match, handler, options = {}) {
|
|
57
|
+
this.match = match;
|
|
58
|
+
this.handler = Predicate.isString(handler) ? stringHandler(handler) : handler;
|
|
59
|
+
this.undoable = options.undoable !== false;
|
|
60
|
+
this.inCode = options.inCode || false;
|
|
61
|
+
this.inCodeMark = options.inCodeMark !== false;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
function stringHandler(string) {
|
|
65
|
+
return (state, match, start, end) => {
|
|
66
|
+
let insert = string;
|
|
67
|
+
if (match[1]) {
|
|
68
|
+
const offset = match[0].lastIndexOf(match[1]);
|
|
69
|
+
insert += match[0].slice(offset + match[1].length);
|
|
70
|
+
start += offset;
|
|
71
|
+
const cutOff = start - end;
|
|
72
|
+
if (cutOff > 0) {
|
|
73
|
+
insert = match[0].slice(offset - cutOff, offset) + insert;
|
|
74
|
+
start = end;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return state.tr.insertTextUnsafe(insert, start, end);
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
const MAX_MATCH = 500;
|
|
81
|
+
/**
|
|
82
|
+
* Create an input rules plugin. When enabled, it will cause text input
|
|
83
|
+
* that matches any of the given rules to trigger the rule's action.
|
|
84
|
+
*
|
|
85
|
+
* Rules are tried in order. Rules whose handler returns an Effect run
|
|
86
|
+
* with the view's context: when such an effect completes synchronously,
|
|
87
|
+
* it behaves exactly like a plain rule. When it is asynchronous, the
|
|
88
|
+
* input is considered handled; when it eventually finds no transaction
|
|
89
|
+
* (or fails), the typed text is inserted, and when it produces a
|
|
90
|
+
* transaction, it is dispatched—both only if the editor state didn't
|
|
91
|
+
* change in the meantime.
|
|
92
|
+
*
|
|
93
|
+
* @since 0.1.0
|
|
94
|
+
* @category constructors
|
|
95
|
+
*/
|
|
96
|
+
const inputRules = ({ rules }) => {
|
|
97
|
+
const plugin = new Plugin({
|
|
98
|
+
state: {
|
|
99
|
+
init: () => Option.none(),
|
|
100
|
+
apply(tr, prev) {
|
|
101
|
+
const stored = tr.getMeta(plugin);
|
|
102
|
+
if (Option.isSome(stored)) return stored;
|
|
103
|
+
return tr.selectionSet || tr.docChanged ? Option.none() : prev;
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
props: {
|
|
107
|
+
handleTextInput(view, from, to, text, deflt) {
|
|
108
|
+
return run(view, from, to, text, rules, plugin, deflt);
|
|
109
|
+
},
|
|
110
|
+
handleDOMEvents: { compositionend: (view) => {
|
|
111
|
+
setTimeout(() => {
|
|
112
|
+
if (view.isDestroyed) return;
|
|
113
|
+
const sel = view.state.selection;
|
|
114
|
+
const $cursor = sel instanceof TextSelection ? sel.$cursorOrNull : null;
|
|
115
|
+
if ($cursor) view.runHandler(run(view, $cursor.pos, $cursor.pos, "", rules, plugin, void 0));
|
|
116
|
+
});
|
|
117
|
+
return false;
|
|
118
|
+
} }
|
|
119
|
+
},
|
|
120
|
+
isInputRules: true
|
|
121
|
+
});
|
|
122
|
+
return plugin;
|
|
123
|
+
};
|
|
124
|
+
const hasCodeMark = (marks) => marks.some((m) => m.type.spec.code);
|
|
125
|
+
function run(view, from, to, text, rules, plugin, deflt) {
|
|
126
|
+
if (view.composing) return false;
|
|
127
|
+
const state = view.state, $from = state.doc.resolveUnsafe(from);
|
|
128
|
+
return tryRules({
|
|
129
|
+
view,
|
|
130
|
+
state,
|
|
131
|
+
$from,
|
|
132
|
+
from,
|
|
133
|
+
to,
|
|
134
|
+
text,
|
|
135
|
+
textBefore: $from.parent.textBetween(Math.max(0, $from.parentOffset - MAX_MATCH), $from.parentOffset, null, "") + text,
|
|
136
|
+
rules,
|
|
137
|
+
plugin,
|
|
138
|
+
deflt,
|
|
139
|
+
sync: true
|
|
140
|
+
}, 0);
|
|
141
|
+
}
|
|
142
|
+
function tryRules(cx, start) {
|
|
143
|
+
const { $from, rules, state, text, textBefore } = cx;
|
|
144
|
+
for (let i = start; i < rules.length; i++) {
|
|
145
|
+
const rule = rules[i];
|
|
146
|
+
if (!rule.inCodeMark && hasCodeMark($from.marks())) continue;
|
|
147
|
+
if ($from.parent.type.spec.code) {
|
|
148
|
+
if (!rule.inCode) continue;
|
|
149
|
+
} else if (rule.inCode === "only") continue;
|
|
150
|
+
const match = rule.match.exec(textBefore);
|
|
151
|
+
if (!match || match[0].length < text.length) continue;
|
|
152
|
+
const startPos = cx.from - (match[0].length - text.length);
|
|
153
|
+
if (!rule.inCodeMark) {
|
|
154
|
+
let hasMark = false;
|
|
155
|
+
state.doc.nodesBetween(startPos, $from.pos, (node) => {
|
|
156
|
+
if (node.isInline && hasCodeMark(node.marks)) hasMark = true;
|
|
157
|
+
});
|
|
158
|
+
if (hasMark) continue;
|
|
159
|
+
}
|
|
160
|
+
const result = rule.handler(state, match, startPos, cx.to);
|
|
161
|
+
if (Effect.isEffect(result)) return runEffectRule(cx, rule, result, i + 1);
|
|
162
|
+
const tr = Option.isOption(result) ? Option.getOrNull(result) : result;
|
|
163
|
+
if (!tr) continue;
|
|
164
|
+
return applyRule(cx, rule, tr);
|
|
165
|
+
}
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
function applyRule(cx, rule, tr) {
|
|
169
|
+
if (rule.undoable) tr.setMeta(cx.plugin, {
|
|
170
|
+
transform: tr,
|
|
171
|
+
from: cx.from,
|
|
172
|
+
to: cx.to,
|
|
173
|
+
text: cx.text
|
|
174
|
+
});
|
|
175
|
+
return Effect.as(cx.view.dispatch(tr), true);
|
|
176
|
+
}
|
|
177
|
+
function fallback(cx) {
|
|
178
|
+
if (cx.sync || !cx.deflt || cx.view.isDestroyed || cx.view.state !== cx.state) return Effect.succeed(false);
|
|
179
|
+
return Effect.as(cx.view.dispatch(cx.deflt()), true);
|
|
180
|
+
}
|
|
181
|
+
function runEffectRule(cx, rule, effect, next) {
|
|
182
|
+
if (cx.sync) queueMicrotask(() => cx.sync = false);
|
|
183
|
+
return effect.pipe(Effect.flatMap((result) => {
|
|
184
|
+
if (Option.isSome(result)) {
|
|
185
|
+
if (cx.view.isDestroyed || cx.view.state !== cx.state) return Effect.succeed(true);
|
|
186
|
+
return applyRule(cx, rule, result.value);
|
|
187
|
+
}
|
|
188
|
+
const rest = tryRules(cx, next);
|
|
189
|
+
if (Effect.isEffect(rest)) return rest;
|
|
190
|
+
return fallback(cx);
|
|
191
|
+
}), Effect.tapCause(() => fallback(cx)));
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* This is a command that will undo an input rule, if applying such a
|
|
195
|
+
* rule was the last thing that the user did.
|
|
196
|
+
*
|
|
197
|
+
* @since 0.1.0
|
|
198
|
+
* @category commands
|
|
199
|
+
*/
|
|
200
|
+
const undoInputRule = (state, dispatch) => Effect.suspend(() => {
|
|
201
|
+
const plugins = state.plugins;
|
|
202
|
+
for (let i = 0; i < plugins.length; i++) {
|
|
203
|
+
const plugin = plugins[i];
|
|
204
|
+
if (!plugin.spec.isInputRules) continue;
|
|
205
|
+
const undoable = Option.getOrNull(Option.flatten(plugin.getState(state)));
|
|
206
|
+
if (!undoable) continue;
|
|
207
|
+
if (!dispatch) return Effect.succeed(true);
|
|
208
|
+
const tr = state.tr, toUndo = undoable.transform;
|
|
209
|
+
for (let j = toUndo.steps.length - 1; j >= 0; j--) tr.stepUnsafe(toUndo.steps[j].invert(toUndo.docs[j]));
|
|
210
|
+
if (undoable.text) {
|
|
211
|
+
const marks = tr.doc.resolveUnsafe(undoable.from).marks();
|
|
212
|
+
tr.replaceWithUnsafe(undoable.from, undoable.to, state.schema.textUnsafe(undoable.text, marks));
|
|
213
|
+
} else tr.deleteUnsafe(undoable.from, undoable.to);
|
|
214
|
+
return Effect.as(dispatch(tr), true);
|
|
215
|
+
}
|
|
216
|
+
return Effect.succeed(false);
|
|
217
|
+
});
|
|
218
|
+
const resolveAttrs = (getAttrs, match) => Predicate.isFunction(getAttrs) ? getAttrs(match) : getAttrs;
|
|
219
|
+
/**
|
|
220
|
+
* Build an input rule for automatically wrapping a textblock when a
|
|
221
|
+
* given string is typed. The `regexp` argument is directly passed
|
|
222
|
+
* through to the `InputRule` constructor. You'll probably want the
|
|
223
|
+
* regexp to start with `^`, so that the pattern can only occur at the
|
|
224
|
+
* start of a textblock.
|
|
225
|
+
*
|
|
226
|
+
* `nodeType` is the type of node to wrap in. If it needs attributes,
|
|
227
|
+
* you can either pass them directly, or pass a function that will
|
|
228
|
+
* compute them from the regular expression match.
|
|
229
|
+
*
|
|
230
|
+
* By default, if there's a node with the same type above the newly
|
|
231
|
+
* wrapped node, the rule will try to join those two nodes. You can pass
|
|
232
|
+
* a join predicate, which takes a regular expression match and the node
|
|
233
|
+
* before the wrapped node, and can return a boolean to indicate whether
|
|
234
|
+
* a join should happen.
|
|
235
|
+
*
|
|
236
|
+
* @since 0.1.0
|
|
237
|
+
* @category constructors
|
|
238
|
+
*/
|
|
239
|
+
const wrappingInputRule = (regexp, nodeType, getAttrs = null, joinPredicate) => new InputRule(regexp, (state, match, start, end) => {
|
|
240
|
+
const attrs = resolveAttrs(getAttrs, match);
|
|
241
|
+
const tr = state.tr.deleteUnsafe(start, end);
|
|
242
|
+
const range = tr.doc.resolveUnsafe(start).blockRangeOrNull();
|
|
243
|
+
const wrapping = range && findWrappingOrNull(range, nodeType, attrs);
|
|
244
|
+
if (!wrapping) return null;
|
|
245
|
+
tr.wrapUnsafe(range, wrapping);
|
|
246
|
+
const before = tr.doc.resolveUnsafe(start - 1).nodeBeforeOrNull;
|
|
247
|
+
if (before && before.type === nodeType && canJoin(tr.doc, start - 1) && (!joinPredicate || joinPredicate(match, before))) tr.joinUnsafe(start - 1);
|
|
248
|
+
return tr;
|
|
249
|
+
});
|
|
250
|
+
/**
|
|
251
|
+
* Build an input rule that changes the type of a textblock when the
|
|
252
|
+
* matched text is typed into it. You'll usually want to start your
|
|
253
|
+
* regexp with `^` so that it is only matched at the start of a
|
|
254
|
+
* textblock. The optional `getAttrs` parameter can be used to compute
|
|
255
|
+
* the new node's attributes, and works the same as in the
|
|
256
|
+
* `wrappingInputRule` function.
|
|
257
|
+
*
|
|
258
|
+
* @since 0.1.0
|
|
259
|
+
* @category constructors
|
|
260
|
+
*/
|
|
261
|
+
const textblockTypeInputRule = (regexp, nodeType, getAttrs = null) => new InputRule(regexp, (state, match, start, end) => {
|
|
262
|
+
const $start = state.doc.resolveUnsafe(start);
|
|
263
|
+
const attrs = resolveAttrs(getAttrs, match);
|
|
264
|
+
if (!$start.node(-1).canReplaceWith($start.index(-1), $start.indexAfter(-1), nodeType)) return null;
|
|
265
|
+
return state.tr.deleteUnsafe(start, end).setBlockTypeUnsafe(start, start, nodeType, attrs);
|
|
266
|
+
});
|
|
267
|
+
/**
|
|
268
|
+
* Converts double dashes to an emdash.
|
|
269
|
+
*
|
|
270
|
+
* @since 0.1.0
|
|
271
|
+
* @category rules
|
|
272
|
+
*/
|
|
273
|
+
const emDash = new InputRule(/--$/, "—", { inCodeMark: false });
|
|
274
|
+
/**
|
|
275
|
+
* Converts three dots to an ellipsis character.
|
|
276
|
+
*
|
|
277
|
+
* @since 0.1.0
|
|
278
|
+
* @category rules
|
|
279
|
+
*/
|
|
280
|
+
const ellipsis = new InputRule(/\.\.\.$/, "…", { inCodeMark: false });
|
|
281
|
+
/**
|
|
282
|
+
* “Smart” opening double quotes.
|
|
283
|
+
*
|
|
284
|
+
* @since 0.1.0
|
|
285
|
+
* @category rules
|
|
286
|
+
*/
|
|
287
|
+
const openDoubleQuote = new InputRule(/(?:^|[\s{[(<'"‘“])(")$/, "“", { inCodeMark: false });
|
|
288
|
+
/**
|
|
289
|
+
* “Smart” closing double quotes.
|
|
290
|
+
*
|
|
291
|
+
* @since 0.1.0
|
|
292
|
+
* @category rules
|
|
293
|
+
*/
|
|
294
|
+
const closeDoubleQuote = new InputRule(/"$/, "”", { inCodeMark: false });
|
|
295
|
+
/**
|
|
296
|
+
* “Smart” opening single quotes.
|
|
297
|
+
*
|
|
298
|
+
* @since 0.1.0
|
|
299
|
+
* @category rules
|
|
300
|
+
*/
|
|
301
|
+
const openSingleQuote = new InputRule(/(?:^|[\s{[(<'"‘“])(')$/, "‘", { inCodeMark: false });
|
|
302
|
+
/**
|
|
303
|
+
* “Smart” closing single quotes.
|
|
304
|
+
*
|
|
305
|
+
* @since 0.1.0
|
|
306
|
+
* @category rules
|
|
307
|
+
*/
|
|
308
|
+
const closeSingleQuote = new InputRule(/'$/, "’", { inCodeMark: false });
|
|
309
|
+
/**
|
|
310
|
+
* Smart-quote related input rules.
|
|
311
|
+
*
|
|
312
|
+
* @since 0.1.0
|
|
313
|
+
* @category rules
|
|
314
|
+
*/
|
|
315
|
+
const smartQuotes = [
|
|
316
|
+
openDoubleQuote,
|
|
317
|
+
closeDoubleQuote,
|
|
318
|
+
openSingleQuote,
|
|
319
|
+
closeSingleQuote
|
|
320
|
+
];
|
|
321
|
+
export { InputRule, InputRuleTypeId, closeDoubleQuote, closeSingleQuote, ellipsis, emDash, inputRules, openDoubleQuote, openSingleQuote, smartQuotes, textblockTypeInputRule, undoInputRule, wrappingInputRule };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as Result from "effect/Result";
|
|
3
|
+
// src/internal/attempt.ts
|
|
4
|
+
/**
|
|
5
|
+
* Lift a synchronous computation that signals expected failure by
|
|
6
|
+
* throwing a tagged error (as recognised by `isExpected`) into an
|
|
7
|
+
* Effect. Other exceptions become defects.
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
const attempt = (f, isExpected) => Effect.suspend(() => Result.match(Result.try(f), {
|
|
12
|
+
onSuccess: Effect.succeed,
|
|
13
|
+
onFailure: (e) => isExpected(e) ? Effect.fail(e) : Effect.die(e)
|
|
14
|
+
}));
|
|
15
|
+
export { attempt };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as Option from "effect/Option";
|
|
2
|
+
import * as Schema from "effect/Schema";
|
|
3
|
+
// src/internal/json.ts
|
|
4
|
+
const UnknownFromJsonString = /* @__PURE__ */ Schema.fromJsonString(Schema.Unknown);
|
|
5
|
+
const JsonFromJsonString = /* @__PURE__ */ Schema.fromJsonString(Schema.Json);
|
|
6
|
+
const encodeJsonString = /* @__PURE__ */ Schema.encodeOption(UnknownFromJsonString);
|
|
7
|
+
const decodeJsonString = /* @__PURE__ */ Schema.decodeOption(JsonFromJsonString);
|
|
8
|
+
/**
|
|
9
|
+
* Serialize a value as a JSON string (calling `toJSON` where defined, as
|
|
10
|
+
* `JSON.stringify` does), or `None` when it has no JSON form (`undefined`,
|
|
11
|
+
* a function, a cycle, a `BigInt`).
|
|
12
|
+
*
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
const stringifyJson = (value) => encodeJsonString(value);
|
|
16
|
+
/**
|
|
17
|
+
* Parse a JSON string, or `None` when it is not valid JSON.
|
|
18
|
+
*
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
const parseJson = (text) => decodeJsonString(text);
|
|
22
|
+
/**
|
|
23
|
+
* Render a value for an error or debug message: its JSON form, or
|
|
24
|
+
* `String(value)` when it has none.
|
|
25
|
+
*
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
const showJson = (value) => Option.getOrElse(stringifyJson(value), () => String(value));
|
|
29
|
+
export { parseJson, showJson, stringifyJson };
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { AnySchema } from "../model/schema.js";
|
|
2
|
+
import "../model.js";
|
|
3
|
+
import "../state.js";
|
|
4
|
+
import { Command } from "../state/transaction.js";
|
|
5
|
+
import { Plugin } from "../state/plugin.js";
|
|
6
|
+
import { EditorView } from "../view/view.js";
|
|
7
|
+
import * as Effect from "effect/Effect";
|
|
8
|
+
import * as Schema from "effect/Schema";
|
|
9
|
+
declare const KeymapError_base: Schema.Class<KeymapError, Schema.TaggedStruct<"KeymapError", {
|
|
10
|
+
readonly message: Schema.String;
|
|
11
|
+
}>, import("effect/Cause").YieldableError>;
|
|
12
|
+
/**
|
|
13
|
+
* An invalid keymap: a key name with an unrecognized modifier, or two
|
|
14
|
+
* bindings for the same key.
|
|
15
|
+
*
|
|
16
|
+
* @since 0.1.0
|
|
17
|
+
* @category errors
|
|
18
|
+
*/
|
|
19
|
+
export declare class KeymapError extends KeymapError_base {}
|
|
20
|
+
/**
|
|
21
|
+
* A set of key bindings, mapping key names to commands.
|
|
22
|
+
*
|
|
23
|
+
* @since 0.1.0
|
|
24
|
+
* @category models
|
|
25
|
+
*/
|
|
26
|
+
export interface Bindings {
|
|
27
|
+
readonly [key: string]: Command<any, any, any>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The union of the error types of the commands in a set of bindings.
|
|
31
|
+
*
|
|
32
|
+
* @since 0.1.0
|
|
33
|
+
* @category type-level
|
|
34
|
+
*/
|
|
35
|
+
export type BindingsError<B extends Bindings> = { [K in keyof B]: B[K] extends ((...args: any) => Effect.Effect<any, infer E, any>) ? E : never; }[keyof B];
|
|
36
|
+
/**
|
|
37
|
+
* The union of the requirements of the commands in a set of bindings.
|
|
38
|
+
*
|
|
39
|
+
* @since 0.1.0
|
|
40
|
+
* @category type-level
|
|
41
|
+
*/
|
|
42
|
+
export type BindingsRequirements<B extends Bindings> = { [K in keyof B]: B[K] extends ((...args: any) => Effect.Effect<any, any, infer R>) ? R : never; }[keyof B];
|
|
43
|
+
/**
|
|
44
|
+
* The editor view a keydown handler receives. Its `dispatch` is passed
|
|
45
|
+
* to bound commands, and the view itself as their third argument.
|
|
46
|
+
*
|
|
47
|
+
* @since 0.1.0
|
|
48
|
+
* @category models
|
|
49
|
+
*/
|
|
50
|
+
export type KeymapView<Sc extends AnySchema = AnySchema> = EditorView<Sc, any, any>;
|
|
51
|
+
/**
|
|
52
|
+
* A keydown handler, as created by `keydownHandler`.
|
|
53
|
+
*
|
|
54
|
+
* @since 0.1.0
|
|
55
|
+
* @category models
|
|
56
|
+
*/
|
|
57
|
+
export type KeydownHandler<E = never, R = never> = (view: KeymapView<any>, event: KeyboardEvent) => Effect.Effect<boolean, E, R>;
|
|
58
|
+
/**
|
|
59
|
+
* Normalize a key name (such as `"Mod-Shift-a"`) into the canonical
|
|
60
|
+
* form used for lookups (`"Shift-Ctrl-a"` on non-Mac platforms).
|
|
61
|
+
* Throws a `KeymapError` for unrecognized modifiers.
|
|
62
|
+
*
|
|
63
|
+
* @since 0.1.0
|
|
64
|
+
* @category utils
|
|
65
|
+
*/
|
|
66
|
+
export declare function normalizeKeyName(name: string): string;
|
|
67
|
+
/**
|
|
68
|
+
* Normalize the key names of a set of bindings. Throws a `KeymapError`
|
|
69
|
+
* for invalid or duplicate key names.
|
|
70
|
+
*
|
|
71
|
+
* @internal
|
|
72
|
+
*/
|
|
73
|
+
export declare function normalizeBindings<A>(map: {
|
|
74
|
+
readonly [key: string]: A;
|
|
75
|
+
}): Record<string, A>;
|
|
76
|
+
/**
|
|
77
|
+
* Find the bindings matching a keydown event, in the order in which
|
|
78
|
+
* they should be tried.
|
|
79
|
+
*
|
|
80
|
+
* @internal
|
|
81
|
+
*/
|
|
82
|
+
export declare function matchBindings<A>(map: Record<string, A>, event: KeyboardEvent): Array<A>;
|
|
83
|
+
/**
|
|
84
|
+
* Create a keymap plugin for the given set of bindings.
|
|
85
|
+
*
|
|
86
|
+
* Bindings should map key names to commands, which will be called with
|
|
87
|
+
* `(state, dispatch, view)` arguments, and should succeed with `true`
|
|
88
|
+
* when they've handled the key. Note that the view argument isn't part
|
|
89
|
+
* of the command protocol, but can be used as an escape hatch if a
|
|
90
|
+
* binding needs to directly interact with the UI.
|
|
91
|
+
*
|
|
92
|
+
* Key names may be strings like `"Shift-Ctrl-Enter"`—a key identifier
|
|
93
|
+
* prefixed with zero or more modifiers. Key identifiers are based on
|
|
94
|
+
* the strings that can appear in `KeyEvent.key`. Use lowercase letters
|
|
95
|
+
* to refer to letter keys (or uppercase letters if you want shift to be
|
|
96
|
+
* held). You may use `"Space"` as an alias for the `" "` name.
|
|
97
|
+
*
|
|
98
|
+
* Modifiers can be given in any order. `Shift-` (or `s-`), `Alt-` (or
|
|
99
|
+
* `a-`), `Ctrl-` (or `c-` or `Control-`) and `Cmd-` (or `m-` or
|
|
100
|
+
* `Meta-`) are recognized. For characters that are created by holding
|
|
101
|
+
* shift, the `Shift-` prefix is implied, and should not be added
|
|
102
|
+
* explicitly.
|
|
103
|
+
*
|
|
104
|
+
* You can use `Mod-` as a shorthand for `Cmd-` on Mac and `Ctrl-` on
|
|
105
|
+
* other platforms.
|
|
106
|
+
*
|
|
107
|
+
* You can add multiple keymap plugins to an editor. The order in which
|
|
108
|
+
* they appear determines their precedence (the ones early in the array
|
|
109
|
+
* get to dispatch first).
|
|
110
|
+
*
|
|
111
|
+
* The plugin's error and requirement types are the unions of those of
|
|
112
|
+
* the bound commands. Throws a `KeymapError` when a key name is invalid
|
|
113
|
+
* or bound twice.
|
|
114
|
+
*
|
|
115
|
+
* @since 0.1.0
|
|
116
|
+
* @category constructors
|
|
117
|
+
*/
|
|
118
|
+
export declare const keymap: <const B extends Bindings>(bindings: B) => Plugin<undefined, AnySchema, BindingsError<B>, BindingsRequirements<B>>;
|
|
119
|
+
/**
|
|
120
|
+
* Given a set of bindings (using the same format as `keymap`), return a
|
|
121
|
+
* keydown handler that handles them. The handler succeeds with `true`
|
|
122
|
+
* when one of the matching commands handled the key.
|
|
123
|
+
*
|
|
124
|
+
* Throws a `KeymapError` when a key name is invalid or bound twice.
|
|
125
|
+
*
|
|
126
|
+
* @since 0.1.0
|
|
127
|
+
* @category constructors
|
|
128
|
+
*/
|
|
129
|
+
export declare const keydownHandler: <const B extends Bindings>(bindings: B) => KeydownHandler<BindingsError<B>, BindingsRequirements<B>>;
|
|
130
|
+
export {};
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { Plugin } from "../state/plugin.js";
|
|
2
|
+
import * as Arr from "effect/Array";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Predicate from "effect/Predicate";
|
|
5
|
+
import * as Schema from "effect/Schema";
|
|
6
|
+
import { base, keyName } from "w3c-keyname";
|
|
7
|
+
// src/keymap/keymap.ts
|
|
8
|
+
/**
|
|
9
|
+
* Keymaps: plugins that bind key names to commands, ported from
|
|
10
|
+
* `prosemirror-keymap`.
|
|
11
|
+
*
|
|
12
|
+
* Ported from prosemirror-keymap (MIT, Marijn Haverbeke and others).
|
|
13
|
+
*
|
|
14
|
+
* @since 0.1.0
|
|
15
|
+
*/
|
|
16
|
+
const mac = !Predicate.isUndefined(globalThis.navigator) && /Mac|iP(hone|[oa]d)/.test(navigator.platform);
|
|
17
|
+
const windows = !Predicate.isUndefined(globalThis.navigator) && /Win/.test(navigator.platform);
|
|
18
|
+
/**
|
|
19
|
+
* An invalid keymap: a key name with an unrecognized modifier, or two
|
|
20
|
+
* bindings for the same key.
|
|
21
|
+
*
|
|
22
|
+
* @since 0.1.0
|
|
23
|
+
* @category errors
|
|
24
|
+
*/
|
|
25
|
+
var KeymapError = class extends Schema.TaggedError()("KeymapError", { message: Schema.String }) {};
|
|
26
|
+
/**
|
|
27
|
+
* Normalize a key name (such as `"Mod-Shift-a"`) into the canonical
|
|
28
|
+
* form used for lookups (`"Shift-Ctrl-a"` on non-Mac platforms).
|
|
29
|
+
* Throws a `KeymapError` for unrecognized modifiers.
|
|
30
|
+
*
|
|
31
|
+
* @since 0.1.0
|
|
32
|
+
* @category utils
|
|
33
|
+
*/
|
|
34
|
+
function normalizeKeyName(name) {
|
|
35
|
+
const parts = name.split(/-(?!$)/);
|
|
36
|
+
let result = parts[parts.length - 1];
|
|
37
|
+
if (result === "Space") result = " ";
|
|
38
|
+
let alt = false, ctrl = false, shift = false, meta = false;
|
|
39
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
40
|
+
const mod = parts[i];
|
|
41
|
+
if (/^(cmd|meta|m)$/i.test(mod)) meta = true;
|
|
42
|
+
else if (/^a(lt)?$/i.test(mod)) alt = true;
|
|
43
|
+
else if (/^(c|ctrl|control)$/i.test(mod)) ctrl = true;
|
|
44
|
+
else if (/^s(hift)?$/i.test(mod)) shift = true;
|
|
45
|
+
else if (/^mod$/i.test(mod)) {
|
|
46
|
+
if (mac) meta = true;
|
|
47
|
+
else ctrl = true;
|
|
48
|
+
} else throw new KeymapError({ message: "Unrecognized modifier name: " + mod });
|
|
49
|
+
}
|
|
50
|
+
if (alt) result = "Alt-" + result;
|
|
51
|
+
if (ctrl) result = "Ctrl-" + result;
|
|
52
|
+
if (meta) result = "Meta-" + result;
|
|
53
|
+
if (shift) result = "Shift-" + result;
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Normalize the key names of a set of bindings. Throws a `KeymapError`
|
|
58
|
+
* for invalid or duplicate key names.
|
|
59
|
+
*
|
|
60
|
+
* @internal
|
|
61
|
+
*/
|
|
62
|
+
function normalizeBindings(map) {
|
|
63
|
+
const copy = Object.create(null);
|
|
64
|
+
for (const prop in map) {
|
|
65
|
+
const norm = normalizeKeyName(prop);
|
|
66
|
+
if (Object.prototype.hasOwnProperty.call(copy, norm)) throw new KeymapError({ message: "Multiple bindings for key " + norm + " in a single keymap" });
|
|
67
|
+
copy[norm] = map[prop];
|
|
68
|
+
}
|
|
69
|
+
return copy;
|
|
70
|
+
}
|
|
71
|
+
function modifiers(name, event, shift = true) {
|
|
72
|
+
if (event.altKey) name = "Alt-" + name;
|
|
73
|
+
if (event.ctrlKey) name = "Ctrl-" + name;
|
|
74
|
+
if (event.metaKey) name = "Meta-" + name;
|
|
75
|
+
if (shift && event.shiftKey) name = "Shift-" + name;
|
|
76
|
+
return name;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Find the bindings matching a keydown event, in the order in which
|
|
80
|
+
* they should be tried.
|
|
81
|
+
*
|
|
82
|
+
* @internal
|
|
83
|
+
*/
|
|
84
|
+
function matchBindings(map, event) {
|
|
85
|
+
const name = keyName(event);
|
|
86
|
+
const candidates = [];
|
|
87
|
+
const direct = map[modifiers(name, event)];
|
|
88
|
+
if (direct) candidates.push(direct);
|
|
89
|
+
if (name.length === 1 && name !== " ") {
|
|
90
|
+
if (event.shiftKey) {
|
|
91
|
+
const noShift = map[modifiers(name, event, false)];
|
|
92
|
+
if (noShift) candidates.push(noShift);
|
|
93
|
+
}
|
|
94
|
+
let baseName;
|
|
95
|
+
if ((event.altKey || event.metaKey || event.ctrlKey) && !(windows && event.ctrlKey && event.altKey) && (baseName = base[event.keyCode]) && baseName !== name) {
|
|
96
|
+
const fromCode = map[modifiers(baseName, event)];
|
|
97
|
+
if (fromCode) candidates.push(fromCode);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return candidates;
|
|
101
|
+
}
|
|
102
|
+
const succeedFalse = Effect.succeed(false);
|
|
103
|
+
const succeedTrue = Effect.succeed(true);
|
|
104
|
+
/**
|
|
105
|
+
* Create a keymap plugin for the given set of bindings.
|
|
106
|
+
*
|
|
107
|
+
* Bindings should map key names to commands, which will be called with
|
|
108
|
+
* `(state, dispatch, view)` arguments, and should succeed with `true`
|
|
109
|
+
* when they've handled the key. Note that the view argument isn't part
|
|
110
|
+
* of the command protocol, but can be used as an escape hatch if a
|
|
111
|
+
* binding needs to directly interact with the UI.
|
|
112
|
+
*
|
|
113
|
+
* Key names may be strings like `"Shift-Ctrl-Enter"`—a key identifier
|
|
114
|
+
* prefixed with zero or more modifiers. Key identifiers are based on
|
|
115
|
+
* the strings that can appear in `KeyEvent.key`. Use lowercase letters
|
|
116
|
+
* to refer to letter keys (or uppercase letters if you want shift to be
|
|
117
|
+
* held). You may use `"Space"` as an alias for the `" "` name.
|
|
118
|
+
*
|
|
119
|
+
* Modifiers can be given in any order. `Shift-` (or `s-`), `Alt-` (or
|
|
120
|
+
* `a-`), `Ctrl-` (or `c-` or `Control-`) and `Cmd-` (or `m-` or
|
|
121
|
+
* `Meta-`) are recognized. For characters that are created by holding
|
|
122
|
+
* shift, the `Shift-` prefix is implied, and should not be added
|
|
123
|
+
* explicitly.
|
|
124
|
+
*
|
|
125
|
+
* You can use `Mod-` as a shorthand for `Cmd-` on Mac and `Ctrl-` on
|
|
126
|
+
* other platforms.
|
|
127
|
+
*
|
|
128
|
+
* You can add multiple keymap plugins to an editor. The order in which
|
|
129
|
+
* they appear determines their precedence (the ones early in the array
|
|
130
|
+
* get to dispatch first).
|
|
131
|
+
*
|
|
132
|
+
* The plugin's error and requirement types are the unions of those of
|
|
133
|
+
* the bound commands. Throws a `KeymapError` when a key name is invalid
|
|
134
|
+
* or bound twice.
|
|
135
|
+
*
|
|
136
|
+
* @since 0.1.0
|
|
137
|
+
* @category constructors
|
|
138
|
+
*/
|
|
139
|
+
const keymap = (bindings) => new Plugin({ props: { handleKeyDown: keydownHandler(bindings) } });
|
|
140
|
+
/**
|
|
141
|
+
* Given a set of bindings (using the same format as `keymap`), return a
|
|
142
|
+
* keydown handler that handles them. The handler succeeds with `true`
|
|
143
|
+
* when one of the matching commands handled the key.
|
|
144
|
+
*
|
|
145
|
+
* Throws a `KeymapError` when a key name is invalid or bound twice.
|
|
146
|
+
*
|
|
147
|
+
* @since 0.1.0
|
|
148
|
+
* @category constructors
|
|
149
|
+
*/
|
|
150
|
+
const keydownHandler = (bindings) => {
|
|
151
|
+
const map = normalizeBindings(bindings);
|
|
152
|
+
return (view, event) => {
|
|
153
|
+
const candidates = matchBindings(map, event);
|
|
154
|
+
if (Arr.isArrayEmpty(candidates)) return succeedFalse;
|
|
155
|
+
const loop = (i) => i === candidates.length ? succeedFalse : Effect.flatMap(Effect.suspend(() => candidates[i](view.state, view.dispatch, view)), (handled) => handled ? succeedTrue : loop(i + 1));
|
|
156
|
+
return loop(0);
|
|
157
|
+
};
|
|
158
|
+
};
|
|
159
|
+
export { KeymapError, keydownHandler, keymap, matchBindings, normalizeBindings, normalizeKeyName };
|
package/dist/keymap.d.ts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { Bindings, BindingsError, BindingsRequirements, KeydownHandler, KeymapError, KeymapView, keydownHandler, keymap, matchBindings, normalizeBindings, normalizeKeyName } from "./keymap/keymap.js";
|
|
2
|
+
export { Bindings, BindingsError, BindingsRequirements, KeydownHandler, KeymapError, KeymapView, keydownHandler, keymap, matchBindings, normalizeBindings, normalizeKeyName };
|
package/dist/keymap.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { KeymapError, keydownHandler, keymap, matchBindings, normalizeBindings, normalizeKeyName } from "./keymap/keymap.js";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as Schema from "effect/Schema";
|
|
2
|
+
declare const MarkdownError_base: Schema.Class<MarkdownError, Schema.TaggedStruct<"MarkdownError", {
|
|
3
|
+
readonly message: Schema.String;
|
|
4
|
+
}>, import("effect/Cause").YieldableError>;
|
|
5
|
+
/**
|
|
6
|
+
* A Markdown error: the tokenizer produced a token type the parser has
|
|
7
|
+
* no handler for, a parser was configured with an invalid parsing
|
|
8
|
+
* spec, or (in strict mode) the serializer met a node or mark type it
|
|
9
|
+
* has no serializer for.
|
|
10
|
+
*
|
|
11
|
+
* Parsing reports unsupported tokens in the Effect error channel; the
|
|
12
|
+
* other cases are programming errors and are thrown.
|
|
13
|
+
*
|
|
14
|
+
* @since 0.1.0
|
|
15
|
+
* @category errors
|
|
16
|
+
*/
|
|
17
|
+
export declare class MarkdownError extends MarkdownError_base {}
|
|
18
|
+
/**
|
|
19
|
+
* @since 0.1.0
|
|
20
|
+
* @category guards
|
|
21
|
+
*/
|
|
22
|
+
export declare const isMarkdownError: (u: unknown) => u is MarkdownError;
|
|
23
|
+
export {};
|