@domternal/core 0.2.0 → 0.3.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/dist/index.cjs CHANGED
@@ -4,8 +4,8 @@ var state = require('@domternal/pm/state');
4
4
  var view = require('@domternal/pm/view');
5
5
  var model = require('@domternal/pm/model');
6
6
  var keymap = require('@domternal/pm/keymap');
7
- var inputrules = require('@domternal/pm/inputrules');
8
7
  var commands = require('@domternal/pm/commands');
8
+ var inputrules = require('@domternal/pm/inputrules');
9
9
  var transform = require('@domternal/pm/transform');
10
10
  var schemaList = require('@domternal/pm/schema-list');
11
11
  var dom = require('@floating-ui/dom');
@@ -109,6 +109,112 @@ var EventEmitter = class {
109
109
  return Array.from(this.callbacks.keys());
110
110
  }
111
111
  };
112
+ var MAX_MATCH = 500;
113
+ function run(view, from, to, text, rules, plugin) {
114
+ if (view.composing) return false;
115
+ const state = view.state;
116
+ const $from = state.doc.resolve(from);
117
+ const textBefore = $from.parent.textBetween(
118
+ Math.max(0, $from.parentOffset - MAX_MATCH),
119
+ $from.parentOffset,
120
+ null,
121
+ "\uFFFC"
122
+ ) + text;
123
+ for (const rawRule of rules) {
124
+ const rule = rawRule;
125
+ if (!rule.inCodeMark && $from.marks().some((m) => m.type.spec.code)) continue;
126
+ if ($from.parent.type.spec.code) {
127
+ if (!rule.inCode) continue;
128
+ } else if (rule.inCode === "only") {
129
+ continue;
130
+ }
131
+ const match = rule.match.exec(textBefore);
132
+ if (!match || match[0].length < text.length) continue;
133
+ const startPos = from - (match[0].length - text.length);
134
+ if (!rule.inCodeMark) {
135
+ const codeMarks = [];
136
+ state.doc.nodesBetween(startPos, $from.pos, (node) => {
137
+ if (node.isInline && node.marks.some((m) => m.type.spec.code)) codeMarks.push(true);
138
+ });
139
+ if (codeMarks.length > 0) continue;
140
+ }
141
+ const tr = rule.handler(state, match, startPos, to);
142
+ if (!tr) continue;
143
+ if (rule.undoable) {
144
+ tr.setMeta(plugin, { transform: tr, from, to, text });
145
+ }
146
+ view.dispatch(tr);
147
+ return true;
148
+ }
149
+ return false;
150
+ }
151
+ function undoInputRule(plugin, state$1, dispatch) {
152
+ const undoable = plugin.getState(state$1);
153
+ if (!undoable) return false;
154
+ if (dispatch) {
155
+ const tr = state$1.tr;
156
+ const toUndo = undoable.transform;
157
+ for (let j = toUndo.steps.length - 1; j >= 0; j--) {
158
+ const step = toUndo.steps[j];
159
+ const doc = toUndo.docs[j];
160
+ if (step && doc) tr.step(step.invert(doc));
161
+ }
162
+ if (undoable.text) {
163
+ const marks = tr.doc.resolve(undoable.from).marks();
164
+ tr.replaceWith(undoable.from, undoable.to, state$1.schema.text(undoable.text, marks));
165
+ const endPos = undoable.from + undoable.text.length;
166
+ if (endPos <= tr.doc.content.size) {
167
+ tr.setSelection(state.TextSelection.create(tr.doc, endPos));
168
+ }
169
+ } else {
170
+ tr.delete(undoable.from, undoable.to);
171
+ }
172
+ dispatch(tr);
173
+ }
174
+ return true;
175
+ }
176
+ function inputRulesPlugin({ rules }) {
177
+ const plugin = new state.Plugin({
178
+ state: {
179
+ init() {
180
+ return null;
181
+ },
182
+ apply(tr, prev) {
183
+ const stored = tr.getMeta(plugin);
184
+ if (stored) return stored;
185
+ if (tr.getMeta("appendedTransaction")) return prev;
186
+ return tr.selectionSet || tr.docChanged ? null : prev;
187
+ }
188
+ },
189
+ props: {
190
+ handleTextInput(view, from, to, text) {
191
+ return run(view, from, to, text, rules, plugin);
192
+ },
193
+ handleKeyDown(view, event) {
194
+ if (event.key === "Backspace" && !event.ctrlKey && !event.metaKey && !event.altKey) {
195
+ return undoInputRule(plugin, view.state, (tr) => {
196
+ view.dispatch(tr);
197
+ });
198
+ }
199
+ return false;
200
+ },
201
+ handleDOMEvents: {
202
+ compositionend: (view) => {
203
+ setTimeout(() => {
204
+ const { $cursor } = view.state.selection;
205
+ if ($cursor) {
206
+ run(view, $cursor.pos, $cursor.pos, "", rules, plugin);
207
+ }
208
+ });
209
+ }
210
+ }
211
+ },
212
+ // Tag so external undoInputRule can also find this plugin
213
+ isInputRules: true
214
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
215
+ });
216
+ return plugin;
217
+ }
112
218
 
113
219
  // src/helpers/callOrReturn.ts
114
220
  function callOrReturn(value, context, ...args) {
@@ -486,14 +592,14 @@ var ExtensionManager = class {
486
592
  */
487
593
  buildPlugins() {
488
594
  const plugins = [];
595
+ const rules = this.collectInputRules();
596
+ if (rules.length > 0) {
597
+ plugins.push(inputRulesPlugin({ rules }));
598
+ }
489
599
  const shortcuts = this.collectKeyboardShortcuts();
490
600
  if (Object.keys(shortcuts).length > 0) {
491
601
  plugins.push(keymap.keymap(shortcuts));
492
602
  }
493
- const rules = this.collectInputRules();
494
- if (rules.length > 0) {
495
- plugins.push(inputrules.inputRules({ rules }));
496
- }
497
603
  for (const ext of this._extensions) {
498
604
  const addPlugins = ext.config.addProseMirrorPlugins;
499
605
  if (addPlugins) {
@@ -936,7 +1042,7 @@ function isDocumentEmpty(doc) {
936
1042
  });
937
1043
  }
938
1044
  function markInputRule(options) {
939
- const { find: find2, type, getAttributes } = options;
1045
+ const { find: find2, type, getAttributes, undoable } = options;
940
1046
  return new inputrules.InputRule(
941
1047
  find2,
942
1048
  (state, match, start, end) => {
@@ -953,7 +1059,8 @@ function markInputRule(options) {
953
1059
  tr.addMark(start, start + textContent.length, type.create(attributes ?? void 0));
954
1060
  tr.removeStoredMark(type);
955
1061
  return tr;
956
- }
1062
+ },
1063
+ undoable !== void 0 ? { undoable } : {}
957
1064
  );
958
1065
  }
959
1066
  var markInputRulePatterns = {
@@ -978,6 +1085,69 @@ var markInputRulePatterns = {
978
1085
  */
979
1086
  highlight: /(?:==)([^=]+)(?:==)$/
980
1087
  };
1088
+ function wrappingInputRule(options) {
1089
+ const { find: find2, type, getAttributes = null, joinPredicate, undoable, guard } = options;
1090
+ return new inputrules.InputRule(
1091
+ find2,
1092
+ (state, match, start, end) => {
1093
+ if (guard && !guard(state)) return null;
1094
+ const attrs = getAttributes instanceof Function ? getAttributes(match) : getAttributes;
1095
+ const tr = state.tr.delete(start, end);
1096
+ const $start = tr.doc.resolve(start);
1097
+ const range = $start.blockRange();
1098
+ const wrapping = range && transform.findWrapping(range, type, attrs);
1099
+ if (!wrapping) return null;
1100
+ tr.wrap(range, wrapping);
1101
+ const before = tr.doc.resolve(start - 1).nodeBefore;
1102
+ if (before?.type === type && transform.canJoin(tr.doc, start - 1) && (!joinPredicate || joinPredicate(match, before))) {
1103
+ tr.join(start - 1);
1104
+ }
1105
+ return tr;
1106
+ },
1107
+ undoable !== void 0 ? { undoable } : {}
1108
+ );
1109
+ }
1110
+ function notInsideList(state) {
1111
+ const { $from } = state.selection;
1112
+ for (let d = $from.depth; d > 0; d--) {
1113
+ const name = $from.node(d).type.name;
1114
+ if (name === "listItem" || name === "taskItem") return false;
1115
+ }
1116
+ return true;
1117
+ }
1118
+ function textblockTypeInputRule(options) {
1119
+ const { find: find2, type, getAttributes = null, undoable } = options;
1120
+ return new inputrules.InputRule(
1121
+ find2,
1122
+ (state, match, start, end) => {
1123
+ const $start = state.doc.resolve(start);
1124
+ const attrs = getAttributes instanceof Function ? getAttributes(match) : getAttributes;
1125
+ if (!$start.node(-1).canReplaceWith($start.index(-1), $start.indexAfter(-1), type)) return null;
1126
+ return state.tr.delete(start, end).setBlockType(start, start, type, attrs);
1127
+ },
1128
+ undoable !== void 0 ? { undoable } : {}
1129
+ );
1130
+ }
1131
+ function textInputRule(options) {
1132
+ const { find: find2, replace, undoable } = options;
1133
+ return new inputrules.InputRule(
1134
+ find2,
1135
+ (state, _match, start, end) => state.tr.replaceWith(start, end, state.schema.text(replace)),
1136
+ undoable !== void 0 ? { undoable } : {}
1137
+ );
1138
+ }
1139
+ function nodeInputRule(options) {
1140
+ const { find: find2, type, getAttributes = null, undoable } = options;
1141
+ return new inputrules.InputRule(
1142
+ find2,
1143
+ (state, match, start, end) => {
1144
+ const attrs = getAttributes instanceof Function ? getAttributes(match, state) : getAttributes;
1145
+ if (getAttributes instanceof Function && attrs === null) return null;
1146
+ return state.tr.replaceWith(start, end, type.create(attrs));
1147
+ },
1148
+ undoable !== void 0 ? { undoable } : {}
1149
+ );
1150
+ }
981
1151
 
982
1152
  // src/helpers/isValidUrl.ts
983
1153
  function isValidUrl(url, options = {}) {
@@ -1821,8 +1991,8 @@ var wrapIn = (nodeName, attributes) => ({ state, tr, dispatch }) => {
1821
1991
  return true;
1822
1992
  };
1823
1993
  var toggleWrap = (nodeName, attributes) => (props) => {
1824
- const { state: state$1, tr, dispatch } = props;
1825
- const nodeType = state$1.schema.nodes[nodeName];
1994
+ const { state, tr, dispatch } = props;
1995
+ const nodeType = state.schema.nodes[nodeName];
1826
1996
  if (!nodeType) {
1827
1997
  return false;
1828
1998
  }
@@ -1866,8 +2036,18 @@ var toggleWrap = (nodeName, attributes) => (props) => {
1866
2036
  const allWrapped = contentBlocks.length > 0 ? contentBlocks.every(({ pos }) => isInsideWrap(pos)) : isInsideWrap(from);
1867
2037
  if (allWrapped) {
1868
2038
  const first = contentBlocks[0];
1869
- if (first) {
1870
- tr.setSelection(state.TextSelection.create(tr.doc, first.pos + 1));
2039
+ const last = contentBlocks[contentBlocks.length - 1];
2040
+ if (first && last) {
2041
+ const $liftFrom = tr.doc.resolve(first.pos + 1);
2042
+ const $liftTo = tr.doc.resolve(last.pos + 1);
2043
+ const range = $liftFrom.blockRange($liftTo);
2044
+ if (!range) return false;
2045
+ const target = transform.liftTarget(range);
2046
+ if (target === null) return false;
2047
+ if (!dispatch) return true;
2048
+ tr.lift(range, target).scrollIntoView();
2049
+ dispatch(tr);
2050
+ return true;
1871
2051
  }
1872
2052
  return lift()(props);
1873
2053
  }
@@ -1901,6 +2081,36 @@ var lift = () => ({ tr, dispatch }) => {
1901
2081
  dispatch(tr);
1902
2082
  return true;
1903
2083
  };
2084
+ function joinListBackwards(tr, listType) {
2085
+ const { $from } = tr.selection;
2086
+ for (let d = $from.depth; d >= 0; d--) {
2087
+ if ($from.node(d).type === listType) {
2088
+ const listPos = $from.before(d);
2089
+ if (listPos > 0 && transform.canJoin(tr.doc, listPos)) {
2090
+ const nodeBefore = tr.doc.resolve(listPos - 1).parent;
2091
+ if (nodeBefore.type === listType) {
2092
+ tr.join(listPos);
2093
+ }
2094
+ }
2095
+ return;
2096
+ }
2097
+ }
2098
+ }
2099
+ function joinListForwards(tr, listType) {
2100
+ const { $from } = tr.selection;
2101
+ for (let d = $from.depth; d >= 0; d--) {
2102
+ if ($from.node(d).type === listType) {
2103
+ const after = $from.after(d);
2104
+ if (after < tr.doc.content.size && transform.canJoin(tr.doc, after)) {
2105
+ const nodeAfter = tr.doc.nodeAt(after);
2106
+ if (nodeAfter?.type === listType) {
2107
+ tr.join(after);
2108
+ }
2109
+ }
2110
+ return;
2111
+ }
2112
+ }
2113
+ }
1904
2114
  var toggleList = (listNodeName, listItemNodeName, attributes) => ({ state: state$1, tr, dispatch }) => {
1905
2115
  const listType = state$1.schema.nodes[listNodeName];
1906
2116
  const listItemType = state$1.schema.nodes[listItemNodeName];
@@ -2056,11 +2266,56 @@ var toggleList = (listNodeName, listItemNodeName, attributes) => ({ state: state
2056
2266
  dispatch(tr);
2057
2267
  return true;
2058
2268
  }
2059
- const { $from: $wrapFrom, $to: $wrapTo } = tr.selection;
2269
+ const blocksInList = contentBlocks.filter((b) => b.inSomeList);
2270
+ if (blocksInList.length === 0) {
2271
+ const { $from: $wf, $to: $wt } = tr.selection;
2272
+ const wr = $wf.blockRange($wt);
2273
+ if (!wr) return false;
2274
+ if (!schemaList.wrapRangeInList(dispatch ? tr : null, wr, listType, attributes)) return false;
2275
+ if (dispatch) {
2276
+ joinListBackwards(tr, listType);
2277
+ joinListForwards(tr, listType);
2278
+ dispatch(tr.scrollIntoView());
2279
+ }
2280
+ return true;
2281
+ }
2282
+ if (!dispatch) return true;
2283
+ const seen = /* @__PURE__ */ new Set();
2284
+ const listPositions = [];
2285
+ for (const block of blocksInList) {
2286
+ const $pos = tr.doc.resolve(block.pos);
2287
+ for (let d = $pos.depth; d >= 0; d--) {
2288
+ const groups = ($pos.node(d).type.spec.group ?? "").split(/\s+/);
2289
+ if (groups.includes("list")) {
2290
+ const lpos = $pos.before(d);
2291
+ if (!seen.has(lpos)) {
2292
+ seen.add(lpos);
2293
+ listPositions.push(lpos);
2294
+ }
2295
+ break;
2296
+ }
2297
+ }
2298
+ }
2299
+ listPositions.sort((a, b) => b - a);
2300
+ for (const pos of listPositions) {
2301
+ const listNode = tr.doc.nodeAt(pos);
2302
+ if (!listNode) continue;
2303
+ const children = [];
2304
+ listNode.forEach((item) => {
2305
+ item.forEach((child) => children.push(child));
2306
+ });
2307
+ tr.replaceWith(pos, pos + listNode.nodeSize, children);
2308
+ }
2309
+ const mappedFrom = tr.mapping.map(from, -1);
2310
+ const mappedTo = tr.mapping.map(to, 1);
2311
+ const $wrapFrom = tr.doc.resolve(mappedFrom);
2312
+ const $wrapTo = tr.doc.resolve(mappedTo);
2060
2313
  const wrapRange = $wrapFrom.blockRange($wrapTo);
2061
2314
  if (!wrapRange) return false;
2062
- if (!schemaList.wrapRangeInList(dispatch ? tr : null, wrapRange, listType, attributes)) return false;
2063
- if (dispatch) dispatch(tr.scrollIntoView());
2315
+ schemaList.wrapRangeInList(tr, wrapRange, listType, attributes);
2316
+ joinListBackwards(tr, listType);
2317
+ joinListForwards(tr, listType);
2318
+ dispatch(tr.scrollIntoView());
2064
2319
  return true;
2065
2320
  };
2066
2321
 
@@ -4409,7 +4664,32 @@ var Heading = Node.create({
4409
4664
  ];
4410
4665
  },
4411
4666
  addProseMirrorPlugins() {
4667
+ const { options, editor } = this;
4668
+ const codeToLevel = {};
4669
+ for (const level of options.levels) {
4670
+ codeToLevel[`Digit${String(level)}`] = level;
4671
+ }
4672
+ codeToLevel["Digit0"] = 0;
4412
4673
  return [
4674
+ new state.Plugin({
4675
+ key: new state.PluginKey("headingKeydownFix"),
4676
+ props: {
4677
+ handleDOMEvents: {
4678
+ keydown(_view, event) {
4679
+ if (!event.altKey || !(event.metaKey || event.ctrlKey)) return false;
4680
+ const level = codeToLevel[event.code];
4681
+ if (level === void 0) return false;
4682
+ event.preventDefault();
4683
+ if (level === 0) {
4684
+ editor?.commands["setParagraph"]?.();
4685
+ } else {
4686
+ editor?.commands["toggleHeading"]?.({ level });
4687
+ }
4688
+ return true;
4689
+ }
4690
+ }
4691
+ }
4692
+ }),
4413
4693
  keymap.keymap({
4414
4694
  Backspace: ((state, dispatch) => {
4415
4695
  const { selection } = state;
@@ -4436,10 +4716,10 @@ var Heading = Node.create({
4436
4716
  }
4437
4717
  const maxLevel = Math.max(...options.levels);
4438
4718
  return [
4439
- inputrules.textblockTypeInputRule(
4440
- new RegExp(`^(#{1,${String(maxLevel)}})\\s$`),
4441
- nodeType,
4442
- (match) => {
4719
+ textblockTypeInputRule({
4720
+ find: new RegExp(`^(#{1,${String(maxLevel)}})\\s$`),
4721
+ type: nodeType,
4722
+ getAttributes: (match) => {
4443
4723
  const hashes = match[1];
4444
4724
  if (!hashes) {
4445
4725
  return null;
@@ -4450,10 +4730,12 @@ var Heading = Node.create({
4450
4730
  }
4451
4731
  return { level };
4452
4732
  }
4453
- )
4733
+ })
4454
4734
  ];
4455
4735
  }
4456
4736
  });
4737
+
4738
+ // src/nodes/Blockquote.ts
4457
4739
  var Blockquote = Node.create({
4458
4740
  name: "blockquote",
4459
4741
  group: "block",
@@ -4513,7 +4795,7 @@ var Blockquote = Node.create({
4513
4795
  return [];
4514
4796
  }
4515
4797
  return [
4516
- inputrules.wrappingInputRule(/^\s*>\s$/, nodeType)
4798
+ wrappingInputRule({ find: /^\s*>\s$/, type: nodeType })
4517
4799
  ];
4518
4800
  }
4519
4801
  });
@@ -4643,14 +4925,14 @@ var CodeBlock = Node.create({
4643
4925
  return [];
4644
4926
  }
4645
4927
  return [
4646
- inputrules.textblockTypeInputRule(
4647
- /^```([a-z]*)?[\s\n]$/,
4648
- nodeType,
4649
- (match) => {
4928
+ textblockTypeInputRule({
4929
+ find: /^```([a-z]*)?[\s\n]$/,
4930
+ type: nodeType,
4931
+ getAttributes: (match) => {
4650
4932
  const language = match[1] ?? null;
4651
4933
  return { language };
4652
4934
  }
4653
- )
4935
+ })
4654
4936
  ];
4655
4937
  }
4656
4938
  });
@@ -4834,14 +5116,16 @@ var BulletList = Node.create({
4834
5116
  }
4835
5117
  return [
4836
5118
  // - item
4837
- inputrules.wrappingInputRule(/^\s*[-]\s$/, nodeType),
5119
+ wrappingInputRule({ find: /^\s*[-]\s$/, type: nodeType, guard: notInsideList }),
4838
5120
  // * item
4839
- inputrules.wrappingInputRule(/^\s*[*]\s$/, nodeType),
5121
+ wrappingInputRule({ find: /^\s*[*]\s$/, type: nodeType, guard: notInsideList }),
4840
5122
  // + item
4841
- inputrules.wrappingInputRule(/^\s*[+]\s$/, nodeType)
5123
+ wrappingInputRule({ find: /^\s*[+]\s$/, type: nodeType, guard: notInsideList })
4842
5124
  ];
4843
5125
  }
4844
5126
  });
5127
+
5128
+ // src/nodes/OrderedList.ts
4845
5129
  var OrderedList = Node.create({
4846
5130
  name: "orderedList",
4847
5131
  group: "block list",
@@ -4917,14 +5201,15 @@ var OrderedList = Node.create({
4917
5201
  }
4918
5202
  return [
4919
5203
  // 1. item (any number followed by . )
4920
- inputrules.wrappingInputRule(
4921
- /^(\d+)\.\s$/,
4922
- nodeType,
4923
- (match) => {
5204
+ wrappingInputRule({
5205
+ find: /^(\d+)\.\s$/,
5206
+ type: nodeType,
5207
+ guard: notInsideList,
5208
+ getAttributes: (match) => {
4924
5209
  const num = match[1];
4925
5210
  return { start: num ? parseInt(num, 10) : 1 };
4926
5211
  }
4927
- )
5212
+ })
4928
5213
  ];
4929
5214
  }
4930
5215
  });
@@ -4999,13 +5284,12 @@ var HorizontalRule = Node.create({
4999
5284
  const $start = state$1.doc.resolve(start);
5000
5285
  const from = $start.before();
5001
5286
  const to = $start.after();
5002
- tr.replaceWith(from, to, nodeType.create());
5003
- if (from + 1 < tr.doc.content.size) {
5004
- const $after = tr.doc.resolve(from + 1);
5005
- const sel = state.TextSelection.findFrom($after, 1);
5006
- if (sel) {
5007
- tr.setSelection(sel);
5008
- }
5287
+ const paragraph = state$1.schema.nodes["paragraph"]?.create();
5288
+ const nodes = paragraph ? [nodeType.create(), paragraph] : [nodeType.create()];
5289
+ tr.replaceWith(from, to, nodes);
5290
+ const sel = state.TextSelection.findFrom(tr.doc.resolve(from + 1), 1);
5291
+ if (sel) {
5292
+ tr.setSelection(sel);
5009
5293
  }
5010
5294
  }
5011
5295
  return tr;
@@ -5047,6 +5331,20 @@ var HardBreak = Node.create({
5047
5331
  }
5048
5332
  };
5049
5333
  },
5334
+ addToolbarItems() {
5335
+ return [
5336
+ {
5337
+ type: "button",
5338
+ name: "hardBreak",
5339
+ command: "setHardBreak",
5340
+ icon: "linkBreak",
5341
+ label: "Hard Break",
5342
+ shortcut: "Shift-Enter",
5343
+ group: "insert",
5344
+ priority: 50
5345
+ }
5346
+ ];
5347
+ },
5050
5348
  addKeyboardShortcuts() {
5051
5349
  const { editor } = this;
5052
5350
  return {
@@ -5282,9 +5580,9 @@ var TaskList = Node.create({
5282
5580
  }
5283
5581
  return [
5284
5582
  // [ ] at start of line creates unchecked task
5285
- inputrules.wrappingInputRule(/^\s*\[\s?\]\s$/, nodeType),
5583
+ wrappingInputRule({ find: /^\s*\[\s?\]\s$/, type: nodeType, guard: notInsideList }),
5286
5584
  // [x] or [X] at start of line creates checked task
5287
- inputrules.wrappingInputRule(/^\s*\[[xX]\]\s$/, nodeType)
5585
+ wrappingInputRule({ find: /^\s*\[[xX]\]\s$/, type: nodeType, guard: notInsideList })
5288
5586
  ];
5289
5587
  }
5290
5588
  });
@@ -6582,40 +6880,39 @@ var Typography = Extension.create({
6582
6880
  },
6583
6881
  addInputRules() {
6584
6882
  const rules = [];
6585
- const textReplace = (find2, replacement) => new inputrules.InputRule(find2, (state, _match, start, end) => state.tr.replaceWith(start, end, state.schema.text(replacement)));
6586
6883
  if (this.options.emDash) {
6587
- rules.push(textReplace(/--$/, "\u2014"));
6884
+ rules.push(textInputRule({ find: /--$/, replace: "\u2014" }));
6588
6885
  }
6589
6886
  if (this.options.ellipsis) {
6590
- rules.push(textReplace(/\.\.\.$/, "\u2026"));
6887
+ rules.push(textInputRule({ find: /\.\.\.$/, replace: "\u2026" }));
6591
6888
  }
6592
6889
  if (this.options.arrows) {
6593
- rules.push(textReplace(/<-$/, "\u2190"));
6594
- rules.push(textReplace(/->$/, "\u2192"));
6595
- rules.push(textReplace(/=>$/, "\u21D2"));
6890
+ rules.push(textInputRule({ find: /<-$/, replace: "\u2190" }));
6891
+ rules.push(textInputRule({ find: /->$/, replace: "\u2192" }));
6892
+ rules.push(textInputRule({ find: /=>$/, replace: "\u21D2" }));
6596
6893
  }
6597
6894
  if (this.options.fractions) {
6598
- rules.push(textReplace(/1\/2$/, "\xBD"));
6599
- rules.push(textReplace(/1\/4$/, "\xBC"));
6600
- rules.push(textReplace(/3\/4$/, "\xBE"));
6601
- rules.push(textReplace(/1\/3$/, "\u2153"));
6602
- rules.push(textReplace(/2\/3$/, "\u2154"));
6895
+ rules.push(textInputRule({ find: /1\/2$/, replace: "\xBD" }));
6896
+ rules.push(textInputRule({ find: /1\/4$/, replace: "\xBC" }));
6897
+ rules.push(textInputRule({ find: /3\/4$/, replace: "\xBE" }));
6898
+ rules.push(textInputRule({ find: /1\/3$/, replace: "\u2153" }));
6899
+ rules.push(textInputRule({ find: /2\/3$/, replace: "\u2154" }));
6603
6900
  }
6604
6901
  if (this.options.symbols) {
6605
- rules.push(textReplace(/\(c\)$/i, "\xA9"));
6606
- rules.push(textReplace(/\(r\)$/i, "\xAE"));
6607
- rules.push(textReplace(/\(tm\)$/i, "\u2122"));
6608
- rules.push(textReplace(/\(sm\)$/i, "\u2120"));
6902
+ rules.push(textInputRule({ find: /\(c\)$/i, replace: "\xA9" }));
6903
+ rules.push(textInputRule({ find: /\(r\)$/i, replace: "\xAE" }));
6904
+ rules.push(textInputRule({ find: /\(tm\)$/i, replace: "\u2122" }));
6905
+ rules.push(textInputRule({ find: /\(sm\)$/i, replace: "\u2120" }));
6609
6906
  }
6610
6907
  if (this.options.math) {
6611
- rules.push(textReplace(/\+\/-$/, "\xB1"));
6612
- rules.push(textReplace(/!=$/, "\u2260"));
6613
- rules.push(textReplace(/<=$/, "\u2264"));
6614
- rules.push(textReplace(/>=$/, "\u2265"));
6908
+ rules.push(textInputRule({ find: /\+\/-$/, replace: "\xB1" }));
6909
+ rules.push(textInputRule({ find: /!=$/, replace: "\u2260" }));
6910
+ rules.push(textInputRule({ find: /<=$/, replace: "\u2264" }));
6911
+ rules.push(textInputRule({ find: />=$/, replace: "\u2265" }));
6615
6912
  }
6616
6913
  if (this.options.guillemets) {
6617
- rules.push(textReplace(/<<$/, "\xAB"));
6618
- rules.push(textReplace(/>>$/, "\xBB"));
6914
+ rules.push(textInputRule({ find: /<<$/, replace: "\xAB" }));
6915
+ rules.push(textInputRule({ find: />>$/, replace: "\xBB" }));
6619
6916
  }
6620
6917
  if (this.options.smartQuotes) {
6621
6918
  const { openDoubleQuote, closeDoubleQuote, openSingleQuote, closeSingleQuote } = this.options;
@@ -7852,11 +8149,13 @@ function linkPopoverPlugin({ editor, markType, protocols }) {
7852
8149
  applyBtn.type = "button";
7853
8150
  applyBtn.className = "dm-link-popover-btn dm-link-popover-apply";
7854
8151
  applyBtn.title = "Apply link";
8152
+ applyBtn.setAttribute("aria-label", "Apply link");
7855
8153
  applyBtn.innerHTML = defaultIcons["check"] ?? "";
7856
8154
  const removeBtn = document.createElement("button");
7857
8155
  removeBtn.type = "button";
7858
8156
  removeBtn.className = "dm-link-popover-btn dm-link-popover-remove";
7859
8157
  removeBtn.title = "Remove link";
8158
+ removeBtn.setAttribute("aria-label", "Remove link");
7860
8159
  removeBtn.innerHTML = defaultIcons["linkBreak"] ?? "";
7861
8160
  el.appendChild(input);
7862
8161
  el.appendChild(applyBtn);
@@ -8622,6 +8921,7 @@ exports.linkPastePlugin = linkPastePlugin;
8622
8921
  exports.linkPastePluginKey = linkPastePluginKey;
8623
8922
  exports.markInputRule = markInputRule;
8624
8923
  exports.markInputRulePatterns = markInputRulePatterns;
8924
+ exports.nodeInputRule = nodeInputRule;
8625
8925
  exports.placeholderPluginKey = placeholderPluginKey;
8626
8926
  exports.positionFloating = positionFloating;
8627
8927
  exports.positionFloatingOnce = positionFloatingOnce;
@@ -8632,6 +8932,8 @@ exports.selectionDecorationPluginKey = selectionDecorationPluginKey;
8632
8932
  exports.setBlockType = setBlockType;
8633
8933
  exports.setContent = setContent;
8634
8934
  exports.setMark = setMark;
8935
+ exports.textInputRule = textInputRule;
8936
+ exports.textblockTypeInputRule = textblockTypeInputRule;
8635
8937
  exports.toggleBlockType = toggleBlockType;
8636
8938
  exports.toggleList = toggleList;
8637
8939
  exports.toggleMark = toggleMark;
@@ -8641,5 +8943,6 @@ exports.unsetAllMarks = unsetAllMarks;
8641
8943
  exports.unsetMark = unsetMark;
8642
8944
  exports.updateAttributes = updateAttributes;
8643
8945
  exports.wrapIn = wrapIn;
8946
+ exports.wrappingInputRule = wrappingInputRule;
8644
8947
  //# sourceMappingURL=index.cjs.map
8645
8948
  //# sourceMappingURL=index.cjs.map