@domternal/core 0.13.0 → 0.15.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
@@ -7,7 +7,7 @@ import { splitBlock, chainCommands, newlineInCode, createParagraphNear, liftEmpt
7
7
  import { InputRule } from '@domternal/pm/inputrules';
8
8
  import { canJoin, canSplit, findWrapping, liftTarget } from '@domternal/pm/transform';
9
9
  import { liftListItem, sinkListItem, splitListItem, wrapRangeInList } from '@domternal/pm/schema-list';
10
- import { offset, flip, shift, autoUpdate, hide, computePosition } from '@floating-ui/dom';
10
+ import { autoUpdate, hide, offset, size, flip, shift, computePosition } from '@floating-ui/dom';
11
11
  import { find } from 'linkifyjs';
12
12
  import { history, redo, undo } from '@domternal/pm/history';
13
13
  import { dropCursor } from '@domternal/pm/dropcursor';
@@ -1139,7 +1139,8 @@ function markInputRule(options) {
1139
1139
  return null;
1140
1140
  }
1141
1141
  const { tr } = state;
1142
- tr.replaceWith(start, end, state.schema.text(textContent));
1142
+ const marks = tr.storedMarks ?? tr.doc.resolve(start).marksAcross(tr.doc.resolve(end));
1143
+ tr.replaceWith(start, end, state.schema.text(textContent, marks));
1143
1144
  tr.addMark(start, start + textContent.length, type.create(attributes ?? void 0));
1144
1145
  tr.removeStoredMark(type);
1145
1146
  return tr;
@@ -1231,7 +1232,10 @@ function textInputRule(options) {
1231
1232
  const { find: find2, replace, undoable } = options;
1232
1233
  return new InputRule(
1233
1234
  find2,
1234
- (state, _match, start, end) => state.tr.replaceWith(start, end, state.schema.text(replace)),
1235
+ // insertText inherits the replaced range's marks (stored marks first,
1236
+ // then marksAcross), so a replacement inside marked text keeps the
1237
+ // marks instead of punching an unmarked hole into them.
1238
+ (state, _match, start, end) => state.tr.insertText(replace, start, end),
1235
1239
  undoable !== void 0 ? { undoable } : {}
1236
1240
  );
1237
1241
  }
@@ -1810,6 +1814,8 @@ var Mark = class _Mark extends Extension {
1810
1814
  if (this.config.group !== void 0) spec.group = this.config.group;
1811
1815
  if (this.config.spanning !== void 0)
1812
1816
  spec.spanning = this.config.spanning;
1817
+ if (this.config.keepOnDuplicate !== void 0)
1818
+ spec["keepOnDuplicate"] = this.config.keepOnDuplicate;
1813
1819
  const attributeSpecs = callOrReturn(this.config.addAttributes, this);
1814
1820
  if (attributeSpecs) {
1815
1821
  spec.attrs = buildProseMirrorAttrs(attributeSpecs);
@@ -1847,9 +1853,9 @@ var Mark = class _Mark extends Extension {
1847
1853
  const renderFn = this.config.renderHTML;
1848
1854
  const attrSpecs = attributeSpecs;
1849
1855
  const markInstance = this;
1850
- spec.toDOM = (mark, _inline) => {
1851
- const htmlAttrs = attrSpecs ? buildHTMLAttributes(mark.attrs, attrSpecs) : {};
1852
- return renderFn.call(markInstance, { mark, HTMLAttributes: htmlAttrs });
1856
+ spec.toDOM = (mark2, _inline) => {
1857
+ const htmlAttrs = attrSpecs ? buildHTMLAttributes(mark2.attrs, attrSpecs) : {};
1858
+ return renderFn.call(markInstance, { mark: mark2, HTMLAttributes: htmlAttrs });
1853
1859
  };
1854
1860
  }
1855
1861
  return spec;
@@ -1942,8 +1948,8 @@ var setMark = (markName, attributes) => ({ state, tr, dispatch }) => {
1942
1948
  const from = firstRange.$from.pos;
1943
1949
  const existingMark = tr.storedMarks?.find((m) => m.type === markType) ?? state.storedMarks?.find((m) => m.type === markType) ?? tr.doc.resolve(from).marks().find((m) => m.type === markType) ?? null;
1944
1950
  const mergedAttrs = existingMark ? { ...existingMark.attrs, ...attributes } : attributes;
1945
- const mark = markType.create(mergedAttrs);
1946
- tr.addStoredMark(mark);
1951
+ const mark2 = markType.create(mergedAttrs);
1952
+ tr.addStoredMark(mark2);
1947
1953
  dispatch(tr);
1948
1954
  return true;
1949
1955
  }
@@ -2570,12 +2576,12 @@ var updateAttributes = (typeOrName, attributes) => ({ state, tr, dispatch }) =>
2570
2576
  const markType = state.schema.marks[typeOrName];
2571
2577
  tr.doc.nodesBetween(from, to, (node, pos) => {
2572
2578
  if (!node.isInline) return;
2573
- const mark = markType.isInSet(node.marks);
2574
- if (mark) {
2579
+ const mark2 = markType.isInSet(node.marks);
2580
+ if (mark2) {
2575
2581
  markChanges.push({
2576
2582
  pos,
2577
2583
  nodeSize: node.nodeSize,
2578
- attrs: { ...mark.attrs, ...attributes }
2584
+ attrs: { ...mark2.attrs, ...attributes }
2579
2585
  });
2580
2586
  }
2581
2587
  });
@@ -2621,12 +2627,12 @@ var resetAttributes = (typeOrName, attributeName) => ({ state, tr, dispatch }) =
2621
2627
  const defaultValue = markType.spec.attrs?.[attributeName]?.default;
2622
2628
  tr.doc.nodesBetween(from, to, (node, pos) => {
2623
2629
  if (!node.isInline) return;
2624
- const mark = markType.isInSet(node.marks);
2625
- if (mark) {
2630
+ const mark2 = markType.isInSet(node.marks);
2631
+ if (mark2) {
2626
2632
  markChanges.push({
2627
2633
  pos,
2628
2634
  nodeSize: node.nodeSize,
2629
- attrs: { ...mark.attrs, [attributeName]: defaultValue }
2635
+ attrs: { ...mark2.attrs, [attributeName]: defaultValue }
2630
2636
  });
2631
2637
  }
2632
2638
  });
@@ -3509,6 +3515,12 @@ var Editor = class _Editor extends EventEmitter {
3509
3515
  * True while EditorView's constructor runs; see buildViewDispatch.
3510
3516
  */
3511
3517
  _isViewConstructing = false;
3518
+ /**
3519
+ * The `.dm-editor` host this editor painted `dm-notion-mode` onto because
3520
+ * of `preset: 'notion'`. Tracked so destroy() removes only a class the
3521
+ * editor itself added, never one the consumer wrote.
3522
+ */
3523
+ _presetClassHost = null;
3512
3524
  /**
3513
3525
  * Creates a new Editor instance
3514
3526
  *
@@ -3553,6 +3565,43 @@ var Editor = class _Editor extends EventEmitter {
3553
3565
  get isEditable() {
3554
3566
  return this.view ? this.view.editable : this.options.editable ?? true;
3555
3567
  }
3568
+ /**
3569
+ * The resolved editing-experience preset.
3570
+ *
3571
+ * The `preset` option wins when provided (so an explicit 'classic' can
3572
+ * opt out of everything). Otherwise a `dm-notion-mode` class on or above
3573
+ * the view counts as 'notion': consumers that predate the option declare
3574
+ * Notion mode with the theme class alone, and behavior must follow what
3575
+ * the user actually sees. Resolved on every read, not cached, so a class
3576
+ * toggled at runtime is picked up.
3577
+ */
3578
+ get preset() {
3579
+ if (this.options.preset) {
3580
+ return this.options.preset;
3581
+ }
3582
+ if (this.view?.dom.closest(".dm-notion-mode")) {
3583
+ return "notion";
3584
+ }
3585
+ return "classic";
3586
+ }
3587
+ /**
3588
+ * Paints `dm-notion-mode` on the `.dm-editor` host when the editor was
3589
+ * created with `preset: 'notion'`. Runs during creation, and framework
3590
+ * wrappers call it again after adopting the view's DOM: they construct
3591
+ * the editor in a detached element, so the creation-time run cannot see
3592
+ * the host yet. Idempotent; a no-op for any other preset. Only a class
3593
+ * added here is removed again on destroy.
3594
+ */
3595
+ adoptPresetClass() {
3596
+ if (this.options.preset !== "notion" || this._presetClassHost) {
3597
+ return;
3598
+ }
3599
+ const host = this.view.dom.closest(".dm-editor");
3600
+ if (host && !host.classList.contains("dm-notion-mode")) {
3601
+ host.classList.add("dm-notion-mode");
3602
+ this._presetClassHost = host;
3603
+ }
3604
+ }
3556
3605
  /**
3557
3606
  * Checks if the editor content is empty
3558
3607
  */
@@ -3638,11 +3687,11 @@ var Editor = class _Editor extends EventEmitter {
3638
3687
  if (markType) {
3639
3688
  if (selection.empty) {
3640
3689
  const storedMarks = state.storedMarks ?? $from.marks();
3641
- const hasMark = storedMarks.some((mark) => mark.type === markType);
3690
+ const hasMark = storedMarks.some((mark2) => mark2.type === markType);
3642
3691
  if (!hasMark) return false;
3643
3692
  if (attrs) {
3644
- const mark = storedMarks.find((m) => m.type === markType);
3645
- return mark ? this.matchAttributes(mark.attrs, attrs) : false;
3693
+ const mark2 = storedMarks.find((m) => m.type === markType);
3694
+ return mark2 ? this.matchAttributes(mark2.attrs, attrs) : false;
3646
3695
  }
3647
3696
  return true;
3648
3697
  }
@@ -3717,8 +3766,8 @@ var Editor = class _Editor extends EventEmitter {
3717
3766
  const markType = schema.marks[name];
3718
3767
  if (markType) {
3719
3768
  const marks = state.storedMarks ?? $from.marks();
3720
- const mark = marks.find((m) => m.type === markType);
3721
- return mark ? { ...mark.attrs } : {};
3769
+ const mark2 = marks.find((m) => m.type === markType);
3770
+ return mark2 ? { ...mark2.attrs } : {};
3722
3771
  }
3723
3772
  const nodeType = schema.nodes[name];
3724
3773
  if (nodeType) {
@@ -3899,6 +3948,10 @@ var Editor = class _Editor extends EventEmitter {
3899
3948
  }
3900
3949
  this.emit("destroy");
3901
3950
  this.options.onDestroy?.();
3951
+ if (this._presetClassHost) {
3952
+ this._presetClassHost.classList.remove("dm-notion-mode");
3953
+ this._presetClassHost = null;
3954
+ }
3902
3955
  this.view.destroy();
3903
3956
  this._extensionManager.destroy();
3904
3957
  this.removeAllListeners();
@@ -4001,6 +4054,7 @@ var Editor = class _Editor extends EventEmitter {
4001
4054
  }
4002
4055
  });
4003
4056
  this._isViewConstructing = false;
4057
+ this.adoptPresetClass();
4004
4058
  this.emit("mount", { editor: this, view: this.view });
4005
4059
  this.options.onMount?.({ editor: this, view: this.view });
4006
4060
  this.commandManager = new CommandManager(this);
@@ -4065,16 +4119,50 @@ var Editor = class _Editor extends EventEmitter {
4065
4119
  return super.emit(event, ...args);
4066
4120
  }
4067
4121
  };
4068
- function positionFloating(reference, floating, options) {
4069
- const placementOpt = options?.placement ?? "bottom";
4122
+ var OPPOSITE_SIDE = {
4123
+ top: "bottom",
4124
+ bottom: "top",
4125
+ left: "right",
4126
+ right: "left"
4127
+ };
4128
+ function oppositePlacement(placement) {
4129
+ const [side = "", alignment] = placement.split("-");
4130
+ const opposite = OPPOSITE_SIDE[side] ?? side;
4131
+ return alignment ? `${opposite}-${alignment}` : opposite;
4132
+ }
4133
+ function buildMiddleware(options, placementOpt) {
4070
4134
  const paddingOpt = options?.padding ?? 10;
4071
4135
  const overflowOpts = options?.boundary ? { padding: paddingOpt, boundary: options.boundary } : { padding: paddingOpt };
4072
- const middleware = [
4073
- offset(options?.offsetValue ?? 4),
4074
- flip(overflowOpts),
4075
- shift(overflowOpts),
4076
- hide()
4077
- ];
4136
+ const constrain = options?.constrainHeight;
4137
+ const middleware = [offset(options?.offsetValue ?? 4)];
4138
+ if (constrain) {
4139
+ middleware.push(
4140
+ size({
4141
+ ...overflowOpts,
4142
+ apply({ availableHeight, elements }) {
4143
+ elements.floating.style.setProperty(
4144
+ "--dm-available-height",
4145
+ `${String(Math.max(constrain.minHeight, Math.floor(availableHeight)))}px`
4146
+ );
4147
+ }
4148
+ })
4149
+ );
4150
+ middleware.push(
4151
+ flip({
4152
+ ...overflowOpts,
4153
+ crossAxis: false,
4154
+ fallbackPlacements: [oppositePlacement(placementOpt)]
4155
+ })
4156
+ );
4157
+ } else {
4158
+ middleware.push(flip(overflowOpts));
4159
+ }
4160
+ middleware.push(shift(overflowOpts));
4161
+ return middleware;
4162
+ }
4163
+ function positionFloating(reference, floating, options) {
4164
+ const placementOpt = options?.placement ?? "bottom";
4165
+ const middleware = [...buildMiddleware(options, placementOpt), hide()];
4078
4166
  const update = () => {
4079
4167
  void computePosition(
4080
4168
  reference,
@@ -4102,13 +4190,7 @@ function positionFloating(reference, floating, options) {
4102
4190
  }
4103
4191
  function positionFloatingOnce(reference, floating, options) {
4104
4192
  const placementOpt = options?.placement ?? "bottom";
4105
- const paddingOpt = options?.padding ?? 10;
4106
- const overflowOpts = options?.boundary ? { padding: paddingOpt, boundary: options.boundary } : { padding: paddingOpt };
4107
- const middleware = [
4108
- offset(options?.offsetValue ?? 4),
4109
- flip(overflowOpts),
4110
- shift(overflowOpts)
4111
- ];
4193
+ const middleware = buildMiddleware(options, placementOpt);
4112
4194
  const update = () => {
4113
4195
  void computePosition(
4114
4196
  reference,
@@ -4209,7 +4291,6 @@ function refocusEditorAfterCommand(view) {
4209
4291
  }
4210
4292
 
4211
4293
  // src/utils/defaultBubbleContexts.ts
4212
- var NOTION_MODE_CLASS = "dm-notion-mode";
4213
4294
  var NOTION_TEXT_CONTEXT = Object.freeze([
4214
4295
  // `ai` leads (Notion's "Ask AI"); skipped with its leading separator when
4215
4296
  // the pro extension is absent, exactly like `mathInline`.
@@ -4237,8 +4318,7 @@ var STANDARD_TEXT_CONTEXT = Object.freeze([
4237
4318
  "link"
4238
4319
  ]);
4239
4320
  function defaultBubbleContexts(editor) {
4240
- const inNotionMode = editor.view.dom.closest("." + NOTION_MODE_CLASS) !== null;
4241
- const text = inNotionMode ? NOTION_TEXT_CONTEXT : STANDARD_TEXT_CONTEXT;
4321
+ const text = editor.preset === "notion" ? NOTION_TEXT_CONTEXT : STANDARD_TEXT_CONTEXT;
4242
4322
  return { text: [...text] };
4243
4323
  }
4244
4324
 
@@ -4700,6 +4780,7 @@ var ToolbarController = class _ToolbarController {
4700
4780
  * Executes a toolbar button's command.
4701
4781
  */
4702
4782
  executeCommand(item) {
4783
+ if (!this.editor.isEditable && item.allowReadOnly !== true) return;
4703
4784
  _ToolbarController.executeItem(this.editor, item);
4704
4785
  this.updateActiveStates();
4705
4786
  }
@@ -4942,16 +5023,20 @@ var ToolbarController = class _ToolbarController {
4942
5023
  checkButtonDisabled(item, canProxy) {
4943
5024
  const wasDisabled = this._disabledMap.get(item.name) ?? false;
4944
5025
  let nowDisabled = false;
4945
- try {
4946
- if (item.emitEvent) {
4947
- nowDisabled = this.editor.isActive("codeBlock");
4948
- } else if (canProxy) {
4949
- const canCmd = canProxy[item.command];
4950
- if (canCmd) {
4951
- nowDisabled = item.commandArgs?.length ? !canCmd(...item.commandArgs) : !canCmd();
5026
+ if (!this.editor.isEditable && item.allowReadOnly !== true) {
5027
+ nowDisabled = true;
5028
+ } else {
5029
+ try {
5030
+ if (item.emitEvent) {
5031
+ nowDisabled = this.editor.isActive("codeBlock");
5032
+ } else if (canProxy) {
5033
+ const canCmd = canProxy[item.command];
5034
+ if (canCmd) {
5035
+ nowDisabled = item.commandArgs?.length ? !canCmd(...item.commandArgs) : !canCmd();
5036
+ }
4952
5037
  }
5038
+ } catch {
4953
5039
  }
4954
- } catch {
4955
5040
  }
4956
5041
  if (wasDisabled !== nowDisabled) {
4957
5042
  this._disabledMap.set(item.name, nowDisabled);
@@ -4992,7 +5077,8 @@ function groupFloatingMenuItems(items) {
4992
5077
  if (!list) {
4993
5078
  list = [];
4994
5079
  map.set(name, list);
4995
- order.push(name);
5080
+ if (name === "") order.unshift(name);
5081
+ else order.push(name);
4996
5082
  }
4997
5083
  list.push(item);
4998
5084
  }
@@ -5363,6 +5449,7 @@ function createFloatingMenuPlugin(options) {
5363
5449
  };
5364
5450
  hideMenu();
5365
5451
  const isVisibleNow = (view) => {
5452
+ if (!editor.isEditable) return false;
5366
5453
  const wantsShow = shouldShow({ editor, view, state: view.state });
5367
5454
  if (!requireExplicitTrigger) return wantsShow;
5368
5455
  const triggered = pluginKey.getState(view.state)?.triggered ?? false;
@@ -5525,7 +5612,8 @@ var defaultIcons = {
5525
5612
  plus: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M224,128a8,8,0,0,1-8,8H136v80a8,8,0,0,1-16,0V136H40a8,8,0,0,1,0-16h80V40a8,8,0,0,1,16,0v80h80A8,8,0,0,1,224,128Z"/></svg>',
5526
5613
  dotsSixVertical: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M108,60A16,16,0,1,1,92,44,16,16,0,0,1,108,60Zm56,16A16,16,0,1,0,148,60,16,16,0,0,0,164,76ZM92,112a16,16,0,1,0,16,16A16,16,0,0,0,92,112Zm72,0a16,16,0,1,0,16,16A16,16,0,0,0,164,112ZM92,180a16,16,0,1,0,16,16A16,16,0,0,0,92,180Zm72,0a16,16,0,1,0,16,16A16,16,0,0,0,164,180Z"/></svg>',
5527
5614
  dotsThree: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M140,128a12,12,0,1,1-12-12A12,12,0,0,1,140,128ZM64,116a12,12,0,1,0,12,12A12,12,0,0,0,64,116Zm128,0a12,12,0,1,0,12,12A12,12,0,0,0,192,116Z"/></svg>',
5528
- copy: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,32H88a8,8,0,0,0-8,8V80H40a8,8,0,0,0-8,8V216a8,8,0,0,0,8,8H168a8,8,0,0,0,8-8V176h40a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32ZM160,208H48V96H160Zm48-48H176V88a8,8,0,0,0-8-8H96V48H208Z"/></svg>'
5615
+ copy: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,32H88a8,8,0,0,0-8,8V80H40a8,8,0,0,0-8,8V216a8,8,0,0,0,8,8H168a8,8,0,0,0,8-8V176h40a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32ZM160,208H48V96H160Zm48-48H176V88a8,8,0,0,0-8-8H96V48H208Z"/></svg>',
5616
+ printer: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M214.67,72H200V40a8,8,0,0,0-8-8H64a8,8,0,0,0-8,8V72H41.33C27.36,72,16,82.77,16,96v80a8,8,0,0,0,8,8H56v32a8,8,0,0,0,8,8H192a8,8,0,0,0,8-8V184h32a8,8,0,0,0,8-8V96C240,82.77,228.64,72,214.67,72ZM72,48H184V72H72ZM184,208H72V160H184Zm40-40H200V152a8,8,0,0,0-8-8H64a8,8,0,0,0-8,8v16H32V96c0-4.34,4.28-8,9.33-8H214.67c5.05,0,9.33,3.66,9.33,8Zm-24-52a12,12,0,1,1-12-12A12,12,0,0,1,200,116Z"/></svg>'
5529
5617
  };
5530
5618
 
5531
5619
  // src/nodes/Document.ts
@@ -5742,7 +5830,8 @@ var Heading = Node2.create({
5742
5830
  key: new PluginKey("headingKeydownFix"),
5743
5831
  props: {
5744
5832
  handleDOMEvents: {
5745
- keydown(_view, event) {
5833
+ keydown(view, event) {
5834
+ if (!view.editable) return false;
5746
5835
  if (!event.altKey || !(event.metaKey || event.ctrlKey)) return false;
5747
5836
  const level = codeToLevel[event.code];
5748
5837
  if (level === void 0) return false;
@@ -7056,6 +7145,7 @@ var TaskList = Node2.create({
7056
7145
  // src/marks/Bold.ts
7057
7146
  var Bold = Mark.create({
7058
7147
  name: "bold",
7148
+ group: "formatting",
7059
7149
  addOptions() {
7060
7150
  return {
7061
7151
  HTMLAttributes: {}
@@ -7133,6 +7223,7 @@ var Bold = Mark.create({
7133
7223
  // src/marks/Italic.ts
7134
7224
  var Italic = Mark.create({
7135
7225
  name: "italic",
7226
+ group: "formatting",
7136
7227
  addOptions() {
7137
7228
  return {
7138
7229
  HTMLAttributes: {}
@@ -7212,6 +7303,7 @@ var Italic = Mark.create({
7212
7303
  // src/marks/Underline.ts
7213
7304
  var Underline = Mark.create({
7214
7305
  name: "underline",
7306
+ group: "formatting",
7215
7307
  addOptions() {
7216
7308
  return {
7217
7309
  HTMLAttributes: {}
@@ -7264,6 +7356,7 @@ var Underline = Mark.create({
7264
7356
  // src/marks/Strike.ts
7265
7357
  var Strike = Mark.create({
7266
7358
  name: "strike",
7359
+ group: "formatting",
7267
7360
  addOptions() {
7268
7361
  return {
7269
7362
  HTMLAttributes: {}
@@ -7335,9 +7428,14 @@ var Code = Mark.create({
7335
7428
  HTMLAttributes: {}
7336
7429
  };
7337
7430
  },
7338
- // Code mark is exclusive - it cannot be combined with other marks
7339
- // ProseMirror uses '_' to mean "exclude all marks"
7340
- excludes: "_",
7431
+ // Code cannot be combined with other FORMATTING marks (bold, italic,
7432
+ // color...), but semantic marks outside the group (link, a comment
7433
+ // thread anchor) survive: code excludes the 'formatting' group instead
7434
+ // of '_' (everything). Third-party formatting marks opt into the same
7435
+ // exclusion by declaring group: 'formatting'. Code is in the group
7436
+ // itself, which also keeps it self-exclusive.
7437
+ group: "formatting",
7438
+ excludes: "formatting",
7341
7439
  // Code should not span across multiple nodes
7342
7440
  spanning: false,
7343
7441
  parseHTML() {
@@ -7825,6 +7923,7 @@ var Link = Mark.create({
7825
7923
  // src/marks/Subscript.ts
7826
7924
  var Subscript = Mark.create({
7827
7925
  name: "subscript",
7926
+ group: "formatting",
7828
7927
  // Mutual exclusion handled in toggle commands (not schema)
7829
7928
  // so can() dry-run works correctly for toolbar disabled state
7830
7929
  excludes: "",
@@ -7886,6 +7985,7 @@ var Subscript = Mark.create({
7886
7985
  // src/marks/Superscript.ts
7887
7986
  var Superscript = Mark.create({
7888
7987
  name: "superscript",
7988
+ group: "formatting",
7889
7989
  // Mutual exclusion handled in toggle commands (not schema)
7890
7990
  // so can() dry-run works correctly for toolbar disabled state
7891
7991
  excludes: "",
@@ -7947,6 +8047,7 @@ var Superscript = Mark.create({
7947
8047
  // src/marks/TextStyle.ts
7948
8048
  var TextStyle = Mark.create({
7949
8049
  name: "textStyle",
8050
+ group: "formatting",
7950
8051
  // Lower priority so it renders after other marks
7951
8052
  priority: 101,
7952
8053
  addOptions() {
@@ -8003,7 +8104,7 @@ var TextStyle = Mark.create({
8003
8104
  let hasEmptyTextStyle = false;
8004
8105
  tr.doc.nodesBetween(from, to, (node) => {
8005
8106
  const textStyleMark = node.marks.find(
8006
- (mark) => mark.type.name === this.name
8107
+ (mark2) => mark2.type.name === this.name
8007
8108
  );
8008
8109
  if (textStyleMark) {
8009
8110
  const hasNonNullAttr = Object.values(textStyleMark.attrs).some(
@@ -8017,9 +8118,9 @@ var TextStyle = Mark.create({
8017
8118
  if (!hasEmptyTextStyle) return false;
8018
8119
  if (dispatch) {
8019
8120
  tr.doc.nodesBetween(from, to, (node, pos) => {
8020
- const mark = node.marks.find((m) => m.type === markType);
8021
- if (mark) {
8022
- const hasActiveAttr = Object.values(mark.attrs).some(
8121
+ const mark2 = node.marks.find((m) => m.type === markType);
8122
+ if (mark2) {
8123
+ const hasActiveAttr = Object.values(mark2.attrs).some(
8023
8124
  (v) => v !== null && v !== void 0
8024
8125
  );
8025
8126
  if (!hasActiveAttr) {
@@ -8524,11 +8625,7 @@ var Typography = Extension.create({
8524
8625
  rules.push(
8525
8626
  new InputRule(/"([^"]+)"$/, (state, match, start, end) => {
8526
8627
  const text = match[1] ?? "";
8527
- return state.tr.replaceWith(
8528
- start,
8529
- end,
8530
- state.schema.text(openDoubleQuote + text + closeDoubleQuote)
8531
- );
8628
+ return state.tr.insertText(openDoubleQuote + text + closeDoubleQuote, start, end);
8532
8629
  })
8533
8630
  );
8534
8631
  rules.push(
@@ -8536,12 +8633,10 @@ var Typography = Extension.create({
8536
8633
  const text = match[1] ?? "";
8537
8634
  const prefix = match[0].charAt(0);
8538
8635
  const hasPrefix = prefix !== "'";
8539
- return state.tr.replaceWith(
8636
+ return state.tr.insertText(
8637
+ hasPrefix ? prefix + openSingleQuote + text + closeSingleQuote : openSingleQuote + text + closeSingleQuote,
8540
8638
  start,
8541
- end,
8542
- state.schema.text(
8543
- hasPrefix ? prefix + openSingleQuote + text + closeSingleQuote : openSingleQuote + text + closeSingleQuote
8544
- )
8639
+ end
8545
8640
  );
8546
8641
  })
8547
8642
  );
@@ -8806,6 +8901,9 @@ function generateUUID() {
8806
8901
  });
8807
8902
  }
8808
8903
  var uniqueIDPluginKey = new PluginKey("uniqueID");
8904
+ function isWithin(from, to, ranges) {
8905
+ return ranges.some((range) => from >= range.from && to <= range.to);
8906
+ }
8809
8907
  var UniqueID = Extension.create({
8810
8908
  name: "uniqueID",
8811
8909
  addOptions() {
@@ -8821,7 +8919,13 @@ var UniqueID = Extension.create({
8821
8919
  "listItem",
8822
8920
  "taskItem",
8823
8921
  "image",
8824
- "horizontalRule"
8922
+ "horizontalRule",
8923
+ // Listed even though it lives in a separate package, exactly as
8924
+ // `image` already is: a global attribute only installs on types the
8925
+ // schema actually has, so naming it is inert when the table extension
8926
+ // is not loaded. Without it a table is the one block the block menu
8927
+ // cannot Copy link, and the one an id-anchored feature cannot address.
8928
+ "table"
8825
8929
  ],
8826
8930
  attributeName: "id",
8827
8931
  generateID: generateUUID,
@@ -8849,11 +8953,27 @@ var UniqueID = Extension.create({
8849
8953
  addProseMirrorPlugins() {
8850
8954
  const { types, attributeName, generateID, filterDuplicates } = this.options;
8851
8955
  const editor = this.editor;
8852
- const transformPastedSlice = (slice) => {
8956
+ const replacedRanges = (view) => {
8957
+ if (view?.dragging) return [];
8958
+ const ranges = view?.state?.selection?.ranges;
8959
+ if (ranges === void 0) return [];
8960
+ const replaced = [];
8961
+ for (const range of ranges) {
8962
+ if (range.$to.pos > range.$from.pos) {
8963
+ replaced.push({ from: range.$from.pos, to: range.$to.pos });
8964
+ }
8965
+ }
8966
+ return replaced;
8967
+ };
8968
+ const transformPastedSlice = (slice, view) => {
8969
+ if (view?.dragging?.move === true) return slice;
8853
8970
  const existingIDs = /* @__PURE__ */ new Set();
8854
- editor?.state.doc.descendants((node) => {
8971
+ const replaced = replacedRanges(view);
8972
+ editor?.state.doc.descendants((node, pos) => {
8973
+ if (isWithin(pos, pos + node.nodeSize, replaced)) return false;
8855
8974
  const id = node.attrs[attributeName];
8856
8975
  if (id) existingIDs.add(id);
8976
+ return true;
8857
8977
  });
8858
8978
  const transformNode = (node) => {
8859
8979
  if (!types.includes(node.type.name)) {
@@ -8883,7 +9003,36 @@ var UniqueID = Extension.create({
8883
9003
  slice.openEnd
8884
9004
  );
8885
9005
  };
8886
- const assignMissingIDs = (doc, tr) => {
9006
+ const incumbentPositions = (oldDoc, mapPos) => {
9007
+ const incumbents = /* @__PURE__ */ new Map();
9008
+ oldDoc.descendants((node, pos) => {
9009
+ if (!types.includes(node.type.name)) return;
9010
+ const id = node.attrs[attributeName];
9011
+ if (id && !incumbents.has(id)) incumbents.set(id, mapPos(pos));
9012
+ });
9013
+ return incumbents;
9014
+ };
9015
+ const assignMissingIDs = (doc, tr, incumbents) => {
9016
+ const winners = /* @__PURE__ */ new Map();
9017
+ if (incumbents && incumbents.size > 0) {
9018
+ const occurrences = /* @__PURE__ */ new Map();
9019
+ doc.descendants((node, pos) => {
9020
+ if (!types.includes(node.type.name)) return;
9021
+ const id = node.attrs[attributeName];
9022
+ if (!id) return;
9023
+ const list = occurrences.get(id);
9024
+ if (list) list.push(pos);
9025
+ else occurrences.set(id, [pos]);
9026
+ });
9027
+ for (const [id, positions] of occurrences) {
9028
+ if (positions.length < 2) continue;
9029
+ const incumbentPos = incumbents.get(id);
9030
+ winners.set(
9031
+ id,
9032
+ incumbentPos !== void 0 && positions.includes(incumbentPos) ? incumbentPos : positions[0]
9033
+ );
9034
+ }
9035
+ }
8887
9036
  const seen = /* @__PURE__ */ new Set();
8888
9037
  doc.descendants((node, pos) => {
8889
9038
  if (!types.includes(node.type.name)) return;
@@ -8898,7 +9047,9 @@ var UniqueID = Extension.create({
8898
9047
  });
8899
9048
  return;
8900
9049
  }
8901
- if (seen.has(existingID)) {
9050
+ const winner = winners.get(existingID);
9051
+ const yieldsToWinner = winner !== void 0 && winner !== pos;
9052
+ if (seen.has(existingID) || yieldsToWinner) {
8902
9053
  let id = generateID();
8903
9054
  while (seen.has(id)) id = generateID();
8904
9055
  seen.add(id);
@@ -8920,6 +9071,7 @@ var UniqueID = Extension.create({
8920
9071
  const tr = editorView.state.tr;
8921
9072
  assignMissingIDs(editorView.state.doc, tr);
8922
9073
  if (tr.docChanged) {
9074
+ tr.setMeta("addToHistory", false);
8923
9075
  editorView.dispatch(tr);
8924
9076
  }
8925
9077
  }, 0);
@@ -8930,12 +9082,18 @@ var UniqueID = Extension.create({
8930
9082
  };
8931
9083
  },
8932
9084
  // Ensure new nodes get IDs
8933
- appendTransaction(transactions, _oldState, newState) {
9085
+ appendTransaction(transactions, oldState, newState) {
8934
9086
  const docChanged = transactions.some((tr2) => tr2.docChanged);
8935
9087
  if (!docChanged) return null;
9088
+ const mapForward = (pos) => transactions.reduce((p, transaction) => transaction.mapping.map(p), pos);
8936
9089
  const tr = newState.tr;
8937
- assignMissingIDs(newState.doc, tr);
8938
- return tr.docChanged ? tr : null;
9090
+ assignMissingIDs(newState.doc, tr, incumbentPositions(oldState.doc, mapForward));
9091
+ if (!tr.docChanged) return null;
9092
+ const ridesAlongWithAnEdit = transactions.some(
9093
+ (transaction) => transaction.docChanged && transaction.getMeta("addToHistory") !== false
9094
+ );
9095
+ if (!ridesAlongWithAnEdit) tr.setMeta("addToHistory", false);
9096
+ return tr;
8939
9097
  },
8940
9098
  // Handle paste - filter duplicates
8941
9099
  props: filterDuplicates ? {
@@ -9665,13 +9823,13 @@ var Highlight = Extension.create({
9665
9823
  let hasHighlight = false;
9666
9824
  if (empty) {
9667
9825
  const marks = state.storedMarks ?? state.doc.resolve(from).marks();
9668
- const mark = markType.isInSet(marks);
9669
- hasHighlight = !!mark?.attrs["backgroundColor"] || !!mark?.attrs["backgroundColorToken"];
9826
+ const mark2 = markType.isInSet(marks);
9827
+ hasHighlight = !!mark2?.attrs["backgroundColor"] || !!mark2?.attrs["backgroundColorToken"];
9670
9828
  } else {
9671
9829
  state.doc.nodesBetween(from, to, (node) => {
9672
9830
  if (hasHighlight) return false;
9673
- const mark = markType.isInSet(node.marks);
9674
- if (mark?.attrs["backgroundColor"] || mark?.attrs["backgroundColorToken"]) {
9831
+ const mark2 = markType.isInSet(node.marks);
9832
+ if (mark2?.attrs["backgroundColor"] || mark2?.attrs["backgroundColorToken"]) {
9675
9833
  hasHighlight = true;
9676
9834
  return false;
9677
9835
  }
@@ -9718,7 +9876,8 @@ var Highlight = Extension.create({
9718
9876
  const content = match[1];
9719
9877
  if (!content) return null;
9720
9878
  const { tr } = state;
9721
- tr.replaceWith(start, end, state.schema.text(content));
9879
+ const marks = tr.storedMarks ?? tr.doc.resolve(start).marksAcross(tr.doc.resolve(end));
9880
+ tr.replaceWith(start, end, state.schema.text(content, marks));
9722
9881
  tr.addMark(
9723
9882
  start,
9724
9883
  start + content.length,
@@ -9904,14 +10063,14 @@ var FontSize = Extension.create({
9904
10063
  addToolbarItems() {
9905
10064
  if (this.options.fontSizes.length === 0) return [];
9906
10065
  const sizes = this.options.fontSizes;
9907
- const items = sizes.map((size, i) => ({
10066
+ const items = sizes.map((size2, i) => ({
9908
10067
  type: "button",
9909
- name: `fontSize-${size}`,
10068
+ name: `fontSize-${size2}`,
9910
10069
  command: "setFontSize",
9911
- commandArgs: [size],
9912
- isActive: { name: "textStyle", attributes: { fontSize: size } },
10070
+ commandArgs: [size2],
10071
+ isActive: { name: "textStyle", attributes: { fontSize: size2 } },
9913
10072
  icon: "textSize",
9914
- label: size,
10073
+ label: size2,
9915
10074
  priority: 200 - i
9916
10075
  }));
9917
10076
  if (this.options.showReset) {
@@ -10014,6 +10173,153 @@ var ClearFormatting = Extension.create({
10014
10173
  ];
10015
10174
  }
10016
10175
  });
10176
+
10177
+ // src/extensions/Print.ts
10178
+ var ROOT_CLASS = "dm-print-root";
10179
+ var ANCESTOR_CLASS = "dm-print-ancestor";
10180
+ var PRINTING_CLASS = "dm-printing";
10181
+ var marked = /* @__PURE__ */ new Set();
10182
+ var printing = false;
10183
+ var Print = Extension.create({
10184
+ name: "print",
10185
+ addOptions() {
10186
+ return {
10187
+ toolbar: true,
10188
+ root: null,
10189
+ isolateNativePrint: false
10190
+ };
10191
+ },
10192
+ addStorage() {
10193
+ return { cleanup: null };
10194
+ },
10195
+ addCommands() {
10196
+ return {
10197
+ printDocument: () => ({ dispatch }) => {
10198
+ if (!dispatch) return true;
10199
+ const editor = this.editor;
10200
+ if (!editor || typeof window === "undefined") return false;
10201
+ const root = resolveRoot(editor, this.options.root);
10202
+ if (!root) return false;
10203
+ mark(root);
10204
+ try {
10205
+ emit(editor, "beforePrint", { root });
10206
+ window.print();
10207
+ } finally {
10208
+ unmark();
10209
+ emit(editor, "afterPrint", void 0);
10210
+ }
10211
+ return true;
10212
+ }
10213
+ };
10214
+ },
10215
+ addToolbarItems() {
10216
+ if (!this.options.toolbar) return [];
10217
+ return [
10218
+ {
10219
+ type: "button",
10220
+ name: "print",
10221
+ command: "printDocument",
10222
+ icon: "printer",
10223
+ label: "Print",
10224
+ shortcut: "Mod-P",
10225
+ group: "document",
10226
+ priority: 100,
10227
+ // Reading a document out to paper is not editing it, so the button
10228
+ // stays live in a read-only editor.
10229
+ allowReadOnly: true
10230
+ }
10231
+ ];
10232
+ },
10233
+ addKeyboardShortcuts() {
10234
+ return {
10235
+ // Only bound while the caret is in the editor, which is exactly when
10236
+ // the reader means "print this document" rather than "print this
10237
+ // page". Everywhere else the browser's own Ctrl/Cmd+P is untouched.
10238
+ "Mod-p": () => this.editor?.commands.printDocument() ?? false
10239
+ };
10240
+ },
10241
+ onCreate() {
10242
+ if (!this.options.isolateNativePrint) return;
10243
+ if (typeof window === "undefined") return;
10244
+ const editor = this.editor;
10245
+ if (!editor) return;
10246
+ const resolve = this.options.root;
10247
+ const before = () => {
10248
+ if (printing) return;
10249
+ const root = resolveRoot(editor, resolve);
10250
+ if (!root) return;
10251
+ mark(root);
10252
+ emit(editor, "beforePrint", { root });
10253
+ };
10254
+ const after = () => {
10255
+ if (!printing) return;
10256
+ unmark();
10257
+ emit(editor, "afterPrint", void 0);
10258
+ };
10259
+ window.addEventListener("beforeprint", before);
10260
+ window.addEventListener("afterprint", after);
10261
+ let detachMedia = null;
10262
+ const onMediaChange = (event) => {
10263
+ if (event.matches) before();
10264
+ else after();
10265
+ };
10266
+ if (typeof window.matchMedia === "function") {
10267
+ const media = window.matchMedia("print");
10268
+ if (typeof media.addEventListener === "function") {
10269
+ media.addEventListener("change", onMediaChange);
10270
+ detachMedia = () => {
10271
+ media.removeEventListener("change", onMediaChange);
10272
+ };
10273
+ }
10274
+ }
10275
+ this.storage.cleanup = () => {
10276
+ window.removeEventListener("beforeprint", before);
10277
+ window.removeEventListener("afterprint", after);
10278
+ detachMedia?.();
10279
+ };
10280
+ },
10281
+ onDestroy() {
10282
+ this.storage.cleanup?.();
10283
+ this.storage.cleanup = null;
10284
+ unmark();
10285
+ }
10286
+ });
10287
+ function resolveRoot(editor, resolve) {
10288
+ if (resolve) return resolve(editor);
10289
+ const dom = editor.view.dom;
10290
+ return dom.closest(".dm-editor") ?? dom;
10291
+ }
10292
+ function mark(root) {
10293
+ root.classList.add(ROOT_CLASS);
10294
+ marked.add(root);
10295
+ let node = parentOf(root);
10296
+ while (node) {
10297
+ node.classList.add(ANCESTOR_CLASS);
10298
+ marked.add(node);
10299
+ node = parentOf(node);
10300
+ }
10301
+ document.body.classList.add(PRINTING_CLASS);
10302
+ printing = true;
10303
+ }
10304
+ function parentOf(node) {
10305
+ if (node.parentElement) return node.parentElement;
10306
+ if (typeof ShadowRoot === "undefined") return null;
10307
+ const root = node.getRootNode();
10308
+ return root instanceof ShadowRoot ? root.host : null;
10309
+ }
10310
+ function unmark() {
10311
+ printing = false;
10312
+ if (typeof document === "undefined") return;
10313
+ document.body.classList.remove(PRINTING_CLASS);
10314
+ for (const el of marked) {
10315
+ el.classList.remove(ROOT_CLASS, ANCESTOR_CLASS);
10316
+ }
10317
+ marked.clear();
10318
+ }
10319
+ function emit(editor, name, payload) {
10320
+ const bus = editor;
10321
+ bus.emit?.(name, payload);
10322
+ }
10017
10323
  var linkPopoverPluginKey = new PluginKey("linkPopover");
10018
10324
  function linkPopoverPlugin({ editor, markType, protocols }) {
10019
10325
  const el = document.createElement("div");
@@ -10351,9 +10657,10 @@ function createBubbleMenuPlugin(options) {
10351
10657
  const onDocumentMousedown = (e) => {
10352
10658
  const target = e.target;
10353
10659
  if (!target) return;
10660
+ if (!target.isConnected) return;
10354
10661
  if (element.contains(target)) return;
10355
10662
  if (editor.view.dom.contains(target)) return;
10356
- if (target instanceof HTMLElement && target.closest("[data-dm-editor-ui]")) return;
10663
+ if (target instanceof Element && target.closest("[data-dm-editor-ui]")) return;
10357
10664
  hideMenu();
10358
10665
  suppressed = true;
10359
10666
  };
@@ -10375,7 +10682,7 @@ function createBubbleMenuPlugin(options) {
10375
10682
  if (from !== prevValue.from || to !== prevValue.to) {
10376
10683
  suppressed = false;
10377
10684
  }
10378
- const visible = !suppressed && !selection.empty && shouldShow({
10685
+ const visible = !suppressed && !selection.empty && editor.isEditable && shouldShow({
10379
10686
  editor,
10380
10687
  view: editor.view,
10381
10688
  state: newState,
@@ -10415,7 +10722,7 @@ function createBubbleMenuPlugin(options) {
10415
10722
  if (mouseDown) return;
10416
10723
  const { selection } = editor.view.state;
10417
10724
  const { from, to } = selection;
10418
- const show = !selection.empty && shouldShow({
10725
+ const show = !selection.empty && editor.isEditable && shouldShow({
10419
10726
  editor,
10420
10727
  view: editor.view,
10421
10728
  state: editor.view.state,
@@ -10451,6 +10758,10 @@ function createBubbleMenuPlugin(options) {
10451
10758
  return {
10452
10759
  update: (view, prevState) => {
10453
10760
  if (view.composing) return;
10761
+ if (!view.editable) {
10762
+ hideMenu();
10763
+ return;
10764
+ }
10454
10765
  const state = pluginKey.getState(view.state);
10455
10766
  const prevPluginState = pluginKey.getState(prevState);
10456
10767
  if (state?.visible === prevPluginState?.visible && state?.from === prevPluginState?.from && state?.to === prevPluginState?.to && !(state?.visible && view.state.doc !== prevState.doc)) {
@@ -10583,8 +10894,8 @@ var StarterKit = Extension.create({
10583
10894
  });
10584
10895
 
10585
10896
  // src/index.ts
10586
- var VERSION = "0.1.0";
10897
+ var VERSION = "0.15.0";
10587
10898
 
10588
- export { BaseKeymap, BlockColor, Blockquote, Bold, BubbleMenu, BulletList, CanChecker, ChainBuilder, CharacterCount, ClearFormatting, Code, CodeBlock, CommandManager, DEFAULT_BLOCK_COLORS, DEFAULT_BLOCK_COLOR_TYPES, DEFAULT_HIGHLIGHT_COLORS, DEFAULT_NOTION_COLOR_PALETTE, DEFAULT_TEXT_COLORS, Document, Dropcursor, Editor, EventEmitter, Extension, ExtensionConfigurationError, ExtensionManager, FLOATING_MENU_META, FLOATING_MENU_NO_FOCUS, FloatingMenuController, Focus, FontFamily, FontSize, Gapcursor, HardBreak, Heading, Highlight, History, HorizontalRule, InvisibleChars, Italic, LIST_ITEM_TYPE_NAMES, LineHeight, Link, LinkPopover, ListIndent, ListItem, ListKeymap, Mark, Node2 as Node, NotionColorPicker, OrderedList, Paragraph, Placeholder, Selection5 as Selection, SelectionDecoration, StarterKit, Strike, Subscript, Superscript, TaskItem, TaskList, Text, TextAlign, TextColor, TextStyle, ToolbarController, TrailingNode, Typography, Underline, UniqueID, VERSION, announce, applyInlineStyles, autolinkPlugin, autolinkPluginKey, blur, bubbleMenuPluginKey, buildCommandProps, builtInCommands, callOrReturn, characterCountPluginKey, clearContent, copyThemeClass, createAccumulatingDispatch, createBubbleMenuPlugin, createCanChecker, createChainBuilder, createDocument, createFloatingMenuPlugin, defaultBlockAt, defaultBubbleContexts, defaultFloatingMenuShouldShow, defaultIcons, deleteSelection, findChildren, findListItemAncestorDepth, findParentNode, floatingMenuPluginKey, focus, focusPluginKey, generateHTML, generateJSON, generateText, getListItemCursorContext, getMarkRange, groupFloatingMenuItems, hideFloatingMenu, indentBlockAsListChild, inlineStyles, insertAsListItemChild, insertChildrenZoneSibling, insertContent, insertText, invisibleCharsPluginKey, isDocumentEmpty, isInListItemLabel, isInsideListItem, isNodeEmpty, isValidUrl, lift, liftCurrentListItem, liftEmptyChildrenZoneParagraph, linkClickPlugin, linkClickPluginKey, linkExitPlugin, linkExitPluginKey, linkPastePlugin, linkPastePluginKey, markInputRule, markInputRulePatterns, nodeInputRule, outdentBlockFromListItem, placeholderPluginKey, positionFloating, positionFloatingOnce, refocusEditorAfterCommand, resetAttributes, selectAll, selectNodeBackward, selectionDecorationPluginKey, setBlockType, setContent, setMark, showFloatingMenu, splitListForInsert, stripInlineColorConflicts, textInputRule, textblockTypeInputRule, toggleBlockType, toggleList, toggleMark, toggleWrap, uniqueIDPluginKey, unsetAllMarks, unsetMark, updateAttributes, wrapIn, wrappingInputRule, writeToClipboard };
10899
+ export { BaseKeymap, BlockColor, Blockquote, Bold, BubbleMenu, BulletList, CanChecker, ChainBuilder, CharacterCount, ClearFormatting, Code, CodeBlock, CommandManager, DEFAULT_BLOCK_COLORS, DEFAULT_BLOCK_COLOR_TYPES, DEFAULT_HIGHLIGHT_COLORS, DEFAULT_NOTION_COLOR_PALETTE, DEFAULT_TEXT_COLORS, Document, Dropcursor, Editor, EventEmitter, Extension, ExtensionConfigurationError, ExtensionManager, FLOATING_MENU_META, FLOATING_MENU_NO_FOCUS, FloatingMenuController, Focus, FontFamily, FontSize, Gapcursor, HardBreak, Heading, Highlight, History, HorizontalRule, InvisibleChars, Italic, LIST_ITEM_TYPE_NAMES, LineHeight, Link, LinkPopover, ListIndent, ListItem, ListKeymap, Mark, Node2 as Node, NotionColorPicker, OrderedList, Paragraph, Placeholder, Print, Selection5 as Selection, SelectionDecoration, StarterKit, Strike, Subscript, Superscript, TaskItem, TaskList, Text, TextAlign, TextColor, TextStyle, ToolbarController, TrailingNode, Typography, Underline, UniqueID, VERSION, announce, applyInlineStyles, autolinkPlugin, autolinkPluginKey, blur, bubbleMenuPluginKey, buildCommandProps, builtInCommands, callOrReturn, characterCountPluginKey, clearContent, copyThemeClass, createAccumulatingDispatch, createBubbleMenuPlugin, createCanChecker, createChainBuilder, createDocument, createFloatingMenuPlugin, defaultBlockAt, defaultBubbleContexts, defaultFloatingMenuShouldShow, defaultIcons, deleteSelection, findChildren, findListItemAncestorDepth, findParentNode, floatingMenuPluginKey, focus, focusPluginKey, generateHTML, generateJSON, generateText, getListItemCursorContext, getMarkRange, groupFloatingMenuItems, hideFloatingMenu, indentBlockAsListChild, inlineStyles, insertAsListItemChild, insertChildrenZoneSibling, insertContent, insertText, invisibleCharsPluginKey, isDocumentEmpty, isInListItemLabel, isInsideListItem, isNodeEmpty, isValidUrl, lift, liftCurrentListItem, liftEmptyChildrenZoneParagraph, linkClickPlugin, linkClickPluginKey, linkExitPlugin, linkExitPluginKey, linkPastePlugin, linkPastePluginKey, markInputRule, markInputRulePatterns, nodeInputRule, outdentBlockFromListItem, placeholderPluginKey, positionFloating, positionFloatingOnce, refocusEditorAfterCommand, resetAttributes, selectAll, selectNodeBackward, selectionDecorationPluginKey, setBlockType, setContent, setMark, showFloatingMenu, splitListForInsert, stripInlineColorConflicts, textInputRule, textblockTypeInputRule, toggleBlockType, toggleList, toggleMark, toggleWrap, uniqueIDPluginKey, unsetAllMarks, unsetMark, updateAttributes, wrapIn, wrappingInputRule, writeToClipboard };
10589
10900
  //# sourceMappingURL=index.js.map
10590
10901
  //# sourceMappingURL=index.js.map