@domternal/core 0.9.0 → 0.10.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 +3 -3
- package/dist/index.cjs +167 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -1
- package/dist/index.d.ts +22 -1
- package/dist/index.js +166 -24
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -21,14 +21,14 @@ See <u>[Packages & Bundle Size](https://domternal.dev/v1/packages)</u> for a ful
|
|
|
21
21
|
- **Vue components** - composable `Domternal` component, `useEditor`/`useEditorState` composables, toolbar, bubble menu, floating menu, emoji picker, notion color picker, custom node views (Vue 3.3+)
|
|
22
22
|
- **Vanilla wrapper** - framework-free class-based API for Astro, Svelte, Solid, plain HTML, and Web Components - editor, toolbar, bubble menu, floating menu, emoji picker, notion color picker
|
|
23
23
|
- **Notion-style block UX** - drag-to-reorder, block context menu, slash command, smart paste, keyboard reorder, floating Table of Contents
|
|
24
|
-
- **
|
|
25
|
-
- **
|
|
24
|
+
- **70+ extensions across 16 packages** - nodes, marks, and behavior extensions
|
|
25
|
+
- **125+ chainable commands** - `editor.chain().focus().toggleBold().run()`
|
|
26
26
|
- **Full table support** - cell merging, column resize, row/column controls, cell toolbar, all free and MIT licensed
|
|
27
27
|
- **Tree-shakeable** - import only what you use, your bundler strips the rest
|
|
28
28
|
- **~44 KB gzipped** (own code), <u>[see Packages](https://domternal.dev/v1/packages)</u> for full bundle breakdown with ProseMirror
|
|
29
29
|
- **TypeScript first** - 100% typed, zero `any`
|
|
30
30
|
- **15,000+ tests** - 4,000+ unit and 11,000+ E2E across 230+ Playwright specs and 4 demo apps
|
|
31
|
-
- **Light and dark theme** -
|
|
31
|
+
- **Light and dark theme** - 120+ CSS custom properties for full visual control
|
|
32
32
|
- **Inline styles export** - `getHTML({ styled: true })` produces inline CSS ready for email clients, CMS, and Google Docs
|
|
33
33
|
- **SSR helpers** - `generateHTML`, `generateJSON`, `generateText` for server-side rendering
|
|
34
34
|
|
package/dist/index.cjs
CHANGED
|
@@ -1018,6 +1018,27 @@ var deleteSelection = () => ({ tr, dispatch }) => {
|
|
|
1018
1018
|
dispatch(tr);
|
|
1019
1019
|
return true;
|
|
1020
1020
|
};
|
|
1021
|
+
var LIST_WRAPPER_TYPES = /* @__PURE__ */ new Set(["bulletList", "orderedList", "taskList"]);
|
|
1022
|
+
function isEmptyPlaceholderList(node) {
|
|
1023
|
+
if (!LIST_WRAPPER_TYPES.has(node.type.name) || node.childCount !== 1) return false;
|
|
1024
|
+
const item = node.child(0);
|
|
1025
|
+
return item.childCount === 1 && item.child(0).type.name === "paragraph" && item.child(0).content.size === 0;
|
|
1026
|
+
}
|
|
1027
|
+
function stripFitterArtifacts(node) {
|
|
1028
|
+
if (!node.isBlock || node.isLeaf) return node;
|
|
1029
|
+
const children = [];
|
|
1030
|
+
node.forEach((child) => children.push(stripFitterArtifacts(child)));
|
|
1031
|
+
const kept = [];
|
|
1032
|
+
children.forEach((cur, i) => {
|
|
1033
|
+
const next = children[i + 1];
|
|
1034
|
+
if (isEmptyPlaceholderList(cur) && next && LIST_WRAPPER_TYPES.has(next.type.name) && next.type !== cur.type) {
|
|
1035
|
+
return;
|
|
1036
|
+
}
|
|
1037
|
+
kept.push(cur);
|
|
1038
|
+
});
|
|
1039
|
+
const unchanged = kept.length === node.childCount && kept.every((c, i) => c === node.child(i));
|
|
1040
|
+
return unchanged ? node : node.copy(model.Fragment.fromArray(kept));
|
|
1041
|
+
}
|
|
1021
1042
|
function isJSONContent(content) {
|
|
1022
1043
|
return typeof content === "object" && content !== null && "type" in content && typeof content.type === "string";
|
|
1023
1044
|
}
|
|
@@ -1040,7 +1061,7 @@ function parseHTMLContent(html, schema, options) {
|
|
|
1040
1061
|
const element = document.createElement("div");
|
|
1041
1062
|
element.innerHTML = html;
|
|
1042
1063
|
const parser = model.DOMParser.fromSchema(schema);
|
|
1043
|
-
return parser.parse(element, options?.parseOptions);
|
|
1064
|
+
return stripFitterArtifacts(parser.parse(element, options?.parseOptions));
|
|
1044
1065
|
}
|
|
1045
1066
|
function createDocument(content, schema, options) {
|
|
1046
1067
|
if (content === null || content === void 0 || content === "") {
|
|
@@ -4113,6 +4134,21 @@ function copyThemeClass(view, target) {
|
|
|
4113
4134
|
});
|
|
4114
4135
|
}
|
|
4115
4136
|
|
|
4137
|
+
// src/utils/refocusEditorAfterCommand.ts
|
|
4138
|
+
function refocusEditorAfterCommand(view) {
|
|
4139
|
+
requestAnimationFrame(() => {
|
|
4140
|
+
const ae = document.activeElement;
|
|
4141
|
+
if (!ae) {
|
|
4142
|
+
view.focus();
|
|
4143
|
+
return;
|
|
4144
|
+
}
|
|
4145
|
+
if (ae.closest("[data-dm-editor-ui]") && !ae.closest(".dm-toolbar") && !ae.closest(".dm-bubble-menu") && !ae.closest(".dm-floating-menu") && !view.dom.contains(ae)) {
|
|
4146
|
+
return;
|
|
4147
|
+
}
|
|
4148
|
+
view.focus();
|
|
4149
|
+
});
|
|
4150
|
+
}
|
|
4151
|
+
|
|
4116
4152
|
// src/utils/defaultBubbleContexts.ts
|
|
4117
4153
|
var NOTION_MODE_CLASS = "dm-notion-mode";
|
|
4118
4154
|
var NOTION_TEXT_CONTEXT = Object.freeze([
|
|
@@ -4121,6 +4157,7 @@ var NOTION_TEXT_CONTEXT = Object.freeze([
|
|
|
4121
4157
|
"underline",
|
|
4122
4158
|
"strike",
|
|
4123
4159
|
"code",
|
|
4160
|
+
"mathInline",
|
|
4124
4161
|
"|",
|
|
4125
4162
|
"link",
|
|
4126
4163
|
"|",
|
|
@@ -4132,6 +4169,7 @@ var STANDARD_TEXT_CONTEXT = Object.freeze([
|
|
|
4132
4169
|
"underline",
|
|
4133
4170
|
"strike",
|
|
4134
4171
|
"code",
|
|
4172
|
+
"mathInline",
|
|
4135
4173
|
"|",
|
|
4136
4174
|
"link"
|
|
4137
4175
|
]);
|
|
@@ -4143,12 +4181,12 @@ function defaultBubbleContexts(editor) {
|
|
|
4143
4181
|
|
|
4144
4182
|
// src/utils/insertAsListItemChild.ts
|
|
4145
4183
|
var LIST_ITEM_TYPES3 = /* @__PURE__ */ new Set(["listItem", "taskItem"]);
|
|
4146
|
-
var
|
|
4184
|
+
var LIST_WRAPPER_TYPES2 = /* @__PURE__ */ new Set(["bulletList", "orderedList", "taskList"]);
|
|
4147
4185
|
function insertAsListItemChild(args) {
|
|
4148
4186
|
const { tr, wrapperPos, targetItemPos, blockNode, sourceRange, childIndex } = args;
|
|
4149
4187
|
if (wrapperPos < 0 || wrapperPos >= tr.doc.content.size) return { ok: false };
|
|
4150
4188
|
const wrapper = tr.doc.nodeAt(wrapperPos);
|
|
4151
|
-
if (!wrapper || !
|
|
4189
|
+
if (!wrapper || !LIST_WRAPPER_TYPES2.has(wrapper.type.name)) return { ok: false };
|
|
4152
4190
|
if (wrapper.childCount === 0) return { ok: false };
|
|
4153
4191
|
let targetItem;
|
|
4154
4192
|
let targetItemStart;
|
|
@@ -5368,6 +5406,9 @@ var defaultIcons = {
|
|
|
5368
5406
|
highlighterCircle: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M201.54,54.46A104,104,0,0,0,54.46,201.54,104,104,0,0,0,201.54,54.46ZM96,210V152h64v58a88.33,88.33,0,0,1-64,0Zm48-74H112V100.94l32-16Zm46.22,54.22A88.09,88.09,0,0,1,176,201.77V152a16,16,0,0,0-16-16V72a8,8,0,0,0-11.58-7.16l-48,24A8,8,0,0,0,96,96v40a16,16,0,0,0-16,16v49.77a88,88,0,1,1,110.22-11.55Z"/></svg>',
|
|
5369
5407
|
textSubscript: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M248,208a8,8,0,0,1-8,8H192a8,8,0,0,1-6.4-12.8l43.17-57.56a16,16,0,1,0-27.86-15,8,8,0,0,1-15.09-5.34,32.18,32.18,0,0,1,4.63-8.59,32,32,0,0,1,51.11,38.52L208,200h32A8,8,0,0,1,248,208ZM149.24,50a8,8,0,0,0-11.29.81L92,103.78l-45.95-53A8,8,0,0,0,34,61.24L81.41,116,34,170.76a8,8,0,0,0,12.1,10.48l46-53,45.95,53a8,8,0,1,0,12.1-10.48L102.59,116l47.46-54.76A8,8,0,0,0,149.24,50Z"/></svg>',
|
|
5370
5408
|
textSuperscript: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M248,144a8,8,0,0,1-8,8H192a8,8,0,0,1-6.4-12.8l43.17-57.55a16,16,0,1,0-27.86-15,8,8,0,0,1-15.09-5.33,32,32,0,1,1,55.74,29.92L208,136h32A8,8,0,0,1,248,144ZM149.24,74a8,8,0,0,0-11.29.8L92,127.79l-45.95-53A8,8,0,0,0,34,85.24L81.41,140,34,194.76a8,8,0,0,0,12.1,10.48l46-53,45.95,53a8,8,0,1,0,12.1-10.48L102.59,140l47.46-54.76A8,8,0,0,0,149.24,74Z"/></svg>',
|
|
5409
|
+
// --- Math ---
|
|
5410
|
+
sigma: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="none" stroke="currentColor" stroke-width="18" stroke-linecap="round" stroke-linejoin="round"><path d="M196 56H64l64 72-64 72h132"/></svg>',
|
|
5411
|
+
radical: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="none" stroke="currentColor" stroke-width="18" stroke-linecap="round" stroke-linejoin="round"><path d="M24 150 L66 200 L118 56 L236 56 M150 98 L204 156 M204 98 L150 156"/></svg>',
|
|
5371
5412
|
link: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M240,88.23a54.43,54.43,0,0,1-16,37L189.25,160a54.27,54.27,0,0,1-38.63,16h-.05A54.63,54.63,0,0,1,96,119.84a8,8,0,0,1,16,.45A38.62,38.62,0,0,0,150.58,160h0a38.39,38.39,0,0,0,27.31-11.31l34.75-34.75a38.63,38.63,0,0,0-54.63-54.63l-11,11A8,8,0,0,1,135.7,59l11-11A54.65,54.65,0,0,1,224,48,54.86,54.86,0,0,1,240,88.23ZM109,185.66l-11,11A38.41,38.41,0,0,1,70.6,208h0a38.63,38.63,0,0,1-27.29-65.94L78,107.31A38.63,38.63,0,0,1,144,135.71a8,8,0,0,0,16,.45A54.86,54.86,0,0,0,144,96a54.65,54.65,0,0,0-77.27,0L32,130.75A54.62,54.62,0,0,0,70.56,224h0a54.28,54.28,0,0,0,38.64-16l11-11A8,8,0,0,0,109,185.66Z"/></svg>',
|
|
5372
5413
|
// --- Format: Block ---
|
|
5373
5414
|
paragraph: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M208,40H96a64,64,0,0,0,0,128h40v40a8,8,0,0,0,16,0V56h24V208a8,8,0,0,0,16,0V56h16a8,8,0,0,0,0-16ZM136,152H96a48,48,0,0,1,0-96h40Z"/></svg>',
|
|
@@ -5929,6 +5970,50 @@ var CodeBlock = Node2.create({
|
|
|
5929
5970
|
];
|
|
5930
5971
|
}
|
|
5931
5972
|
});
|
|
5973
|
+
var LIST_ITEM_TYPES4 = /* @__PURE__ */ new Set(["listItem", "taskItem"]);
|
|
5974
|
+
function liftCrossTypeListItem(state$1, dispatch) {
|
|
5975
|
+
const { $from } = state$1.selection;
|
|
5976
|
+
if (!state$1.selection.empty) return false;
|
|
5977
|
+
let itemDepth = -1;
|
|
5978
|
+
for (let d = $from.depth; d > 0; d--) {
|
|
5979
|
+
if (LIST_ITEM_TYPES4.has($from.node(d).type.name)) {
|
|
5980
|
+
itemDepth = d;
|
|
5981
|
+
break;
|
|
5982
|
+
}
|
|
5983
|
+
}
|
|
5984
|
+
if (itemDepth < 4) return false;
|
|
5985
|
+
const item = $from.node(itemDepth);
|
|
5986
|
+
const wrapper = $from.node(itemDepth - 1);
|
|
5987
|
+
const parentItem = $from.node(itemDepth - 2);
|
|
5988
|
+
if (!LIST_ITEM_TYPES4.has(parentItem.type.name)) return false;
|
|
5989
|
+
if (parentItem.type === item.type) return false;
|
|
5990
|
+
const parentWrapper = $from.node(itemDepth - 3);
|
|
5991
|
+
const grandParent = $from.node(itemDepth - 4);
|
|
5992
|
+
const gpIndex = $from.index(itemDepth - 4);
|
|
5993
|
+
if (!grandParent.canReplaceWith(gpIndex + 1, gpIndex + 1, wrapper.type)) return false;
|
|
5994
|
+
if (!dispatch) return true;
|
|
5995
|
+
const onlyChild = wrapper.childCount === 1;
|
|
5996
|
+
const removeFrom = onlyChild ? $from.before(itemDepth - 1) : $from.before(itemDepth);
|
|
5997
|
+
const removeTo = onlyChild ? $from.after(itemDepth - 1) : $from.after(itemDepth);
|
|
5998
|
+
const parentIsLast = $from.index(itemDepth - 3) === parentWrapper.childCount - 1;
|
|
5999
|
+
const tr = state$1.tr;
|
|
6000
|
+
tr.delete(removeFrom, removeTo);
|
|
6001
|
+
const newList = wrapper.type.create(wrapper.attrs, item);
|
|
6002
|
+
if (parentIsLast) {
|
|
6003
|
+
const insertAt = tr.mapping.map($from.after(itemDepth - 3));
|
|
6004
|
+
tr.insert(insertAt, newList);
|
|
6005
|
+
tr.setSelection(state.Selection.near(tr.doc.resolve(insertAt + 2)));
|
|
6006
|
+
} else {
|
|
6007
|
+
const splitAt = tr.mapping.map($from.after(itemDepth - 2));
|
|
6008
|
+
tr.split(splitAt, 1);
|
|
6009
|
+
tr.insert(splitAt + 1, newList);
|
|
6010
|
+
tr.setSelection(state.Selection.near(tr.doc.resolve(splitAt + 2)));
|
|
6011
|
+
}
|
|
6012
|
+
dispatch(tr.scrollIntoView());
|
|
6013
|
+
return true;
|
|
6014
|
+
}
|
|
6015
|
+
|
|
6016
|
+
// src/extensions/ListKeymap.ts
|
|
5932
6017
|
var LIST_GROUP_TYPES = /* @__PURE__ */ new Set(["bulletList", "orderedList", "taskList"]);
|
|
5933
6018
|
function getListItemContext(editor, listItemName) {
|
|
5934
6019
|
const { state, view } = editor;
|
|
@@ -5970,6 +6055,7 @@ var ListKeymap = Extension.create({
|
|
|
5970
6055
|
if (!this.editor) return false;
|
|
5971
6056
|
const ctx = getListItemContext(this.editor, this.options.listItem);
|
|
5972
6057
|
if (!ctx) return false;
|
|
6058
|
+
if (liftCrossTypeListItem(ctx.state, ctx.view.dispatch)) return true;
|
|
5973
6059
|
return schemaList.liftListItem(ctx.listItemType)(ctx.state, ctx.view.dispatch);
|
|
5974
6060
|
},
|
|
5975
6061
|
// Backspace at start of list item to lift
|
|
@@ -6023,6 +6109,7 @@ var ListKeymap = Extension.create({
|
|
|
6023
6109
|
if (firstChild?.isTextblock) {
|
|
6024
6110
|
const posInListItem = $from.pos - $from.start(listItemDepth);
|
|
6025
6111
|
if (posInListItem <= 1) {
|
|
6112
|
+
if (liftCrossTypeListItem(state$1, view.dispatch)) return true;
|
|
6026
6113
|
return schemaList.liftListItem(listItemType)(state$1, view.dispatch);
|
|
6027
6114
|
}
|
|
6028
6115
|
}
|
|
@@ -6069,7 +6156,22 @@ var ListItem = Node2.create({
|
|
|
6069
6156
|
if (commands.splitBlock(state$1, view.dispatch)) return true;
|
|
6070
6157
|
}
|
|
6071
6158
|
}
|
|
6072
|
-
|
|
6159
|
+
const item = $from.node(-1);
|
|
6160
|
+
const hasChildren = item.childCount > 1;
|
|
6161
|
+
const atEnd = $from.parentOffset === $from.parent.content.size;
|
|
6162
|
+
const labelEmpty = $from.parent.content.size === 0;
|
|
6163
|
+
if (!ctx?.isInChildrenZone && hasChildren && atEnd && !labelEmpty) {
|
|
6164
|
+
const newItem = this.nodeType.createAndFill();
|
|
6165
|
+
if (newItem) {
|
|
6166
|
+
const insertAt = $from.after($from.depth - 1);
|
|
6167
|
+
const tr = state$1.tr.insert(insertAt, newItem);
|
|
6168
|
+
tr.setSelection(state.Selection.near(tr.doc.resolve(insertAt + 2)));
|
|
6169
|
+
view.dispatch(tr.scrollIntoView());
|
|
6170
|
+
return true;
|
|
6171
|
+
}
|
|
6172
|
+
}
|
|
6173
|
+
const skipSplit = !ctx?.isInChildrenZone && labelEmpty && hasChildren;
|
|
6174
|
+
if (!skipSplit && schemaList.splitListItem(this.nodeType)(state$1, view.dispatch)) return true;
|
|
6073
6175
|
const listDepth = $from.depth - 2;
|
|
6074
6176
|
const taskItemType = state$1.schema.nodes["taskItem"];
|
|
6075
6177
|
if ($from.parent.content.size === 0 && listDepth > 0 && taskItemType && $from.node(listDepth - 1).type === taskItemType) {
|
|
@@ -6078,9 +6180,9 @@ var ListItem = Node2.create({
|
|
|
6078
6180
|
tr.delete($from.before(delDepth), $from.after(delDepth));
|
|
6079
6181
|
const taskItemDepth = listDepth - 1;
|
|
6080
6182
|
const end = tr.mapping.map($from.after(taskItemDepth));
|
|
6081
|
-
const
|
|
6082
|
-
if (
|
|
6083
|
-
tr.insert(end,
|
|
6183
|
+
const item2 = taskItemType.createAndFill();
|
|
6184
|
+
if (item2) {
|
|
6185
|
+
tr.insert(end, item2);
|
|
6084
6186
|
tr.setSelection(state.Selection.near(tr.doc.resolve(end + 2)));
|
|
6085
6187
|
view.dispatch(tr.scrollIntoView());
|
|
6086
6188
|
return true;
|
|
@@ -6209,16 +6311,20 @@ var OrderedList = Node2.create({
|
|
|
6209
6311
|
return {
|
|
6210
6312
|
start: {
|
|
6211
6313
|
default: 1,
|
|
6314
|
+
// Clamp to a finite integer >= 1. Without this, a malformed
|
|
6315
|
+
// `start="abc"` parses to NaN; `JSON.stringify(NaN)` is `null`, so
|
|
6316
|
+
// getJSON() serializes `start: null` and a save/load cycle
|
|
6317
|
+
// permanently dirties the document (reloads as `<ol start="null">`).
|
|
6212
6318
|
parseHTML: (element) => {
|
|
6213
|
-
const
|
|
6214
|
-
return
|
|
6319
|
+
const n = parseInt(element.getAttribute("start") ?? "", 10);
|
|
6320
|
+
return Number.isFinite(n) && n >= 1 ? Math.floor(n) : 1;
|
|
6215
6321
|
},
|
|
6216
6322
|
renderHTML: (attributes) => {
|
|
6217
6323
|
const start = attributes["start"];
|
|
6218
|
-
if (start
|
|
6324
|
+
if (!Number.isFinite(start) || start <= 1) {
|
|
6219
6325
|
return {};
|
|
6220
6326
|
}
|
|
6221
|
-
return { start: String(start) };
|
|
6327
|
+
return { start: String(Math.floor(start)) };
|
|
6222
6328
|
}
|
|
6223
6329
|
}
|
|
6224
6330
|
};
|
|
@@ -6297,8 +6403,8 @@ var OrderedList = Node2.create({
|
|
|
6297
6403
|
guard: notInsideList,
|
|
6298
6404
|
joinForward: true,
|
|
6299
6405
|
getAttributes: (match) => {
|
|
6300
|
-
const
|
|
6301
|
-
return { start:
|
|
6406
|
+
const n = parseInt(match[1] ?? "", 10);
|
|
6407
|
+
return { start: Number.isFinite(n) && n >= 1 ? Math.floor(n) : 1 };
|
|
6302
6408
|
}
|
|
6303
6409
|
})
|
|
6304
6410
|
];
|
|
@@ -6570,7 +6676,10 @@ var TaskItem = Node2.create({
|
|
|
6570
6676
|
keepOnSplit: false,
|
|
6571
6677
|
parseHTML: (element) => {
|
|
6572
6678
|
const dataChecked = element.getAttribute("data-checked");
|
|
6573
|
-
|
|
6679
|
+
if (dataChecked !== null) {
|
|
6680
|
+
return dataChecked.toLowerCase() === "true" || dataChecked === "";
|
|
6681
|
+
}
|
|
6682
|
+
return element.querySelector('input[type="checkbox"]')?.hasAttribute("checked") ?? false;
|
|
6574
6683
|
},
|
|
6575
6684
|
renderHTML: (attributes) => ({
|
|
6576
6685
|
"data-checked": attributes["checked"] ? "true" : "false"
|
|
@@ -6583,6 +6692,14 @@ var TaskItem = Node2.create({
|
|
|
6583
6692
|
{
|
|
6584
6693
|
tag: `li[data-type="${this.name}"]`,
|
|
6585
6694
|
priority: 51
|
|
6695
|
+
},
|
|
6696
|
+
// GFM / markdown task lists: `<li class="task-list-item">` carries no
|
|
6697
|
+
// data-type. Priority 51 keeps it ahead of the generic `li` (listItem,
|
|
6698
|
+
// 50); class-scoped so it never swallows ordinary bullet items. The
|
|
6699
|
+
// `checked` attribute is derived from the descendant `<input>` above.
|
|
6700
|
+
{
|
|
6701
|
+
tag: "li.task-list-item",
|
|
6702
|
+
priority: 51
|
|
6586
6703
|
}
|
|
6587
6704
|
];
|
|
6588
6705
|
},
|
|
@@ -6668,7 +6785,22 @@ var TaskItem = Node2.create({
|
|
|
6668
6785
|
return true;
|
|
6669
6786
|
}
|
|
6670
6787
|
}
|
|
6671
|
-
|
|
6788
|
+
const item = $from.node(-1);
|
|
6789
|
+
const hasChildren = item.childCount > 1;
|
|
6790
|
+
const labelEmpty = $from.parent.content.size === 0;
|
|
6791
|
+
const atEnd = $from.parentOffset === $from.parent.content.size;
|
|
6792
|
+
if (!ctx?.isInChildrenZone && hasChildren && atEnd && !labelEmpty) {
|
|
6793
|
+
const newItem = this.nodeType.createAndFill({ checked: false });
|
|
6794
|
+
if (newItem) {
|
|
6795
|
+
const insertAt = $from.after($from.depth - 1);
|
|
6796
|
+
const tr = state$1.tr.insert(insertAt, newItem);
|
|
6797
|
+
tr.setSelection(state.Selection.near(tr.doc.resolve(insertAt + 2)));
|
|
6798
|
+
view.dispatch(tr.scrollIntoView());
|
|
6799
|
+
return true;
|
|
6800
|
+
}
|
|
6801
|
+
}
|
|
6802
|
+
const skipSplit = !ctx?.isInChildrenZone && labelEmpty && hasChildren;
|
|
6803
|
+
if (!skipSplit && schemaList.splitListItem(this.nodeType, { checked: false })(state$1, view.dispatch)) return true;
|
|
6672
6804
|
if ($from.parent.content.size === 0) {
|
|
6673
6805
|
const listItemType = state$1.schema.nodes["listItem"];
|
|
6674
6806
|
if (listItemType) {
|
|
@@ -6715,9 +6847,11 @@ var TaskItem = Node2.create({
|
|
|
6715
6847
|
},
|
|
6716
6848
|
"Shift-Tab": () => {
|
|
6717
6849
|
if (!this.editor || !this.nodeType) return false;
|
|
6718
|
-
const {
|
|
6850
|
+
const { state, view } = this.editor;
|
|
6851
|
+
const { $from } = state.selection;
|
|
6719
6852
|
if ($from.depth < 1 || $from.node(-1).type !== this.nodeType) return false;
|
|
6720
|
-
|
|
6853
|
+
if (liftCrossTypeListItem(state, view.dispatch)) return true;
|
|
6854
|
+
return schemaList.liftListItem(this.nodeType)(state, view.dispatch);
|
|
6721
6855
|
},
|
|
6722
6856
|
Backspace: () => {
|
|
6723
6857
|
if (!this.editor || !this.nodeType) return false;
|
|
@@ -6739,6 +6873,7 @@ var TaskItem = Node2.create({
|
|
|
6739
6873
|
}
|
|
6740
6874
|
if (taskItemDepth === -1) return false;
|
|
6741
6875
|
if ($from.index(taskItemDepth) !== 0) return false;
|
|
6876
|
+
if (liftCrossTypeListItem(state, view.dispatch)) return true;
|
|
6742
6877
|
return schemaList.liftListItem(this.nodeType)(state, view.dispatch);
|
|
6743
6878
|
},
|
|
6744
6879
|
"Mod-Enter": () => {
|
|
@@ -6765,6 +6900,13 @@ var TaskList = Node2.create({
|
|
|
6765
6900
|
tag: `ul[data-type="${this.name}"]`,
|
|
6766
6901
|
priority: 51
|
|
6767
6902
|
// Higher priority than regular bulletList
|
|
6903
|
+
},
|
|
6904
|
+
// GFM / markdown task lists: `<ul class="contains-task-list">`. Priority
|
|
6905
|
+
// 51 keeps it ahead of the generic `ul` (bulletList, 50); class-scoped so
|
|
6906
|
+
// it only matches real GFM task-list containers, not ordinary bullets.
|
|
6907
|
+
{
|
|
6908
|
+
tag: "ul.contains-task-list",
|
|
6909
|
+
priority: 51
|
|
6768
6910
|
}
|
|
6769
6911
|
];
|
|
6770
6912
|
},
|
|
@@ -8025,12 +8167,12 @@ var Placeholder = Extension.create({
|
|
|
8025
8167
|
];
|
|
8026
8168
|
}
|
|
8027
8169
|
});
|
|
8028
|
-
var
|
|
8029
|
-
var
|
|
8170
|
+
var LIST_ITEM_TYPES5 = /* @__PURE__ */ new Set(["listItem", "taskItem"]);
|
|
8171
|
+
var LIST_WRAPPER_TYPES3 = /* @__PURE__ */ new Set(["bulletList", "orderedList", "taskList"]);
|
|
8030
8172
|
function isCursorInsideListItem(state) {
|
|
8031
8173
|
const { $from } = state.selection;
|
|
8032
8174
|
for (let d = $from.depth; d > 0; d--) {
|
|
8033
|
-
if (
|
|
8175
|
+
if (LIST_ITEM_TYPES5.has($from.node(d).type.name)) return true;
|
|
8034
8176
|
}
|
|
8035
8177
|
return false;
|
|
8036
8178
|
}
|
|
@@ -8061,7 +8203,7 @@ function indentBlockAsListChild(state$1, dispatch) {
|
|
|
8061
8203
|
}
|
|
8062
8204
|
if (blockIndex === 0) return false;
|
|
8063
8205
|
const prevSibling = state$1.doc.child(blockIndex - 1);
|
|
8064
|
-
if (!
|
|
8206
|
+
if (!LIST_WRAPPER_TYPES3.has(prevSibling.type.name)) return false;
|
|
8065
8207
|
let wrapperPos = 0;
|
|
8066
8208
|
for (let i = 0; i < blockIndex - 1; i++) {
|
|
8067
8209
|
wrapperPos += state$1.doc.child(i).nodeSize;
|
|
@@ -8085,7 +8227,7 @@ function outdentBlockFromListItem(state$1, dispatch) {
|
|
|
8085
8227
|
const { $from } = selection;
|
|
8086
8228
|
let listItemDepth = -1;
|
|
8087
8229
|
for (let d = $from.depth; d > 0; d--) {
|
|
8088
|
-
if (
|
|
8230
|
+
if (LIST_ITEM_TYPES5.has($from.node(d).type.name)) {
|
|
8089
8231
|
listItemDepth = d;
|
|
8090
8232
|
break;
|
|
8091
8233
|
}
|
|
@@ -8865,7 +9007,7 @@ var BlockColor = Extension.create({
|
|
|
8865
9007
|
};
|
|
8866
9008
|
}
|
|
8867
9009
|
});
|
|
8868
|
-
var
|
|
9010
|
+
var Selection5 = Extension.create({
|
|
8869
9011
|
name: "selection",
|
|
8870
9012
|
addStorage() {
|
|
8871
9013
|
return {
|
|
@@ -10419,7 +10561,7 @@ exports.NotionColorPicker = NotionColorPicker;
|
|
|
10419
10561
|
exports.OrderedList = OrderedList;
|
|
10420
10562
|
exports.Paragraph = Paragraph;
|
|
10421
10563
|
exports.Placeholder = Placeholder;
|
|
10422
|
-
exports.Selection =
|
|
10564
|
+
exports.Selection = Selection5;
|
|
10423
10565
|
exports.SelectionDecoration = SelectionDecoration;
|
|
10424
10566
|
exports.StarterKit = StarterKit;
|
|
10425
10567
|
exports.Strike = Strike;
|
|
@@ -10500,6 +10642,7 @@ exports.outdentBlockFromListItem = outdentBlockFromListItem;
|
|
|
10500
10642
|
exports.placeholderPluginKey = placeholderPluginKey;
|
|
10501
10643
|
exports.positionFloating = positionFloating;
|
|
10502
10644
|
exports.positionFloatingOnce = positionFloatingOnce;
|
|
10645
|
+
exports.refocusEditorAfterCommand = refocusEditorAfterCommand;
|
|
10503
10646
|
exports.resetAttributes = resetAttributes;
|
|
10504
10647
|
exports.selectAll = selectAll;
|
|
10505
10648
|
exports.selectNodeBackward = selectNodeBackward;
|