@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.js CHANGED
@@ -1,11 +1,11 @@
1
- import { Selection, TextSelection, PluginKey, Plugin, NodeSelection, AllSelection, EditorState } from '@domternal/pm/state';
1
+ import { Plugin, PluginKey, Selection, TextSelection, NodeSelection, AllSelection, EditorState } from '@domternal/pm/state';
2
2
  export { PluginKey } from '@domternal/pm/state';
3
3
  import { DecorationSet, Decoration, EditorView } from '@domternal/pm/view';
4
4
  import { Slice, Fragment, Schema, Node as Node$1, DOMSerializer, DOMParser } from '@domternal/pm/model';
5
5
  import { keymap } from '@domternal/pm/keymap';
6
- import { textblockTypeInputRule, wrappingInputRule, InputRule, inputRules } from '@domternal/pm/inputrules';
7
6
  import { chainCommands, newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock, baseKeymap, selectNodeBackward as selectNodeBackward$1 } from '@domternal/pm/commands';
8
- import { findWrapping, liftTarget } from '@domternal/pm/transform';
7
+ import { InputRule } from '@domternal/pm/inputrules';
8
+ import { findWrapping, canJoin, liftTarget } from '@domternal/pm/transform';
9
9
  import { liftListItem, sinkListItem, splitListItem, wrapRangeInList } from '@domternal/pm/schema-list';
10
10
  import { offset, flip, shift, autoUpdate, hide, computePosition } from '@floating-ui/dom';
11
11
  import { find } from 'linkifyjs';
@@ -108,6 +108,112 @@ var EventEmitter = class {
108
108
  return Array.from(this.callbacks.keys());
109
109
  }
110
110
  };
111
+ var MAX_MATCH = 500;
112
+ function run(view, from, to, text, rules, plugin) {
113
+ if (view.composing) return false;
114
+ const state = view.state;
115
+ const $from = state.doc.resolve(from);
116
+ const textBefore = $from.parent.textBetween(
117
+ Math.max(0, $from.parentOffset - MAX_MATCH),
118
+ $from.parentOffset,
119
+ null,
120
+ "\uFFFC"
121
+ ) + text;
122
+ for (const rawRule of rules) {
123
+ const rule = rawRule;
124
+ if (!rule.inCodeMark && $from.marks().some((m) => m.type.spec.code)) continue;
125
+ if ($from.parent.type.spec.code) {
126
+ if (!rule.inCode) continue;
127
+ } else if (rule.inCode === "only") {
128
+ continue;
129
+ }
130
+ const match = rule.match.exec(textBefore);
131
+ if (!match || match[0].length < text.length) continue;
132
+ const startPos = from - (match[0].length - text.length);
133
+ if (!rule.inCodeMark) {
134
+ const codeMarks = [];
135
+ state.doc.nodesBetween(startPos, $from.pos, (node) => {
136
+ if (node.isInline && node.marks.some((m) => m.type.spec.code)) codeMarks.push(true);
137
+ });
138
+ if (codeMarks.length > 0) continue;
139
+ }
140
+ const tr = rule.handler(state, match, startPos, to);
141
+ if (!tr) continue;
142
+ if (rule.undoable) {
143
+ tr.setMeta(plugin, { transform: tr, from, to, text });
144
+ }
145
+ view.dispatch(tr);
146
+ return true;
147
+ }
148
+ return false;
149
+ }
150
+ function undoInputRule(plugin, state, dispatch) {
151
+ const undoable = plugin.getState(state);
152
+ if (!undoable) return false;
153
+ if (dispatch) {
154
+ const tr = state.tr;
155
+ const toUndo = undoable.transform;
156
+ for (let j = toUndo.steps.length - 1; j >= 0; j--) {
157
+ const step = toUndo.steps[j];
158
+ const doc = toUndo.docs[j];
159
+ if (step && doc) tr.step(step.invert(doc));
160
+ }
161
+ if (undoable.text) {
162
+ const marks = tr.doc.resolve(undoable.from).marks();
163
+ tr.replaceWith(undoable.from, undoable.to, state.schema.text(undoable.text, marks));
164
+ const endPos = undoable.from + undoable.text.length;
165
+ if (endPos <= tr.doc.content.size) {
166
+ tr.setSelection(TextSelection.create(tr.doc, endPos));
167
+ }
168
+ } else {
169
+ tr.delete(undoable.from, undoable.to);
170
+ }
171
+ dispatch(tr);
172
+ }
173
+ return true;
174
+ }
175
+ function inputRulesPlugin({ rules }) {
176
+ const plugin = new Plugin({
177
+ state: {
178
+ init() {
179
+ return null;
180
+ },
181
+ apply(tr, prev) {
182
+ const stored = tr.getMeta(plugin);
183
+ if (stored) return stored;
184
+ if (tr.getMeta("appendedTransaction")) return prev;
185
+ return tr.selectionSet || tr.docChanged ? null : prev;
186
+ }
187
+ },
188
+ props: {
189
+ handleTextInput(view, from, to, text) {
190
+ return run(view, from, to, text, rules, plugin);
191
+ },
192
+ handleKeyDown(view, event) {
193
+ if (event.key === "Backspace" && !event.ctrlKey && !event.metaKey && !event.altKey) {
194
+ return undoInputRule(plugin, view.state, (tr) => {
195
+ view.dispatch(tr);
196
+ });
197
+ }
198
+ return false;
199
+ },
200
+ handleDOMEvents: {
201
+ compositionend: (view) => {
202
+ setTimeout(() => {
203
+ const { $cursor } = view.state.selection;
204
+ if ($cursor) {
205
+ run(view, $cursor.pos, $cursor.pos, "", rules, plugin);
206
+ }
207
+ });
208
+ }
209
+ }
210
+ },
211
+ // Tag so external undoInputRule can also find this plugin
212
+ isInputRules: true
213
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
214
+ });
215
+ return plugin;
216
+ }
111
217
 
112
218
  // src/helpers/callOrReturn.ts
113
219
  function callOrReturn(value, context, ...args) {
@@ -485,14 +591,14 @@ var ExtensionManager = class {
485
591
  */
486
592
  buildPlugins() {
487
593
  const plugins = [];
594
+ const rules = this.collectInputRules();
595
+ if (rules.length > 0) {
596
+ plugins.push(inputRulesPlugin({ rules }));
597
+ }
488
598
  const shortcuts = this.collectKeyboardShortcuts();
489
599
  if (Object.keys(shortcuts).length > 0) {
490
600
  plugins.push(keymap(shortcuts));
491
601
  }
492
- const rules = this.collectInputRules();
493
- if (rules.length > 0) {
494
- plugins.push(inputRules({ rules }));
495
- }
496
602
  for (const ext of this._extensions) {
497
603
  const addPlugins = ext.config.addProseMirrorPlugins;
498
604
  if (addPlugins) {
@@ -601,8 +707,12 @@ var ExtensionManager = class {
601
707
  return items;
602
708
  }
603
709
  /**
604
- * Collects node views from all Node extensions
605
- * Returns a map of node name NodeViewConstructor for EditorView
710
+ * Collects node views from all Node extensions.
711
+ * Returns a map of node name to NodeViewConstructor for EditorView.
712
+ *
713
+ * Each constructor is annotated with `__domternalContext` containing
714
+ * the editor and extension metadata so framework wrappers (React, Vue)
715
+ * can access them without changing the ProseMirror calling convention.
606
716
  */
607
717
  collectNodeViews() {
608
718
  const nodeViews = {};
@@ -616,6 +726,10 @@ var ExtensionManager = class {
616
726
  `${ext.name}.addNodeView`
617
727
  );
618
728
  if (nodeView) {
729
+ nodeView.__domternalContext = {
730
+ editor: this.editor,
731
+ extension: { name: nodeExt.name, options: nodeExt.options }
732
+ };
619
733
  nodeViews[ext.name] = nodeView;
620
734
  }
621
735
  }
@@ -935,7 +1049,7 @@ function isDocumentEmpty(doc) {
935
1049
  });
936
1050
  }
937
1051
  function markInputRule(options) {
938
- const { find: find2, type, getAttributes } = options;
1052
+ const { find: find2, type, getAttributes, undoable } = options;
939
1053
  return new InputRule(
940
1054
  find2,
941
1055
  (state, match, start, end) => {
@@ -952,7 +1066,8 @@ function markInputRule(options) {
952
1066
  tr.addMark(start, start + textContent.length, type.create(attributes ?? void 0));
953
1067
  tr.removeStoredMark(type);
954
1068
  return tr;
955
- }
1069
+ },
1070
+ undoable !== void 0 ? { undoable } : {}
956
1071
  );
957
1072
  }
958
1073
  var markInputRulePatterns = {
@@ -977,6 +1092,69 @@ var markInputRulePatterns = {
977
1092
  */
978
1093
  highlight: /(?:==)([^=]+)(?:==)$/
979
1094
  };
1095
+ function wrappingInputRule(options) {
1096
+ const { find: find2, type, getAttributes = null, joinPredicate, undoable, guard } = options;
1097
+ return new InputRule(
1098
+ find2,
1099
+ (state, match, start, end) => {
1100
+ if (guard && !guard(state)) return null;
1101
+ const attrs = getAttributes instanceof Function ? getAttributes(match) : getAttributes;
1102
+ const tr = state.tr.delete(start, end);
1103
+ const $start = tr.doc.resolve(start);
1104
+ const range = $start.blockRange();
1105
+ const wrapping = range && findWrapping(range, type, attrs);
1106
+ if (!wrapping) return null;
1107
+ tr.wrap(range, wrapping);
1108
+ const before = tr.doc.resolve(start - 1).nodeBefore;
1109
+ if (before?.type === type && canJoin(tr.doc, start - 1) && (!joinPredicate || joinPredicate(match, before))) {
1110
+ tr.join(start - 1);
1111
+ }
1112
+ return tr;
1113
+ },
1114
+ undoable !== void 0 ? { undoable } : {}
1115
+ );
1116
+ }
1117
+ function notInsideList(state) {
1118
+ const { $from } = state.selection;
1119
+ for (let d = $from.depth; d > 0; d--) {
1120
+ const name = $from.node(d).type.name;
1121
+ if (name === "listItem" || name === "taskItem") return false;
1122
+ }
1123
+ return true;
1124
+ }
1125
+ function textblockTypeInputRule(options) {
1126
+ const { find: find2, type, getAttributes = null, undoable } = options;
1127
+ return new InputRule(
1128
+ find2,
1129
+ (state, match, start, end) => {
1130
+ const $start = state.doc.resolve(start);
1131
+ const attrs = getAttributes instanceof Function ? getAttributes(match) : getAttributes;
1132
+ if (!$start.node(-1).canReplaceWith($start.index(-1), $start.indexAfter(-1), type)) return null;
1133
+ return state.tr.delete(start, end).setBlockType(start, start, type, attrs);
1134
+ },
1135
+ undoable !== void 0 ? { undoable } : {}
1136
+ );
1137
+ }
1138
+ function textInputRule(options) {
1139
+ const { find: find2, replace, undoable } = options;
1140
+ return new InputRule(
1141
+ find2,
1142
+ (state, _match, start, end) => state.tr.replaceWith(start, end, state.schema.text(replace)),
1143
+ undoable !== void 0 ? { undoable } : {}
1144
+ );
1145
+ }
1146
+ function nodeInputRule(options) {
1147
+ const { find: find2, type, getAttributes = null, undoable } = options;
1148
+ return new InputRule(
1149
+ find2,
1150
+ (state, match, start, end) => {
1151
+ const attrs = getAttributes instanceof Function ? getAttributes(match, state) : getAttributes;
1152
+ if (getAttributes instanceof Function && attrs === null) return null;
1153
+ return state.tr.replaceWith(start, end, type.create(attrs));
1154
+ },
1155
+ undoable !== void 0 ? { undoable } : {}
1156
+ );
1157
+ }
980
1158
 
981
1159
  // src/helpers/isValidUrl.ts
982
1160
  function isValidUrl(url, options = {}) {
@@ -1865,8 +2043,18 @@ var toggleWrap = (nodeName, attributes) => (props) => {
1865
2043
  const allWrapped = contentBlocks.length > 0 ? contentBlocks.every(({ pos }) => isInsideWrap(pos)) : isInsideWrap(from);
1866
2044
  if (allWrapped) {
1867
2045
  const first = contentBlocks[0];
1868
- if (first) {
1869
- tr.setSelection(TextSelection.create(tr.doc, first.pos + 1));
2046
+ const last = contentBlocks[contentBlocks.length - 1];
2047
+ if (first && last) {
2048
+ const $liftFrom = tr.doc.resolve(first.pos + 1);
2049
+ const $liftTo = tr.doc.resolve(last.pos + 1);
2050
+ const range = $liftFrom.blockRange($liftTo);
2051
+ if (!range) return false;
2052
+ const target = liftTarget(range);
2053
+ if (target === null) return false;
2054
+ if (!dispatch) return true;
2055
+ tr.lift(range, target).scrollIntoView();
2056
+ dispatch(tr);
2057
+ return true;
1870
2058
  }
1871
2059
  return lift()(props);
1872
2060
  }
@@ -1900,6 +2088,36 @@ var lift = () => ({ tr, dispatch }) => {
1900
2088
  dispatch(tr);
1901
2089
  return true;
1902
2090
  };
2091
+ function joinListBackwards(tr, listType) {
2092
+ const { $from } = tr.selection;
2093
+ for (let d = $from.depth; d >= 0; d--) {
2094
+ if ($from.node(d).type === listType) {
2095
+ const listPos = $from.before(d);
2096
+ if (listPos > 0 && canJoin(tr.doc, listPos)) {
2097
+ const nodeBefore = tr.doc.resolve(listPos - 1).parent;
2098
+ if (nodeBefore.type === listType) {
2099
+ tr.join(listPos);
2100
+ }
2101
+ }
2102
+ return;
2103
+ }
2104
+ }
2105
+ }
2106
+ function joinListForwards(tr, listType) {
2107
+ const { $from } = tr.selection;
2108
+ for (let d = $from.depth; d >= 0; d--) {
2109
+ if ($from.node(d).type === listType) {
2110
+ const after = $from.after(d);
2111
+ if (after < tr.doc.content.size && canJoin(tr.doc, after)) {
2112
+ const nodeAfter = tr.doc.nodeAt(after);
2113
+ if (nodeAfter?.type === listType) {
2114
+ tr.join(after);
2115
+ }
2116
+ }
2117
+ return;
2118
+ }
2119
+ }
2120
+ }
1903
2121
  var toggleList = (listNodeName, listItemNodeName, attributes) => ({ state, tr, dispatch }) => {
1904
2122
  const listType = state.schema.nodes[listNodeName];
1905
2123
  const listItemType = state.schema.nodes[listItemNodeName];
@@ -2055,11 +2273,56 @@ var toggleList = (listNodeName, listItemNodeName, attributes) => ({ state, tr, d
2055
2273
  dispatch(tr);
2056
2274
  return true;
2057
2275
  }
2058
- const { $from: $wrapFrom, $to: $wrapTo } = tr.selection;
2276
+ const blocksInList = contentBlocks.filter((b) => b.inSomeList);
2277
+ if (blocksInList.length === 0) {
2278
+ const { $from: $wf, $to: $wt } = tr.selection;
2279
+ const wr = $wf.blockRange($wt);
2280
+ if (!wr) return false;
2281
+ if (!wrapRangeInList(dispatch ? tr : null, wr, listType, attributes)) return false;
2282
+ if (dispatch) {
2283
+ joinListBackwards(tr, listType);
2284
+ joinListForwards(tr, listType);
2285
+ dispatch(tr.scrollIntoView());
2286
+ }
2287
+ return true;
2288
+ }
2289
+ if (!dispatch) return true;
2290
+ const seen = /* @__PURE__ */ new Set();
2291
+ const listPositions = [];
2292
+ for (const block of blocksInList) {
2293
+ const $pos = tr.doc.resolve(block.pos);
2294
+ for (let d = $pos.depth; d >= 0; d--) {
2295
+ const groups = ($pos.node(d).type.spec.group ?? "").split(/\s+/);
2296
+ if (groups.includes("list")) {
2297
+ const lpos = $pos.before(d);
2298
+ if (!seen.has(lpos)) {
2299
+ seen.add(lpos);
2300
+ listPositions.push(lpos);
2301
+ }
2302
+ break;
2303
+ }
2304
+ }
2305
+ }
2306
+ listPositions.sort((a, b) => b - a);
2307
+ for (const pos of listPositions) {
2308
+ const listNode = tr.doc.nodeAt(pos);
2309
+ if (!listNode) continue;
2310
+ const children = [];
2311
+ listNode.forEach((item) => {
2312
+ item.forEach((child) => children.push(child));
2313
+ });
2314
+ tr.replaceWith(pos, pos + listNode.nodeSize, children);
2315
+ }
2316
+ const mappedFrom = tr.mapping.map(from, -1);
2317
+ const mappedTo = tr.mapping.map(to, 1);
2318
+ const $wrapFrom = tr.doc.resolve(mappedFrom);
2319
+ const $wrapTo = tr.doc.resolve(mappedTo);
2059
2320
  const wrapRange = $wrapFrom.blockRange($wrapTo);
2060
2321
  if (!wrapRange) return false;
2061
- if (!wrapRangeInList(dispatch ? tr : null, wrapRange, listType, attributes)) return false;
2062
- if (dispatch) dispatch(tr.scrollIntoView());
2322
+ wrapRangeInList(tr, wrapRange, listType, attributes);
2323
+ joinListBackwards(tr, listType);
2324
+ joinListForwards(tr, listType);
2325
+ dispatch(tr.scrollIntoView());
2063
2326
  return true;
2064
2327
  };
2065
2328
 
@@ -4408,7 +4671,32 @@ var Heading = Node.create({
4408
4671
  ];
4409
4672
  },
4410
4673
  addProseMirrorPlugins() {
4674
+ const { options, editor } = this;
4675
+ const codeToLevel = {};
4676
+ for (const level of options.levels) {
4677
+ codeToLevel[`Digit${String(level)}`] = level;
4678
+ }
4679
+ codeToLevel["Digit0"] = 0;
4411
4680
  return [
4681
+ new Plugin({
4682
+ key: new PluginKey("headingKeydownFix"),
4683
+ props: {
4684
+ handleDOMEvents: {
4685
+ keydown(_view, event) {
4686
+ if (!event.altKey || !(event.metaKey || event.ctrlKey)) return false;
4687
+ const level = codeToLevel[event.code];
4688
+ if (level === void 0) return false;
4689
+ event.preventDefault();
4690
+ if (level === 0) {
4691
+ editor?.commands["setParagraph"]?.();
4692
+ } else {
4693
+ editor?.commands["toggleHeading"]?.({ level });
4694
+ }
4695
+ return true;
4696
+ }
4697
+ }
4698
+ }
4699
+ }),
4412
4700
  keymap({
4413
4701
  Backspace: ((state, dispatch) => {
4414
4702
  const { selection } = state;
@@ -4435,10 +4723,10 @@ var Heading = Node.create({
4435
4723
  }
4436
4724
  const maxLevel = Math.max(...options.levels);
4437
4725
  return [
4438
- textblockTypeInputRule(
4439
- new RegExp(`^(#{1,${String(maxLevel)}})\\s$`),
4440
- nodeType,
4441
- (match) => {
4726
+ textblockTypeInputRule({
4727
+ find: new RegExp(`^(#{1,${String(maxLevel)}})\\s$`),
4728
+ type: nodeType,
4729
+ getAttributes: (match) => {
4442
4730
  const hashes = match[1];
4443
4731
  if (!hashes) {
4444
4732
  return null;
@@ -4449,10 +4737,12 @@ var Heading = Node.create({
4449
4737
  }
4450
4738
  return { level };
4451
4739
  }
4452
- )
4740
+ })
4453
4741
  ];
4454
4742
  }
4455
4743
  });
4744
+
4745
+ // src/nodes/Blockquote.ts
4456
4746
  var Blockquote = Node.create({
4457
4747
  name: "blockquote",
4458
4748
  group: "block",
@@ -4512,7 +4802,7 @@ var Blockquote = Node.create({
4512
4802
  return [];
4513
4803
  }
4514
4804
  return [
4515
- wrappingInputRule(/^\s*>\s$/, nodeType)
4805
+ wrappingInputRule({ find: /^\s*>\s$/, type: nodeType })
4516
4806
  ];
4517
4807
  }
4518
4808
  });
@@ -4642,14 +4932,14 @@ var CodeBlock = Node.create({
4642
4932
  return [];
4643
4933
  }
4644
4934
  return [
4645
- textblockTypeInputRule(
4646
- /^```([a-z]*)?[\s\n]$/,
4647
- nodeType,
4648
- (match) => {
4935
+ textblockTypeInputRule({
4936
+ find: /^```([a-z]*)?[\s\n]$/,
4937
+ type: nodeType,
4938
+ getAttributes: (match) => {
4649
4939
  const language = match[1] ?? null;
4650
4940
  return { language };
4651
4941
  }
4652
- )
4942
+ })
4653
4943
  ];
4654
4944
  }
4655
4945
  });
@@ -4833,14 +5123,16 @@ var BulletList = Node.create({
4833
5123
  }
4834
5124
  return [
4835
5125
  // - item
4836
- wrappingInputRule(/^\s*[-]\s$/, nodeType),
5126
+ wrappingInputRule({ find: /^\s*[-]\s$/, type: nodeType, guard: notInsideList }),
4837
5127
  // * item
4838
- wrappingInputRule(/^\s*[*]\s$/, nodeType),
5128
+ wrappingInputRule({ find: /^\s*[*]\s$/, type: nodeType, guard: notInsideList }),
4839
5129
  // + item
4840
- wrappingInputRule(/^\s*[+]\s$/, nodeType)
5130
+ wrappingInputRule({ find: /^\s*[+]\s$/, type: nodeType, guard: notInsideList })
4841
5131
  ];
4842
5132
  }
4843
5133
  });
5134
+
5135
+ // src/nodes/OrderedList.ts
4844
5136
  var OrderedList = Node.create({
4845
5137
  name: "orderedList",
4846
5138
  group: "block list",
@@ -4916,14 +5208,15 @@ var OrderedList = Node.create({
4916
5208
  }
4917
5209
  return [
4918
5210
  // 1. item (any number followed by . )
4919
- wrappingInputRule(
4920
- /^(\d+)\.\s$/,
4921
- nodeType,
4922
- (match) => {
5211
+ wrappingInputRule({
5212
+ find: /^(\d+)\.\s$/,
5213
+ type: nodeType,
5214
+ guard: notInsideList,
5215
+ getAttributes: (match) => {
4923
5216
  const num = match[1];
4924
5217
  return { start: num ? parseInt(num, 10) : 1 };
4925
5218
  }
4926
- )
5219
+ })
4927
5220
  ];
4928
5221
  }
4929
5222
  });
@@ -4998,13 +5291,12 @@ var HorizontalRule = Node.create({
4998
5291
  const $start = state.doc.resolve(start);
4999
5292
  const from = $start.before();
5000
5293
  const to = $start.after();
5001
- tr.replaceWith(from, to, nodeType.create());
5002
- if (from + 1 < tr.doc.content.size) {
5003
- const $after = tr.doc.resolve(from + 1);
5004
- const sel = TextSelection.findFrom($after, 1);
5005
- if (sel) {
5006
- tr.setSelection(sel);
5007
- }
5294
+ const paragraph = state.schema.nodes["paragraph"]?.create();
5295
+ const nodes = paragraph ? [nodeType.create(), paragraph] : [nodeType.create()];
5296
+ tr.replaceWith(from, to, nodes);
5297
+ const sel = TextSelection.findFrom(tr.doc.resolve(from + 1), 1);
5298
+ if (sel) {
5299
+ tr.setSelection(sel);
5008
5300
  }
5009
5301
  }
5010
5302
  return tr;
@@ -5295,9 +5587,9 @@ var TaskList = Node.create({
5295
5587
  }
5296
5588
  return [
5297
5589
  // [ ] at start of line creates unchecked task
5298
- wrappingInputRule(/^\s*\[\s?\]\s$/, nodeType),
5590
+ wrappingInputRule({ find: /^\s*\[\s?\]\s$/, type: nodeType, guard: notInsideList }),
5299
5591
  // [x] or [X] at start of line creates checked task
5300
- wrappingInputRule(/^\s*\[[xX]\]\s$/, nodeType)
5592
+ wrappingInputRule({ find: /^\s*\[[xX]\]\s$/, type: nodeType, guard: notInsideList })
5301
5593
  ];
5302
5594
  }
5303
5595
  });
@@ -6595,40 +6887,39 @@ var Typography = Extension.create({
6595
6887
  },
6596
6888
  addInputRules() {
6597
6889
  const rules = [];
6598
- const textReplace = (find2, replacement) => new InputRule(find2, (state, _match, start, end) => state.tr.replaceWith(start, end, state.schema.text(replacement)));
6599
6890
  if (this.options.emDash) {
6600
- rules.push(textReplace(/--$/, "\u2014"));
6891
+ rules.push(textInputRule({ find: /--$/, replace: "\u2014" }));
6601
6892
  }
6602
6893
  if (this.options.ellipsis) {
6603
- rules.push(textReplace(/\.\.\.$/, "\u2026"));
6894
+ rules.push(textInputRule({ find: /\.\.\.$/, replace: "\u2026" }));
6604
6895
  }
6605
6896
  if (this.options.arrows) {
6606
- rules.push(textReplace(/<-$/, "\u2190"));
6607
- rules.push(textReplace(/->$/, "\u2192"));
6608
- rules.push(textReplace(/=>$/, "\u21D2"));
6897
+ rules.push(textInputRule({ find: /<-$/, replace: "\u2190" }));
6898
+ rules.push(textInputRule({ find: /->$/, replace: "\u2192" }));
6899
+ rules.push(textInputRule({ find: /=>$/, replace: "\u21D2" }));
6609
6900
  }
6610
6901
  if (this.options.fractions) {
6611
- rules.push(textReplace(/1\/2$/, "\xBD"));
6612
- rules.push(textReplace(/1\/4$/, "\xBC"));
6613
- rules.push(textReplace(/3\/4$/, "\xBE"));
6614
- rules.push(textReplace(/1\/3$/, "\u2153"));
6615
- rules.push(textReplace(/2\/3$/, "\u2154"));
6902
+ rules.push(textInputRule({ find: /1\/2$/, replace: "\xBD" }));
6903
+ rules.push(textInputRule({ find: /1\/4$/, replace: "\xBC" }));
6904
+ rules.push(textInputRule({ find: /3\/4$/, replace: "\xBE" }));
6905
+ rules.push(textInputRule({ find: /1\/3$/, replace: "\u2153" }));
6906
+ rules.push(textInputRule({ find: /2\/3$/, replace: "\u2154" }));
6616
6907
  }
6617
6908
  if (this.options.symbols) {
6618
- rules.push(textReplace(/\(c\)$/i, "\xA9"));
6619
- rules.push(textReplace(/\(r\)$/i, "\xAE"));
6620
- rules.push(textReplace(/\(tm\)$/i, "\u2122"));
6621
- rules.push(textReplace(/\(sm\)$/i, "\u2120"));
6909
+ rules.push(textInputRule({ find: /\(c\)$/i, replace: "\xA9" }));
6910
+ rules.push(textInputRule({ find: /\(r\)$/i, replace: "\xAE" }));
6911
+ rules.push(textInputRule({ find: /\(tm\)$/i, replace: "\u2122" }));
6912
+ rules.push(textInputRule({ find: /\(sm\)$/i, replace: "\u2120" }));
6622
6913
  }
6623
6914
  if (this.options.math) {
6624
- rules.push(textReplace(/\+\/-$/, "\xB1"));
6625
- rules.push(textReplace(/!=$/, "\u2260"));
6626
- rules.push(textReplace(/<=$/, "\u2264"));
6627
- rules.push(textReplace(/>=$/, "\u2265"));
6915
+ rules.push(textInputRule({ find: /\+\/-$/, replace: "\xB1" }));
6916
+ rules.push(textInputRule({ find: /!=$/, replace: "\u2260" }));
6917
+ rules.push(textInputRule({ find: /<=$/, replace: "\u2264" }));
6918
+ rules.push(textInputRule({ find: />=$/, replace: "\u2265" }));
6628
6919
  }
6629
6920
  if (this.options.guillemets) {
6630
- rules.push(textReplace(/<<$/, "\xAB"));
6631
- rules.push(textReplace(/>>$/, "\xBB"));
6921
+ rules.push(textInputRule({ find: /<<$/, replace: "\xAB" }));
6922
+ rules.push(textInputRule({ find: />>$/, replace: "\xBB" }));
6632
6923
  }
6633
6924
  if (this.options.smartQuotes) {
6634
6925
  const { openDoubleQuote, closeDoubleQuote, openSingleQuote, closeSingleQuote } = this.options;
@@ -7373,31 +7664,31 @@ var InvisibleChars = Extension.create({
7373
7664
 
7374
7665
  // src/extensions/TextColor.ts
7375
7666
  var DEFAULT_TEXT_COLORS = [
7376
- // Row 1 Neutrals
7667
+ // Row 1 - Neutrals
7377
7668
  "#000000",
7378
7669
  "#595959",
7379
7670
  "#a6a6a6",
7380
7671
  "#d9d9d9",
7381
7672
  "#ffffff",
7382
- // Row 2 Pastel
7673
+ // Row 2 - Pastel
7383
7674
  "#ffc9c9",
7384
7675
  "#fff3bf",
7385
7676
  "#b2f2bb",
7386
7677
  "#a5d8ff",
7387
7678
  "#d0bfff",
7388
- // Row 3 Vivid
7679
+ // Row 3 - Vivid
7389
7680
  "#e03131",
7390
7681
  "#f08c00",
7391
7682
  "#2f9e44",
7392
7683
  "#1971c2",
7393
7684
  "#7048e8",
7394
- // Row 4 Medium
7685
+ // Row 4 - Medium
7395
7686
  "#ff6b6b",
7396
7687
  "#ffd43b",
7397
7688
  "#69db7c",
7398
7689
  "#4dabf7",
7399
7690
  "#9775fa",
7400
- // Row 5 Dark
7691
+ // Row 5 - Dark
7401
7692
  "#c92a2a",
7402
7693
  "#e67700",
7403
7694
  "#2b8a3e",
@@ -7487,31 +7778,31 @@ var TextColor = Extension.create({
7487
7778
  }
7488
7779
  });
7489
7780
  var DEFAULT_HIGHLIGHT_COLORS = [
7490
- // Row 1 Classic warm highlights
7781
+ // Row 1 - Classic warm highlights
7491
7782
  "#fef08a",
7492
7783
  "#fde68a",
7493
7784
  "#fed7aa",
7494
7785
  "#fecaca",
7495
7786
  "#fbcfe8",
7496
- // Row 2 Lighter warm pastels
7787
+ // Row 2 - Lighter warm pastels
7497
7788
  "#fef9c3",
7498
7789
  "#fef3c7",
7499
7790
  "#ffedd5",
7500
7791
  "#fee2e2",
7501
7792
  "#fce7f3",
7502
- // Row 3 Cool highlights
7793
+ // Row 3 - Cool highlights
7503
7794
  "#a7f3d0",
7504
7795
  "#99f6e4",
7505
7796
  "#a5f3fc",
7506
7797
  "#bfdbfe",
7507
7798
  "#c4b5fd",
7508
- // Row 4 Lighter cool pastels
7799
+ // Row 4 - Lighter cool pastels
7509
7800
  "#d1fae5",
7510
7801
  "#ccfbf1",
7511
7802
  "#cffafe",
7512
7803
  "#dbeafe",
7513
7804
  "#ede9fe",
7514
- // Row 5 Neutrals
7805
+ // Row 5 - Neutrals
7515
7806
  "#e5e7eb",
7516
7807
  "#d1d5db",
7517
7808
  "#f3f4f6",
@@ -7865,11 +8156,13 @@ function linkPopoverPlugin({ editor, markType, protocols }) {
7865
8156
  applyBtn.type = "button";
7866
8157
  applyBtn.className = "dm-link-popover-btn dm-link-popover-apply";
7867
8158
  applyBtn.title = "Apply link";
8159
+ applyBtn.setAttribute("aria-label", "Apply link");
7868
8160
  applyBtn.innerHTML = defaultIcons["check"] ?? "";
7869
8161
  const removeBtn = document.createElement("button");
7870
8162
  removeBtn.type = "button";
7871
8163
  removeBtn.className = "dm-link-popover-btn dm-link-popover-remove";
7872
8164
  removeBtn.title = "Remove link";
8165
+ removeBtn.setAttribute("aria-label", "Remove link");
7873
8166
  removeBtn.innerHTML = defaultIcons["linkBreak"] ?? "";
7874
8167
  el.appendChild(input);
7875
8168
  el.appendChild(applyBtn);
@@ -8527,6 +8820,6 @@ var StarterKit = Extension.create({
8527
8820
  // src/index.ts
8528
8821
  var VERSION = "0.1.0";
8529
8822
 
8530
- export { BaseKeymap, Blockquote, Bold, BubbleMenu, BulletList, CanChecker, ChainBuilder, CharacterCount, ClearFormatting, Code, CodeBlock, CommandManager, DEFAULT_HIGHLIGHT_COLORS, DEFAULT_TEXT_COLORS, Document, Dropcursor, Editor, EventEmitter, Extension, ExtensionManager, FloatingMenu, Focus, FontFamily, FontSize, Gapcursor, HardBreak, Heading, Highlight, History, HorizontalRule, InvisibleChars, Italic, LineHeight, Link, LinkPopover, ListItem, ListKeymap, Mark, Node, OrderedList, Paragraph, Placeholder, Selection3 as Selection, SelectionDecoration, StarterKit, Strike, Subscript, Superscript, TaskItem, TaskList, Text, TextAlign, TextColor, TextStyle, ToolbarController, TrailingNode, Typography, Underline, UniqueID, VERSION, applyInlineStyles, autolinkPlugin, autolinkPluginKey, blur, bubbleMenuPluginKey, buildCommandProps, builtInCommands, callOrReturn, characterCountPluginKey, clearContent, createAccumulatingDispatch, createBubbleMenuPlugin, createCanChecker, createChainBuilder, createDocument, createFloatingMenuPlugin, defaultBlockAt, defaultIcons, deleteSelection, findChildren, findParentNode, floatingMenuPluginKey, focus, focusPluginKey, generateHTML, generateJSON, generateText, getMarkRange, inlineStyles, insertContent, insertText, invisibleCharsPluginKey, isDocumentEmpty, isNodeEmpty, isValidUrl, lift, linkClickPlugin, linkClickPluginKey, linkExitPlugin, linkExitPluginKey, linkPastePlugin, linkPastePluginKey, markInputRule, markInputRulePatterns, placeholderPluginKey, positionFloating, positionFloatingOnce, resetAttributes, selectAll, selectNodeBackward, selectionDecorationPluginKey, setBlockType, setContent, setMark, toggleBlockType, toggleList, toggleMark, toggleWrap, uniqueIDPluginKey, unsetAllMarks, unsetMark, updateAttributes, wrapIn };
8823
+ export { BaseKeymap, Blockquote, Bold, BubbleMenu, BulletList, CanChecker, ChainBuilder, CharacterCount, ClearFormatting, Code, CodeBlock, CommandManager, DEFAULT_HIGHLIGHT_COLORS, DEFAULT_TEXT_COLORS, Document, Dropcursor, Editor, EventEmitter, Extension, ExtensionManager, FloatingMenu, Focus, FontFamily, FontSize, Gapcursor, HardBreak, Heading, Highlight, History, HorizontalRule, InvisibleChars, Italic, LineHeight, Link, LinkPopover, ListItem, ListKeymap, Mark, Node, OrderedList, Paragraph, Placeholder, Selection3 as Selection, SelectionDecoration, StarterKit, Strike, Subscript, Superscript, TaskItem, TaskList, Text, TextAlign, TextColor, TextStyle, ToolbarController, TrailingNode, Typography, Underline, UniqueID, VERSION, applyInlineStyles, autolinkPlugin, autolinkPluginKey, blur, bubbleMenuPluginKey, buildCommandProps, builtInCommands, callOrReturn, characterCountPluginKey, clearContent, createAccumulatingDispatch, createBubbleMenuPlugin, createCanChecker, createChainBuilder, createDocument, createFloatingMenuPlugin, defaultBlockAt, defaultIcons, deleteSelection, findChildren, findParentNode, floatingMenuPluginKey, focus, focusPluginKey, generateHTML, generateJSON, generateText, getMarkRange, inlineStyles, insertContent, insertText, invisibleCharsPluginKey, isDocumentEmpty, isNodeEmpty, isValidUrl, lift, linkClickPlugin, linkClickPluginKey, linkExitPlugin, linkExitPluginKey, linkPastePlugin, linkPastePluginKey, markInputRule, markInputRulePatterns, nodeInputRule, placeholderPluginKey, positionFloating, positionFloatingOnce, resetAttributes, selectAll, selectNodeBackward, selectionDecorationPluginKey, setBlockType, setContent, setMark, textInputRule, textblockTypeInputRule, toggleBlockType, toggleList, toggleMark, toggleWrap, uniqueIDPluginKey, unsetAllMarks, unsetMark, updateAttributes, wrapIn, wrappingInputRule };
8531
8824
  //# sourceMappingURL=index.js.map
8532
8825
  //# sourceMappingURL=index.js.map