@domternal/core 0.14.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 +276 -48
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +156 -8
- package/dist/index.d.ts +156 -8
- package/dist/index.js +276 -49
- package/dist/index.js.map +1 -1
- package/package.json +12 -14
package/dist/index.js
CHANGED
|
@@ -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);
|
|
@@ -4237,7 +4291,6 @@ function refocusEditorAfterCommand(view) {
|
|
|
4237
4291
|
}
|
|
4238
4292
|
|
|
4239
4293
|
// src/utils/defaultBubbleContexts.ts
|
|
4240
|
-
var NOTION_MODE_CLASS = "dm-notion-mode";
|
|
4241
4294
|
var NOTION_TEXT_CONTEXT = Object.freeze([
|
|
4242
4295
|
// `ai` leads (Notion's "Ask AI"); skipped with its leading separator when
|
|
4243
4296
|
// the pro extension is absent, exactly like `mathInline`.
|
|
@@ -4265,8 +4318,7 @@ var STANDARD_TEXT_CONTEXT = Object.freeze([
|
|
|
4265
4318
|
"link"
|
|
4266
4319
|
]);
|
|
4267
4320
|
function defaultBubbleContexts(editor) {
|
|
4268
|
-
const
|
|
4269
|
-
const text = inNotionMode ? NOTION_TEXT_CONTEXT : STANDARD_TEXT_CONTEXT;
|
|
4321
|
+
const text = editor.preset === "notion" ? NOTION_TEXT_CONTEXT : STANDARD_TEXT_CONTEXT;
|
|
4270
4322
|
return { text: [...text] };
|
|
4271
4323
|
}
|
|
4272
4324
|
|
|
@@ -5025,7 +5077,8 @@ function groupFloatingMenuItems(items) {
|
|
|
5025
5077
|
if (!list) {
|
|
5026
5078
|
list = [];
|
|
5027
5079
|
map.set(name, list);
|
|
5028
|
-
order.
|
|
5080
|
+
if (name === "") order.unshift(name);
|
|
5081
|
+
else order.push(name);
|
|
5029
5082
|
}
|
|
5030
5083
|
list.push(item);
|
|
5031
5084
|
}
|
|
@@ -5559,7 +5612,8 @@ var defaultIcons = {
|
|
|
5559
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>',
|
|
5560
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>',
|
|
5561
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>',
|
|
5562
|
-
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>'
|
|
5563
5617
|
};
|
|
5564
5618
|
|
|
5565
5619
|
// src/nodes/Document.ts
|
|
@@ -7091,6 +7145,7 @@ var TaskList = Node2.create({
|
|
|
7091
7145
|
// src/marks/Bold.ts
|
|
7092
7146
|
var Bold = Mark.create({
|
|
7093
7147
|
name: "bold",
|
|
7148
|
+
group: "formatting",
|
|
7094
7149
|
addOptions() {
|
|
7095
7150
|
return {
|
|
7096
7151
|
HTMLAttributes: {}
|
|
@@ -7168,6 +7223,7 @@ var Bold = Mark.create({
|
|
|
7168
7223
|
// src/marks/Italic.ts
|
|
7169
7224
|
var Italic = Mark.create({
|
|
7170
7225
|
name: "italic",
|
|
7226
|
+
group: "formatting",
|
|
7171
7227
|
addOptions() {
|
|
7172
7228
|
return {
|
|
7173
7229
|
HTMLAttributes: {}
|
|
@@ -7247,6 +7303,7 @@ var Italic = Mark.create({
|
|
|
7247
7303
|
// src/marks/Underline.ts
|
|
7248
7304
|
var Underline = Mark.create({
|
|
7249
7305
|
name: "underline",
|
|
7306
|
+
group: "formatting",
|
|
7250
7307
|
addOptions() {
|
|
7251
7308
|
return {
|
|
7252
7309
|
HTMLAttributes: {}
|
|
@@ -7299,6 +7356,7 @@ var Underline = Mark.create({
|
|
|
7299
7356
|
// src/marks/Strike.ts
|
|
7300
7357
|
var Strike = Mark.create({
|
|
7301
7358
|
name: "strike",
|
|
7359
|
+
group: "formatting",
|
|
7302
7360
|
addOptions() {
|
|
7303
7361
|
return {
|
|
7304
7362
|
HTMLAttributes: {}
|
|
@@ -7370,9 +7428,14 @@ var Code = Mark.create({
|
|
|
7370
7428
|
HTMLAttributes: {}
|
|
7371
7429
|
};
|
|
7372
7430
|
},
|
|
7373
|
-
// Code
|
|
7374
|
-
//
|
|
7375
|
-
|
|
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",
|
|
7376
7439
|
// Code should not span across multiple nodes
|
|
7377
7440
|
spanning: false,
|
|
7378
7441
|
parseHTML() {
|
|
@@ -7860,6 +7923,7 @@ var Link = Mark.create({
|
|
|
7860
7923
|
// src/marks/Subscript.ts
|
|
7861
7924
|
var Subscript = Mark.create({
|
|
7862
7925
|
name: "subscript",
|
|
7926
|
+
group: "formatting",
|
|
7863
7927
|
// Mutual exclusion handled in toggle commands (not schema)
|
|
7864
7928
|
// so can() dry-run works correctly for toolbar disabled state
|
|
7865
7929
|
excludes: "",
|
|
@@ -7921,6 +7985,7 @@ var Subscript = Mark.create({
|
|
|
7921
7985
|
// src/marks/Superscript.ts
|
|
7922
7986
|
var Superscript = Mark.create({
|
|
7923
7987
|
name: "superscript",
|
|
7988
|
+
group: "formatting",
|
|
7924
7989
|
// Mutual exclusion handled in toggle commands (not schema)
|
|
7925
7990
|
// so can() dry-run works correctly for toolbar disabled state
|
|
7926
7991
|
excludes: "",
|
|
@@ -7982,6 +8047,7 @@ var Superscript = Mark.create({
|
|
|
7982
8047
|
// src/marks/TextStyle.ts
|
|
7983
8048
|
var TextStyle = Mark.create({
|
|
7984
8049
|
name: "textStyle",
|
|
8050
|
+
group: "formatting",
|
|
7985
8051
|
// Lower priority so it renders after other marks
|
|
7986
8052
|
priority: 101,
|
|
7987
8053
|
addOptions() {
|
|
@@ -8038,7 +8104,7 @@ var TextStyle = Mark.create({
|
|
|
8038
8104
|
let hasEmptyTextStyle = false;
|
|
8039
8105
|
tr.doc.nodesBetween(from, to, (node) => {
|
|
8040
8106
|
const textStyleMark = node.marks.find(
|
|
8041
|
-
(
|
|
8107
|
+
(mark2) => mark2.type.name === this.name
|
|
8042
8108
|
);
|
|
8043
8109
|
if (textStyleMark) {
|
|
8044
8110
|
const hasNonNullAttr = Object.values(textStyleMark.attrs).some(
|
|
@@ -8052,9 +8118,9 @@ var TextStyle = Mark.create({
|
|
|
8052
8118
|
if (!hasEmptyTextStyle) return false;
|
|
8053
8119
|
if (dispatch) {
|
|
8054
8120
|
tr.doc.nodesBetween(from, to, (node, pos) => {
|
|
8055
|
-
const
|
|
8056
|
-
if (
|
|
8057
|
-
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(
|
|
8058
8124
|
(v) => v !== null && v !== void 0
|
|
8059
8125
|
);
|
|
8060
8126
|
if (!hasActiveAttr) {
|
|
@@ -8559,11 +8625,7 @@ var Typography = Extension.create({
|
|
|
8559
8625
|
rules.push(
|
|
8560
8626
|
new InputRule(/"([^"]+)"$/, (state, match, start, end) => {
|
|
8561
8627
|
const text = match[1] ?? "";
|
|
8562
|
-
return state.tr.
|
|
8563
|
-
start,
|
|
8564
|
-
end,
|
|
8565
|
-
state.schema.text(openDoubleQuote + text + closeDoubleQuote)
|
|
8566
|
-
);
|
|
8628
|
+
return state.tr.insertText(openDoubleQuote + text + closeDoubleQuote, start, end);
|
|
8567
8629
|
})
|
|
8568
8630
|
);
|
|
8569
8631
|
rules.push(
|
|
@@ -8571,12 +8633,10 @@ var Typography = Extension.create({
|
|
|
8571
8633
|
const text = match[1] ?? "";
|
|
8572
8634
|
const prefix = match[0].charAt(0);
|
|
8573
8635
|
const hasPrefix = prefix !== "'";
|
|
8574
|
-
return state.tr.
|
|
8636
|
+
return state.tr.insertText(
|
|
8637
|
+
hasPrefix ? prefix + openSingleQuote + text + closeSingleQuote : openSingleQuote + text + closeSingleQuote,
|
|
8575
8638
|
start,
|
|
8576
|
-
end
|
|
8577
|
-
state.schema.text(
|
|
8578
|
-
hasPrefix ? prefix + openSingleQuote + text + closeSingleQuote : openSingleQuote + text + closeSingleQuote
|
|
8579
|
-
)
|
|
8639
|
+
end
|
|
8580
8640
|
);
|
|
8581
8641
|
})
|
|
8582
8642
|
);
|
|
@@ -8841,6 +8901,9 @@ function generateUUID() {
|
|
|
8841
8901
|
});
|
|
8842
8902
|
}
|
|
8843
8903
|
var uniqueIDPluginKey = new PluginKey("uniqueID");
|
|
8904
|
+
function isWithin(from, to, ranges) {
|
|
8905
|
+
return ranges.some((range) => from >= range.from && to <= range.to);
|
|
8906
|
+
}
|
|
8844
8907
|
var UniqueID = Extension.create({
|
|
8845
8908
|
name: "uniqueID",
|
|
8846
8909
|
addOptions() {
|
|
@@ -8890,12 +8953,27 @@ var UniqueID = Extension.create({
|
|
|
8890
8953
|
addProseMirrorPlugins() {
|
|
8891
8954
|
const { types, attributeName, generateID, filterDuplicates } = this.options;
|
|
8892
8955
|
const editor = this.editor;
|
|
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
|
+
};
|
|
8893
8968
|
const transformPastedSlice = (slice, view) => {
|
|
8894
8969
|
if (view?.dragging?.move === true) return slice;
|
|
8895
8970
|
const existingIDs = /* @__PURE__ */ new Set();
|
|
8896
|
-
|
|
8971
|
+
const replaced = replacedRanges(view);
|
|
8972
|
+
editor?.state.doc.descendants((node, pos) => {
|
|
8973
|
+
if (isWithin(pos, pos + node.nodeSize, replaced)) return false;
|
|
8897
8974
|
const id = node.attrs[attributeName];
|
|
8898
8975
|
if (id) existingIDs.add(id);
|
|
8976
|
+
return true;
|
|
8899
8977
|
});
|
|
8900
8978
|
const transformNode = (node) => {
|
|
8901
8979
|
if (!types.includes(node.type.name)) {
|
|
@@ -9745,13 +9823,13 @@ var Highlight = Extension.create({
|
|
|
9745
9823
|
let hasHighlight = false;
|
|
9746
9824
|
if (empty) {
|
|
9747
9825
|
const marks = state.storedMarks ?? state.doc.resolve(from).marks();
|
|
9748
|
-
const
|
|
9749
|
-
hasHighlight = !!
|
|
9826
|
+
const mark2 = markType.isInSet(marks);
|
|
9827
|
+
hasHighlight = !!mark2?.attrs["backgroundColor"] || !!mark2?.attrs["backgroundColorToken"];
|
|
9750
9828
|
} else {
|
|
9751
9829
|
state.doc.nodesBetween(from, to, (node) => {
|
|
9752
9830
|
if (hasHighlight) return false;
|
|
9753
|
-
const
|
|
9754
|
-
if (
|
|
9831
|
+
const mark2 = markType.isInSet(node.marks);
|
|
9832
|
+
if (mark2?.attrs["backgroundColor"] || mark2?.attrs["backgroundColorToken"]) {
|
|
9755
9833
|
hasHighlight = true;
|
|
9756
9834
|
return false;
|
|
9757
9835
|
}
|
|
@@ -9798,7 +9876,8 @@ var Highlight = Extension.create({
|
|
|
9798
9876
|
const content = match[1];
|
|
9799
9877
|
if (!content) return null;
|
|
9800
9878
|
const { tr } = state;
|
|
9801
|
-
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));
|
|
9802
9881
|
tr.addMark(
|
|
9803
9882
|
start,
|
|
9804
9883
|
start + content.length,
|
|
@@ -10094,6 +10173,153 @@ var ClearFormatting = Extension.create({
|
|
|
10094
10173
|
];
|
|
10095
10174
|
}
|
|
10096
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
|
+
}
|
|
10097
10323
|
var linkPopoverPluginKey = new PluginKey("linkPopover");
|
|
10098
10324
|
function linkPopoverPlugin({ editor, markType, protocols }) {
|
|
10099
10325
|
const el = document.createElement("div");
|
|
@@ -10431,9 +10657,10 @@ function createBubbleMenuPlugin(options) {
|
|
|
10431
10657
|
const onDocumentMousedown = (e) => {
|
|
10432
10658
|
const target = e.target;
|
|
10433
10659
|
if (!target) return;
|
|
10660
|
+
if (!target.isConnected) return;
|
|
10434
10661
|
if (element.contains(target)) return;
|
|
10435
10662
|
if (editor.view.dom.contains(target)) return;
|
|
10436
|
-
if (target instanceof
|
|
10663
|
+
if (target instanceof Element && target.closest("[data-dm-editor-ui]")) return;
|
|
10437
10664
|
hideMenu();
|
|
10438
10665
|
suppressed = true;
|
|
10439
10666
|
};
|
|
@@ -10667,8 +10894,8 @@ var StarterKit = Extension.create({
|
|
|
10667
10894
|
});
|
|
10668
10895
|
|
|
10669
10896
|
// src/index.ts
|
|
10670
|
-
var VERSION = "0.
|
|
10897
|
+
var VERSION = "0.15.0";
|
|
10671
10898
|
|
|
10672
|
-
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 };
|
|
10673
10900
|
//# sourceMappingURL=index.js.map
|
|
10674
10901
|
//# sourceMappingURL=index.js.map
|