@domternal/core 0.2.1 → 0.4.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) {
@@ -602,8 +708,12 @@ var ExtensionManager = class {
602
708
  return items;
603
709
  }
604
710
  /**
605
- * Collects node views from all Node extensions
606
- * Returns a map of node name NodeViewConstructor for EditorView
711
+ * Collects node views from all Node extensions.
712
+ * Returns a map of node name to NodeViewConstructor for EditorView.
713
+ *
714
+ * Each constructor is annotated with `__domternalContext` containing
715
+ * the editor and extension metadata so framework wrappers (React, Vue)
716
+ * can access them without changing the ProseMirror calling convention.
607
717
  */
608
718
  collectNodeViews() {
609
719
  const nodeViews = {};
@@ -617,6 +727,10 @@ var ExtensionManager = class {
617
727
  `${ext.name}.addNodeView`
618
728
  );
619
729
  if (nodeView) {
730
+ nodeView.__domternalContext = {
731
+ editor: this.editor,
732
+ extension: { name: nodeExt.name, options: nodeExt.options }
733
+ };
620
734
  nodeViews[ext.name] = nodeView;
621
735
  }
622
736
  }
@@ -936,7 +1050,7 @@ function isDocumentEmpty(doc) {
936
1050
  });
937
1051
  }
938
1052
  function markInputRule(options) {
939
- const { find: find2, type, getAttributes } = options;
1053
+ const { find: find2, type, getAttributes, undoable } = options;
940
1054
  return new inputrules.InputRule(
941
1055
  find2,
942
1056
  (state, match, start, end) => {
@@ -953,7 +1067,8 @@ function markInputRule(options) {
953
1067
  tr.addMark(start, start + textContent.length, type.create(attributes ?? void 0));
954
1068
  tr.removeStoredMark(type);
955
1069
  return tr;
956
- }
1070
+ },
1071
+ undoable !== void 0 ? { undoable } : {}
957
1072
  );
958
1073
  }
959
1074
  var markInputRulePatterns = {
@@ -978,6 +1093,69 @@ var markInputRulePatterns = {
978
1093
  */
979
1094
  highlight: /(?:==)([^=]+)(?:==)$/
980
1095
  };
1096
+ function wrappingInputRule(options) {
1097
+ const { find: find2, type, getAttributes = null, joinPredicate, undoable, guard } = options;
1098
+ return new inputrules.InputRule(
1099
+ find2,
1100
+ (state, match, start, end) => {
1101
+ if (guard && !guard(state)) return null;
1102
+ const attrs = getAttributes instanceof Function ? getAttributes(match) : getAttributes;
1103
+ const tr = state.tr.delete(start, end);
1104
+ const $start = tr.doc.resolve(start);
1105
+ const range = $start.blockRange();
1106
+ const wrapping = range && transform.findWrapping(range, type, attrs);
1107
+ if (!wrapping) return null;
1108
+ tr.wrap(range, wrapping);
1109
+ const before = tr.doc.resolve(start - 1).nodeBefore;
1110
+ if (before?.type === type && transform.canJoin(tr.doc, start - 1) && (!joinPredicate || joinPredicate(match, before))) {
1111
+ tr.join(start - 1);
1112
+ }
1113
+ return tr;
1114
+ },
1115
+ undoable !== void 0 ? { undoable } : {}
1116
+ );
1117
+ }
1118
+ function notInsideList(state) {
1119
+ const { $from } = state.selection;
1120
+ for (let d = $from.depth; d > 0; d--) {
1121
+ const name = $from.node(d).type.name;
1122
+ if (name === "listItem" || name === "taskItem") return false;
1123
+ }
1124
+ return true;
1125
+ }
1126
+ function textblockTypeInputRule(options) {
1127
+ const { find: find2, type, getAttributes = null, undoable } = options;
1128
+ return new inputrules.InputRule(
1129
+ find2,
1130
+ (state, match, start, end) => {
1131
+ const $start = state.doc.resolve(start);
1132
+ const attrs = getAttributes instanceof Function ? getAttributes(match) : getAttributes;
1133
+ if (!$start.node(-1).canReplaceWith($start.index(-1), $start.indexAfter(-1), type)) return null;
1134
+ return state.tr.delete(start, end).setBlockType(start, start, type, attrs);
1135
+ },
1136
+ undoable !== void 0 ? { undoable } : {}
1137
+ );
1138
+ }
1139
+ function textInputRule(options) {
1140
+ const { find: find2, replace, undoable } = options;
1141
+ return new inputrules.InputRule(
1142
+ find2,
1143
+ (state, _match, start, end) => state.tr.replaceWith(start, end, state.schema.text(replace)),
1144
+ undoable !== void 0 ? { undoable } : {}
1145
+ );
1146
+ }
1147
+ function nodeInputRule(options) {
1148
+ const { find: find2, type, getAttributes = null, undoable } = options;
1149
+ return new inputrules.InputRule(
1150
+ find2,
1151
+ (state, match, start, end) => {
1152
+ const attrs = getAttributes instanceof Function ? getAttributes(match, state) : getAttributes;
1153
+ if (getAttributes instanceof Function && attrs === null) return null;
1154
+ return state.tr.replaceWith(start, end, type.create(attrs));
1155
+ },
1156
+ undoable !== void 0 ? { undoable } : {}
1157
+ );
1158
+ }
981
1159
 
982
1160
  // src/helpers/isValidUrl.ts
983
1161
  function isValidUrl(url, options = {}) {
@@ -1821,8 +1999,8 @@ var wrapIn = (nodeName, attributes) => ({ state, tr, dispatch }) => {
1821
1999
  return true;
1822
2000
  };
1823
2001
  var toggleWrap = (nodeName, attributes) => (props) => {
1824
- const { state: state$1, tr, dispatch } = props;
1825
- const nodeType = state$1.schema.nodes[nodeName];
2002
+ const { state, tr, dispatch } = props;
2003
+ const nodeType = state.schema.nodes[nodeName];
1826
2004
  if (!nodeType) {
1827
2005
  return false;
1828
2006
  }
@@ -1866,8 +2044,18 @@ var toggleWrap = (nodeName, attributes) => (props) => {
1866
2044
  const allWrapped = contentBlocks.length > 0 ? contentBlocks.every(({ pos }) => isInsideWrap(pos)) : isInsideWrap(from);
1867
2045
  if (allWrapped) {
1868
2046
  const first = contentBlocks[0];
1869
- if (first) {
1870
- tr.setSelection(state.TextSelection.create(tr.doc, first.pos + 1));
2047
+ const last = contentBlocks[contentBlocks.length - 1];
2048
+ if (first && last) {
2049
+ const $liftFrom = tr.doc.resolve(first.pos + 1);
2050
+ const $liftTo = tr.doc.resolve(last.pos + 1);
2051
+ const range = $liftFrom.blockRange($liftTo);
2052
+ if (!range) return false;
2053
+ const target = transform.liftTarget(range);
2054
+ if (target === null) return false;
2055
+ if (!dispatch) return true;
2056
+ tr.lift(range, target).scrollIntoView();
2057
+ dispatch(tr);
2058
+ return true;
1871
2059
  }
1872
2060
  return lift()(props);
1873
2061
  }
@@ -1901,6 +2089,36 @@ var lift = () => ({ tr, dispatch }) => {
1901
2089
  dispatch(tr);
1902
2090
  return true;
1903
2091
  };
2092
+ function joinListBackwards(tr, listType) {
2093
+ const { $from } = tr.selection;
2094
+ for (let d = $from.depth; d >= 0; d--) {
2095
+ if ($from.node(d).type === listType) {
2096
+ const listPos = $from.before(d);
2097
+ if (listPos > 0 && transform.canJoin(tr.doc, listPos)) {
2098
+ const nodeBefore = tr.doc.resolve(listPos - 1).parent;
2099
+ if (nodeBefore.type === listType) {
2100
+ tr.join(listPos);
2101
+ }
2102
+ }
2103
+ return;
2104
+ }
2105
+ }
2106
+ }
2107
+ function joinListForwards(tr, listType) {
2108
+ const { $from } = tr.selection;
2109
+ for (let d = $from.depth; d >= 0; d--) {
2110
+ if ($from.node(d).type === listType) {
2111
+ const after = $from.after(d);
2112
+ if (after < tr.doc.content.size && transform.canJoin(tr.doc, after)) {
2113
+ const nodeAfter = tr.doc.nodeAt(after);
2114
+ if (nodeAfter?.type === listType) {
2115
+ tr.join(after);
2116
+ }
2117
+ }
2118
+ return;
2119
+ }
2120
+ }
2121
+ }
1904
2122
  var toggleList = (listNodeName, listItemNodeName, attributes) => ({ state: state$1, tr, dispatch }) => {
1905
2123
  const listType = state$1.schema.nodes[listNodeName];
1906
2124
  const listItemType = state$1.schema.nodes[listItemNodeName];
@@ -2056,11 +2274,56 @@ var toggleList = (listNodeName, listItemNodeName, attributes) => ({ state: state
2056
2274
  dispatch(tr);
2057
2275
  return true;
2058
2276
  }
2059
- const { $from: $wrapFrom, $to: $wrapTo } = tr.selection;
2277
+ const blocksInList = contentBlocks.filter((b) => b.inSomeList);
2278
+ if (blocksInList.length === 0) {
2279
+ const { $from: $wf, $to: $wt } = tr.selection;
2280
+ const wr = $wf.blockRange($wt);
2281
+ if (!wr) return false;
2282
+ if (!schemaList.wrapRangeInList(dispatch ? tr : null, wr, listType, attributes)) return false;
2283
+ if (dispatch) {
2284
+ joinListBackwards(tr, listType);
2285
+ joinListForwards(tr, listType);
2286
+ dispatch(tr.scrollIntoView());
2287
+ }
2288
+ return true;
2289
+ }
2290
+ if (!dispatch) return true;
2291
+ const seen = /* @__PURE__ */ new Set();
2292
+ const listPositions = [];
2293
+ for (const block of blocksInList) {
2294
+ const $pos = tr.doc.resolve(block.pos);
2295
+ for (let d = $pos.depth; d >= 0; d--) {
2296
+ const groups = ($pos.node(d).type.spec.group ?? "").split(/\s+/);
2297
+ if (groups.includes("list")) {
2298
+ const lpos = $pos.before(d);
2299
+ if (!seen.has(lpos)) {
2300
+ seen.add(lpos);
2301
+ listPositions.push(lpos);
2302
+ }
2303
+ break;
2304
+ }
2305
+ }
2306
+ }
2307
+ listPositions.sort((a, b) => b - a);
2308
+ for (const pos of listPositions) {
2309
+ const listNode = tr.doc.nodeAt(pos);
2310
+ if (!listNode) continue;
2311
+ const children = [];
2312
+ listNode.forEach((item) => {
2313
+ item.forEach((child) => children.push(child));
2314
+ });
2315
+ tr.replaceWith(pos, pos + listNode.nodeSize, children);
2316
+ }
2317
+ const mappedFrom = tr.mapping.map(from, -1);
2318
+ const mappedTo = tr.mapping.map(to, 1);
2319
+ const $wrapFrom = tr.doc.resolve(mappedFrom);
2320
+ const $wrapTo = tr.doc.resolve(mappedTo);
2060
2321
  const wrapRange = $wrapFrom.blockRange($wrapTo);
2061
2322
  if (!wrapRange) return false;
2062
- if (!schemaList.wrapRangeInList(dispatch ? tr : null, wrapRange, listType, attributes)) return false;
2063
- if (dispatch) dispatch(tr.scrollIntoView());
2323
+ schemaList.wrapRangeInList(tr, wrapRange, listType, attributes);
2324
+ joinListBackwards(tr, listType);
2325
+ joinListForwards(tr, listType);
2326
+ dispatch(tr.scrollIntoView());
2064
2327
  return true;
2065
2328
  };
2066
2329
 
@@ -4409,7 +4672,32 @@ var Heading = Node.create({
4409
4672
  ];
4410
4673
  },
4411
4674
  addProseMirrorPlugins() {
4675
+ const { options, editor } = this;
4676
+ const codeToLevel = {};
4677
+ for (const level of options.levels) {
4678
+ codeToLevel[`Digit${String(level)}`] = level;
4679
+ }
4680
+ codeToLevel["Digit0"] = 0;
4412
4681
  return [
4682
+ new state.Plugin({
4683
+ key: new state.PluginKey("headingKeydownFix"),
4684
+ props: {
4685
+ handleDOMEvents: {
4686
+ keydown(_view, event) {
4687
+ if (!event.altKey || !(event.metaKey || event.ctrlKey)) return false;
4688
+ const level = codeToLevel[event.code];
4689
+ if (level === void 0) return false;
4690
+ event.preventDefault();
4691
+ if (level === 0) {
4692
+ editor?.commands["setParagraph"]?.();
4693
+ } else {
4694
+ editor?.commands["toggleHeading"]?.({ level });
4695
+ }
4696
+ return true;
4697
+ }
4698
+ }
4699
+ }
4700
+ }),
4413
4701
  keymap.keymap({
4414
4702
  Backspace: ((state, dispatch) => {
4415
4703
  const { selection } = state;
@@ -4436,10 +4724,10 @@ var Heading = Node.create({
4436
4724
  }
4437
4725
  const maxLevel = Math.max(...options.levels);
4438
4726
  return [
4439
- inputrules.textblockTypeInputRule(
4440
- new RegExp(`^(#{1,${String(maxLevel)}})\\s$`),
4441
- nodeType,
4442
- (match) => {
4727
+ textblockTypeInputRule({
4728
+ find: new RegExp(`^(#{1,${String(maxLevel)}})\\s$`),
4729
+ type: nodeType,
4730
+ getAttributes: (match) => {
4443
4731
  const hashes = match[1];
4444
4732
  if (!hashes) {
4445
4733
  return null;
@@ -4450,10 +4738,12 @@ var Heading = Node.create({
4450
4738
  }
4451
4739
  return { level };
4452
4740
  }
4453
- )
4741
+ })
4454
4742
  ];
4455
4743
  }
4456
4744
  });
4745
+
4746
+ // src/nodes/Blockquote.ts
4457
4747
  var Blockquote = Node.create({
4458
4748
  name: "blockquote",
4459
4749
  group: "block",
@@ -4513,7 +4803,7 @@ var Blockquote = Node.create({
4513
4803
  return [];
4514
4804
  }
4515
4805
  return [
4516
- inputrules.wrappingInputRule(/^\s*>\s$/, nodeType)
4806
+ wrappingInputRule({ find: /^\s*>\s$/, type: nodeType })
4517
4807
  ];
4518
4808
  }
4519
4809
  });
@@ -4643,14 +4933,14 @@ var CodeBlock = Node.create({
4643
4933
  return [];
4644
4934
  }
4645
4935
  return [
4646
- inputrules.textblockTypeInputRule(
4647
- /^```([a-z]*)?[\s\n]$/,
4648
- nodeType,
4649
- (match) => {
4936
+ textblockTypeInputRule({
4937
+ find: /^```([a-z]*)?[\s\n]$/,
4938
+ type: nodeType,
4939
+ getAttributes: (match) => {
4650
4940
  const language = match[1] ?? null;
4651
4941
  return { language };
4652
4942
  }
4653
- )
4943
+ })
4654
4944
  ];
4655
4945
  }
4656
4946
  });
@@ -4834,14 +5124,16 @@ var BulletList = Node.create({
4834
5124
  }
4835
5125
  return [
4836
5126
  // - item
4837
- inputrules.wrappingInputRule(/^\s*[-]\s$/, nodeType),
5127
+ wrappingInputRule({ find: /^\s*[-]\s$/, type: nodeType, guard: notInsideList }),
4838
5128
  // * item
4839
- inputrules.wrappingInputRule(/^\s*[*]\s$/, nodeType),
5129
+ wrappingInputRule({ find: /^\s*[*]\s$/, type: nodeType, guard: notInsideList }),
4840
5130
  // + item
4841
- inputrules.wrappingInputRule(/^\s*[+]\s$/, nodeType)
5131
+ wrappingInputRule({ find: /^\s*[+]\s$/, type: nodeType, guard: notInsideList })
4842
5132
  ];
4843
5133
  }
4844
5134
  });
5135
+
5136
+ // src/nodes/OrderedList.ts
4845
5137
  var OrderedList = Node.create({
4846
5138
  name: "orderedList",
4847
5139
  group: "block list",
@@ -4917,14 +5209,15 @@ var OrderedList = Node.create({
4917
5209
  }
4918
5210
  return [
4919
5211
  // 1. item (any number followed by . )
4920
- inputrules.wrappingInputRule(
4921
- /^(\d+)\.\s$/,
4922
- nodeType,
4923
- (match) => {
5212
+ wrappingInputRule({
5213
+ find: /^(\d+)\.\s$/,
5214
+ type: nodeType,
5215
+ guard: notInsideList,
5216
+ getAttributes: (match) => {
4924
5217
  const num = match[1];
4925
5218
  return { start: num ? parseInt(num, 10) : 1 };
4926
5219
  }
4927
- )
5220
+ })
4928
5221
  ];
4929
5222
  }
4930
5223
  });
@@ -4999,13 +5292,12 @@ var HorizontalRule = Node.create({
4999
5292
  const $start = state$1.doc.resolve(start);
5000
5293
  const from = $start.before();
5001
5294
  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
- }
5295
+ const paragraph = state$1.schema.nodes["paragraph"]?.create();
5296
+ const nodes = paragraph ? [nodeType.create(), paragraph] : [nodeType.create()];
5297
+ tr.replaceWith(from, to, nodes);
5298
+ const sel = state.TextSelection.findFrom(tr.doc.resolve(from + 1), 1);
5299
+ if (sel) {
5300
+ tr.setSelection(sel);
5009
5301
  }
5010
5302
  }
5011
5303
  return tr;
@@ -5296,9 +5588,9 @@ var TaskList = Node.create({
5296
5588
  }
5297
5589
  return [
5298
5590
  // [ ] at start of line creates unchecked task
5299
- inputrules.wrappingInputRule(/^\s*\[\s?\]\s$/, nodeType),
5591
+ wrappingInputRule({ find: /^\s*\[\s?\]\s$/, type: nodeType, guard: notInsideList }),
5300
5592
  // [x] or [X] at start of line creates checked task
5301
- inputrules.wrappingInputRule(/^\s*\[[xX]\]\s$/, nodeType)
5593
+ wrappingInputRule({ find: /^\s*\[[xX]\]\s$/, type: nodeType, guard: notInsideList })
5302
5594
  ];
5303
5595
  }
5304
5596
  });
@@ -6596,40 +6888,39 @@ var Typography = Extension.create({
6596
6888
  },
6597
6889
  addInputRules() {
6598
6890
  const rules = [];
6599
- const textReplace = (find2, replacement) => new inputrules.InputRule(find2, (state, _match, start, end) => state.tr.replaceWith(start, end, state.schema.text(replacement)));
6600
6891
  if (this.options.emDash) {
6601
- rules.push(textReplace(/--$/, "\u2014"));
6892
+ rules.push(textInputRule({ find: /--$/, replace: "\u2014" }));
6602
6893
  }
6603
6894
  if (this.options.ellipsis) {
6604
- rules.push(textReplace(/\.\.\.$/, "\u2026"));
6895
+ rules.push(textInputRule({ find: /\.\.\.$/, replace: "\u2026" }));
6605
6896
  }
6606
6897
  if (this.options.arrows) {
6607
- rules.push(textReplace(/<-$/, "\u2190"));
6608
- rules.push(textReplace(/->$/, "\u2192"));
6609
- rules.push(textReplace(/=>$/, "\u21D2"));
6898
+ rules.push(textInputRule({ find: /<-$/, replace: "\u2190" }));
6899
+ rules.push(textInputRule({ find: /->$/, replace: "\u2192" }));
6900
+ rules.push(textInputRule({ find: /=>$/, replace: "\u21D2" }));
6610
6901
  }
6611
6902
  if (this.options.fractions) {
6612
- rules.push(textReplace(/1\/2$/, "\xBD"));
6613
- rules.push(textReplace(/1\/4$/, "\xBC"));
6614
- rules.push(textReplace(/3\/4$/, "\xBE"));
6615
- rules.push(textReplace(/1\/3$/, "\u2153"));
6616
- rules.push(textReplace(/2\/3$/, "\u2154"));
6903
+ rules.push(textInputRule({ find: /1\/2$/, replace: "\xBD" }));
6904
+ rules.push(textInputRule({ find: /1\/4$/, replace: "\xBC" }));
6905
+ rules.push(textInputRule({ find: /3\/4$/, replace: "\xBE" }));
6906
+ rules.push(textInputRule({ find: /1\/3$/, replace: "\u2153" }));
6907
+ rules.push(textInputRule({ find: /2\/3$/, replace: "\u2154" }));
6617
6908
  }
6618
6909
  if (this.options.symbols) {
6619
- rules.push(textReplace(/\(c\)$/i, "\xA9"));
6620
- rules.push(textReplace(/\(r\)$/i, "\xAE"));
6621
- rules.push(textReplace(/\(tm\)$/i, "\u2122"));
6622
- rules.push(textReplace(/\(sm\)$/i, "\u2120"));
6910
+ rules.push(textInputRule({ find: /\(c\)$/i, replace: "\xA9" }));
6911
+ rules.push(textInputRule({ find: /\(r\)$/i, replace: "\xAE" }));
6912
+ rules.push(textInputRule({ find: /\(tm\)$/i, replace: "\u2122" }));
6913
+ rules.push(textInputRule({ find: /\(sm\)$/i, replace: "\u2120" }));
6623
6914
  }
6624
6915
  if (this.options.math) {
6625
- rules.push(textReplace(/\+\/-$/, "\xB1"));
6626
- rules.push(textReplace(/!=$/, "\u2260"));
6627
- rules.push(textReplace(/<=$/, "\u2264"));
6628
- rules.push(textReplace(/>=$/, "\u2265"));
6916
+ rules.push(textInputRule({ find: /\+\/-$/, replace: "\xB1" }));
6917
+ rules.push(textInputRule({ find: /!=$/, replace: "\u2260" }));
6918
+ rules.push(textInputRule({ find: /<=$/, replace: "\u2264" }));
6919
+ rules.push(textInputRule({ find: />=$/, replace: "\u2265" }));
6629
6920
  }
6630
6921
  if (this.options.guillemets) {
6631
- rules.push(textReplace(/<<$/, "\xAB"));
6632
- rules.push(textReplace(/>>$/, "\xBB"));
6922
+ rules.push(textInputRule({ find: /<<$/, replace: "\xAB" }));
6923
+ rules.push(textInputRule({ find: />>$/, replace: "\xBB" }));
6633
6924
  }
6634
6925
  if (this.options.smartQuotes) {
6635
6926
  const { openDoubleQuote, closeDoubleQuote, openSingleQuote, closeSingleQuote } = this.options;
@@ -7374,31 +7665,31 @@ var InvisibleChars = Extension.create({
7374
7665
 
7375
7666
  // src/extensions/TextColor.ts
7376
7667
  var DEFAULT_TEXT_COLORS = [
7377
- // Row 1 Neutrals
7668
+ // Row 1 - Neutrals
7378
7669
  "#000000",
7379
7670
  "#595959",
7380
7671
  "#a6a6a6",
7381
7672
  "#d9d9d9",
7382
7673
  "#ffffff",
7383
- // Row 2 Pastel
7674
+ // Row 2 - Pastel
7384
7675
  "#ffc9c9",
7385
7676
  "#fff3bf",
7386
7677
  "#b2f2bb",
7387
7678
  "#a5d8ff",
7388
7679
  "#d0bfff",
7389
- // Row 3 Vivid
7680
+ // Row 3 - Vivid
7390
7681
  "#e03131",
7391
7682
  "#f08c00",
7392
7683
  "#2f9e44",
7393
7684
  "#1971c2",
7394
7685
  "#7048e8",
7395
- // Row 4 Medium
7686
+ // Row 4 - Medium
7396
7687
  "#ff6b6b",
7397
7688
  "#ffd43b",
7398
7689
  "#69db7c",
7399
7690
  "#4dabf7",
7400
7691
  "#9775fa",
7401
- // Row 5 Dark
7692
+ // Row 5 - Dark
7402
7693
  "#c92a2a",
7403
7694
  "#e67700",
7404
7695
  "#2b8a3e",
@@ -7488,31 +7779,31 @@ var TextColor = Extension.create({
7488
7779
  }
7489
7780
  });
7490
7781
  var DEFAULT_HIGHLIGHT_COLORS = [
7491
- // Row 1 Classic warm highlights
7782
+ // Row 1 - Classic warm highlights
7492
7783
  "#fef08a",
7493
7784
  "#fde68a",
7494
7785
  "#fed7aa",
7495
7786
  "#fecaca",
7496
7787
  "#fbcfe8",
7497
- // Row 2 Lighter warm pastels
7788
+ // Row 2 - Lighter warm pastels
7498
7789
  "#fef9c3",
7499
7790
  "#fef3c7",
7500
7791
  "#ffedd5",
7501
7792
  "#fee2e2",
7502
7793
  "#fce7f3",
7503
- // Row 3 Cool highlights
7794
+ // Row 3 - Cool highlights
7504
7795
  "#a7f3d0",
7505
7796
  "#99f6e4",
7506
7797
  "#a5f3fc",
7507
7798
  "#bfdbfe",
7508
7799
  "#c4b5fd",
7509
- // Row 4 Lighter cool pastels
7800
+ // Row 4 - Lighter cool pastels
7510
7801
  "#d1fae5",
7511
7802
  "#ccfbf1",
7512
7803
  "#cffafe",
7513
7804
  "#dbeafe",
7514
7805
  "#ede9fe",
7515
- // Row 5 Neutrals
7806
+ // Row 5 - Neutrals
7516
7807
  "#e5e7eb",
7517
7808
  "#d1d5db",
7518
7809
  "#f3f4f6",
@@ -7866,11 +8157,13 @@ function linkPopoverPlugin({ editor, markType, protocols }) {
7866
8157
  applyBtn.type = "button";
7867
8158
  applyBtn.className = "dm-link-popover-btn dm-link-popover-apply";
7868
8159
  applyBtn.title = "Apply link";
8160
+ applyBtn.setAttribute("aria-label", "Apply link");
7869
8161
  applyBtn.innerHTML = defaultIcons["check"] ?? "";
7870
8162
  const removeBtn = document.createElement("button");
7871
8163
  removeBtn.type = "button";
7872
8164
  removeBtn.className = "dm-link-popover-btn dm-link-popover-remove";
7873
8165
  removeBtn.title = "Remove link";
8166
+ removeBtn.setAttribute("aria-label", "Remove link");
7874
8167
  removeBtn.innerHTML = defaultIcons["linkBreak"] ?? "";
7875
8168
  el.appendChild(input);
7876
8169
  el.appendChild(applyBtn);
@@ -8636,6 +8929,7 @@ exports.linkPastePlugin = linkPastePlugin;
8636
8929
  exports.linkPastePluginKey = linkPastePluginKey;
8637
8930
  exports.markInputRule = markInputRule;
8638
8931
  exports.markInputRulePatterns = markInputRulePatterns;
8932
+ exports.nodeInputRule = nodeInputRule;
8639
8933
  exports.placeholderPluginKey = placeholderPluginKey;
8640
8934
  exports.positionFloating = positionFloating;
8641
8935
  exports.positionFloatingOnce = positionFloatingOnce;
@@ -8646,6 +8940,8 @@ exports.selectionDecorationPluginKey = selectionDecorationPluginKey;
8646
8940
  exports.setBlockType = setBlockType;
8647
8941
  exports.setContent = setContent;
8648
8942
  exports.setMark = setMark;
8943
+ exports.textInputRule = textInputRule;
8944
+ exports.textblockTypeInputRule = textblockTypeInputRule;
8649
8945
  exports.toggleBlockType = toggleBlockType;
8650
8946
  exports.toggleList = toggleList;
8651
8947
  exports.toggleMark = toggleMark;
@@ -8655,5 +8951,6 @@ exports.unsetAllMarks = unsetAllMarks;
8655
8951
  exports.unsetMark = unsetMark;
8656
8952
  exports.updateAttributes = updateAttributes;
8657
8953
  exports.wrapIn = wrapIn;
8954
+ exports.wrappingInputRule = wrappingInputRule;
8658
8955
  //# sourceMappingURL=index.cjs.map
8659
8956
  //# sourceMappingURL=index.cjs.map