@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/README.md +41 -0
- package/dist/index.cjs +398 -86
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +177 -9
- package/dist/index.d.ts +177 -9
- package/dist/index.js +399 -88
- package/dist/index.js.map +1 -1
- package/package.json +12 -14
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 {
|
|
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.
|
|
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
|
-
|
|
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 = (
|
|
1851
|
-
const htmlAttrs = attrSpecs ? buildHTMLAttributes(
|
|
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
|
|
1946
|
-
tr.addStoredMark(
|
|
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
|
|
2574
|
-
if (
|
|
2579
|
+
const mark2 = markType.isInSet(node.marks);
|
|
2580
|
+
if (mark2) {
|
|
2575
2581
|
markChanges.push({
|
|
2576
2582
|
pos,
|
|
2577
2583
|
nodeSize: node.nodeSize,
|
|
2578
|
-
attrs: { ...
|
|
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
|
|
2625
|
-
if (
|
|
2630
|
+
const mark2 = markType.isInSet(node.marks);
|
|
2631
|
+
if (mark2) {
|
|
2626
2632
|
markChanges.push({
|
|
2627
2633
|
pos,
|
|
2628
2634
|
nodeSize: node.nodeSize,
|
|
2629
|
-
attrs: { ...
|
|
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((
|
|
3690
|
+
const hasMark = storedMarks.some((mark2) => mark2.type === markType);
|
|
3642
3691
|
if (!hasMark) return false;
|
|
3643
3692
|
if (attrs) {
|
|
3644
|
-
const
|
|
3645
|
-
return
|
|
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
|
|
3721
|
-
return
|
|
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
|
-
|
|
4069
|
-
|
|
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
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
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.
|
|
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(
|
|
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
|
|
7339
|
-
//
|
|
7340
|
-
|
|
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
|
-
(
|
|
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
|
|
8021
|
-
if (
|
|
8022
|
-
const hasActiveAttr = Object.values(
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
|
9669
|
-
hasHighlight = !!
|
|
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
|
|
9674
|
-
if (
|
|
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.
|
|
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((
|
|
10066
|
+
const items = sizes.map((size2, i) => ({
|
|
9908
10067
|
type: "button",
|
|
9909
|
-
name: `fontSize-${
|
|
10068
|
+
name: `fontSize-${size2}`,
|
|
9910
10069
|
command: "setFontSize",
|
|
9911
|
-
commandArgs: [
|
|
9912
|
-
isActive: { name: "textStyle", attributes: { fontSize:
|
|
10070
|
+
commandArgs: [size2],
|
|
10071
|
+
isActive: { name: "textStyle", attributes: { fontSize: size2 } },
|
|
9913
10072
|
icon: "textSize",
|
|
9914
|
-
label:
|
|
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
|
|
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.
|
|
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
|