@domternal/core 0.9.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +146 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +146 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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 === "") {
|
|
@@ -4143,12 +4164,12 @@ function defaultBubbleContexts(editor) {
|
|
|
4143
4164
|
|
|
4144
4165
|
// src/utils/insertAsListItemChild.ts
|
|
4145
4166
|
var LIST_ITEM_TYPES3 = /* @__PURE__ */ new Set(["listItem", "taskItem"]);
|
|
4146
|
-
var
|
|
4167
|
+
var LIST_WRAPPER_TYPES2 = /* @__PURE__ */ new Set(["bulletList", "orderedList", "taskList"]);
|
|
4147
4168
|
function insertAsListItemChild(args) {
|
|
4148
4169
|
const { tr, wrapperPos, targetItemPos, blockNode, sourceRange, childIndex } = args;
|
|
4149
4170
|
if (wrapperPos < 0 || wrapperPos >= tr.doc.content.size) return { ok: false };
|
|
4150
4171
|
const wrapper = tr.doc.nodeAt(wrapperPos);
|
|
4151
|
-
if (!wrapper || !
|
|
4172
|
+
if (!wrapper || !LIST_WRAPPER_TYPES2.has(wrapper.type.name)) return { ok: false };
|
|
4152
4173
|
if (wrapper.childCount === 0) return { ok: false };
|
|
4153
4174
|
let targetItem;
|
|
4154
4175
|
let targetItemStart;
|
|
@@ -5929,6 +5950,50 @@ var CodeBlock = Node2.create({
|
|
|
5929
5950
|
];
|
|
5930
5951
|
}
|
|
5931
5952
|
});
|
|
5953
|
+
var LIST_ITEM_TYPES4 = /* @__PURE__ */ new Set(["listItem", "taskItem"]);
|
|
5954
|
+
function liftCrossTypeListItem(state$1, dispatch) {
|
|
5955
|
+
const { $from } = state$1.selection;
|
|
5956
|
+
if (!state$1.selection.empty) return false;
|
|
5957
|
+
let itemDepth = -1;
|
|
5958
|
+
for (let d = $from.depth; d > 0; d--) {
|
|
5959
|
+
if (LIST_ITEM_TYPES4.has($from.node(d).type.name)) {
|
|
5960
|
+
itemDepth = d;
|
|
5961
|
+
break;
|
|
5962
|
+
}
|
|
5963
|
+
}
|
|
5964
|
+
if (itemDepth < 4) return false;
|
|
5965
|
+
const item = $from.node(itemDepth);
|
|
5966
|
+
const wrapper = $from.node(itemDepth - 1);
|
|
5967
|
+
const parentItem = $from.node(itemDepth - 2);
|
|
5968
|
+
if (!LIST_ITEM_TYPES4.has(parentItem.type.name)) return false;
|
|
5969
|
+
if (parentItem.type === item.type) return false;
|
|
5970
|
+
const parentWrapper = $from.node(itemDepth - 3);
|
|
5971
|
+
const grandParent = $from.node(itemDepth - 4);
|
|
5972
|
+
const gpIndex = $from.index(itemDepth - 4);
|
|
5973
|
+
if (!grandParent.canReplaceWith(gpIndex + 1, gpIndex + 1, wrapper.type)) return false;
|
|
5974
|
+
if (!dispatch) return true;
|
|
5975
|
+
const onlyChild = wrapper.childCount === 1;
|
|
5976
|
+
const removeFrom = onlyChild ? $from.before(itemDepth - 1) : $from.before(itemDepth);
|
|
5977
|
+
const removeTo = onlyChild ? $from.after(itemDepth - 1) : $from.after(itemDepth);
|
|
5978
|
+
const parentIsLast = $from.index(itemDepth - 3) === parentWrapper.childCount - 1;
|
|
5979
|
+
const tr = state$1.tr;
|
|
5980
|
+
tr.delete(removeFrom, removeTo);
|
|
5981
|
+
const newList = wrapper.type.create(wrapper.attrs, item);
|
|
5982
|
+
if (parentIsLast) {
|
|
5983
|
+
const insertAt = tr.mapping.map($from.after(itemDepth - 3));
|
|
5984
|
+
tr.insert(insertAt, newList);
|
|
5985
|
+
tr.setSelection(state.Selection.near(tr.doc.resolve(insertAt + 2)));
|
|
5986
|
+
} else {
|
|
5987
|
+
const splitAt = tr.mapping.map($from.after(itemDepth - 2));
|
|
5988
|
+
tr.split(splitAt, 1);
|
|
5989
|
+
tr.insert(splitAt + 1, newList);
|
|
5990
|
+
tr.setSelection(state.Selection.near(tr.doc.resolve(splitAt + 2)));
|
|
5991
|
+
}
|
|
5992
|
+
dispatch(tr.scrollIntoView());
|
|
5993
|
+
return true;
|
|
5994
|
+
}
|
|
5995
|
+
|
|
5996
|
+
// src/extensions/ListKeymap.ts
|
|
5932
5997
|
var LIST_GROUP_TYPES = /* @__PURE__ */ new Set(["bulletList", "orderedList", "taskList"]);
|
|
5933
5998
|
function getListItemContext(editor, listItemName) {
|
|
5934
5999
|
const { state, view } = editor;
|
|
@@ -5970,6 +6035,7 @@ var ListKeymap = Extension.create({
|
|
|
5970
6035
|
if (!this.editor) return false;
|
|
5971
6036
|
const ctx = getListItemContext(this.editor, this.options.listItem);
|
|
5972
6037
|
if (!ctx) return false;
|
|
6038
|
+
if (liftCrossTypeListItem(ctx.state, ctx.view.dispatch)) return true;
|
|
5973
6039
|
return schemaList.liftListItem(ctx.listItemType)(ctx.state, ctx.view.dispatch);
|
|
5974
6040
|
},
|
|
5975
6041
|
// Backspace at start of list item to lift
|
|
@@ -6023,6 +6089,7 @@ var ListKeymap = Extension.create({
|
|
|
6023
6089
|
if (firstChild?.isTextblock) {
|
|
6024
6090
|
const posInListItem = $from.pos - $from.start(listItemDepth);
|
|
6025
6091
|
if (posInListItem <= 1) {
|
|
6092
|
+
if (liftCrossTypeListItem(state$1, view.dispatch)) return true;
|
|
6026
6093
|
return schemaList.liftListItem(listItemType)(state$1, view.dispatch);
|
|
6027
6094
|
}
|
|
6028
6095
|
}
|
|
@@ -6069,7 +6136,22 @@ var ListItem = Node2.create({
|
|
|
6069
6136
|
if (commands.splitBlock(state$1, view.dispatch)) return true;
|
|
6070
6137
|
}
|
|
6071
6138
|
}
|
|
6072
|
-
|
|
6139
|
+
const item = $from.node(-1);
|
|
6140
|
+
const hasChildren = item.childCount > 1;
|
|
6141
|
+
const atEnd = $from.parentOffset === $from.parent.content.size;
|
|
6142
|
+
const labelEmpty = $from.parent.content.size === 0;
|
|
6143
|
+
if (!ctx?.isInChildrenZone && hasChildren && atEnd && !labelEmpty) {
|
|
6144
|
+
const newItem = this.nodeType.createAndFill();
|
|
6145
|
+
if (newItem) {
|
|
6146
|
+
const insertAt = $from.after($from.depth - 1);
|
|
6147
|
+
const tr = state$1.tr.insert(insertAt, newItem);
|
|
6148
|
+
tr.setSelection(state.Selection.near(tr.doc.resolve(insertAt + 2)));
|
|
6149
|
+
view.dispatch(tr.scrollIntoView());
|
|
6150
|
+
return true;
|
|
6151
|
+
}
|
|
6152
|
+
}
|
|
6153
|
+
const skipSplit = !ctx?.isInChildrenZone && labelEmpty && hasChildren;
|
|
6154
|
+
if (!skipSplit && schemaList.splitListItem(this.nodeType)(state$1, view.dispatch)) return true;
|
|
6073
6155
|
const listDepth = $from.depth - 2;
|
|
6074
6156
|
const taskItemType = state$1.schema.nodes["taskItem"];
|
|
6075
6157
|
if ($from.parent.content.size === 0 && listDepth > 0 && taskItemType && $from.node(listDepth - 1).type === taskItemType) {
|
|
@@ -6078,9 +6160,9 @@ var ListItem = Node2.create({
|
|
|
6078
6160
|
tr.delete($from.before(delDepth), $from.after(delDepth));
|
|
6079
6161
|
const taskItemDepth = listDepth - 1;
|
|
6080
6162
|
const end = tr.mapping.map($from.after(taskItemDepth));
|
|
6081
|
-
const
|
|
6082
|
-
if (
|
|
6083
|
-
tr.insert(end,
|
|
6163
|
+
const item2 = taskItemType.createAndFill();
|
|
6164
|
+
if (item2) {
|
|
6165
|
+
tr.insert(end, item2);
|
|
6084
6166
|
tr.setSelection(state.Selection.near(tr.doc.resolve(end + 2)));
|
|
6085
6167
|
view.dispatch(tr.scrollIntoView());
|
|
6086
6168
|
return true;
|
|
@@ -6209,16 +6291,20 @@ var OrderedList = Node2.create({
|
|
|
6209
6291
|
return {
|
|
6210
6292
|
start: {
|
|
6211
6293
|
default: 1,
|
|
6294
|
+
// Clamp to a finite integer >= 1. Without this, a malformed
|
|
6295
|
+
// `start="abc"` parses to NaN; `JSON.stringify(NaN)` is `null`, so
|
|
6296
|
+
// getJSON() serializes `start: null` and a save/load cycle
|
|
6297
|
+
// permanently dirties the document (reloads as `<ol start="null">`).
|
|
6212
6298
|
parseHTML: (element) => {
|
|
6213
|
-
const
|
|
6214
|
-
return
|
|
6299
|
+
const n = parseInt(element.getAttribute("start") ?? "", 10);
|
|
6300
|
+
return Number.isFinite(n) && n >= 1 ? Math.floor(n) : 1;
|
|
6215
6301
|
},
|
|
6216
6302
|
renderHTML: (attributes) => {
|
|
6217
6303
|
const start = attributes["start"];
|
|
6218
|
-
if (start
|
|
6304
|
+
if (!Number.isFinite(start) || start <= 1) {
|
|
6219
6305
|
return {};
|
|
6220
6306
|
}
|
|
6221
|
-
return { start: String(start) };
|
|
6307
|
+
return { start: String(Math.floor(start)) };
|
|
6222
6308
|
}
|
|
6223
6309
|
}
|
|
6224
6310
|
};
|
|
@@ -6297,8 +6383,8 @@ var OrderedList = Node2.create({
|
|
|
6297
6383
|
guard: notInsideList,
|
|
6298
6384
|
joinForward: true,
|
|
6299
6385
|
getAttributes: (match) => {
|
|
6300
|
-
const
|
|
6301
|
-
return { start:
|
|
6386
|
+
const n = parseInt(match[1] ?? "", 10);
|
|
6387
|
+
return { start: Number.isFinite(n) && n >= 1 ? Math.floor(n) : 1 };
|
|
6302
6388
|
}
|
|
6303
6389
|
})
|
|
6304
6390
|
];
|
|
@@ -6570,7 +6656,10 @@ var TaskItem = Node2.create({
|
|
|
6570
6656
|
keepOnSplit: false,
|
|
6571
6657
|
parseHTML: (element) => {
|
|
6572
6658
|
const dataChecked = element.getAttribute("data-checked");
|
|
6573
|
-
|
|
6659
|
+
if (dataChecked !== null) {
|
|
6660
|
+
return dataChecked.toLowerCase() === "true" || dataChecked === "";
|
|
6661
|
+
}
|
|
6662
|
+
return element.querySelector('input[type="checkbox"]')?.hasAttribute("checked") ?? false;
|
|
6574
6663
|
},
|
|
6575
6664
|
renderHTML: (attributes) => ({
|
|
6576
6665
|
"data-checked": attributes["checked"] ? "true" : "false"
|
|
@@ -6583,6 +6672,14 @@ var TaskItem = Node2.create({
|
|
|
6583
6672
|
{
|
|
6584
6673
|
tag: `li[data-type="${this.name}"]`,
|
|
6585
6674
|
priority: 51
|
|
6675
|
+
},
|
|
6676
|
+
// GFM / markdown task lists: `<li class="task-list-item">` carries no
|
|
6677
|
+
// data-type. Priority 51 keeps it ahead of the generic `li` (listItem,
|
|
6678
|
+
// 50); class-scoped so it never swallows ordinary bullet items. The
|
|
6679
|
+
// `checked` attribute is derived from the descendant `<input>` above.
|
|
6680
|
+
{
|
|
6681
|
+
tag: "li.task-list-item",
|
|
6682
|
+
priority: 51
|
|
6586
6683
|
}
|
|
6587
6684
|
];
|
|
6588
6685
|
},
|
|
@@ -6668,7 +6765,22 @@ var TaskItem = Node2.create({
|
|
|
6668
6765
|
return true;
|
|
6669
6766
|
}
|
|
6670
6767
|
}
|
|
6671
|
-
|
|
6768
|
+
const item = $from.node(-1);
|
|
6769
|
+
const hasChildren = item.childCount > 1;
|
|
6770
|
+
const labelEmpty = $from.parent.content.size === 0;
|
|
6771
|
+
const atEnd = $from.parentOffset === $from.parent.content.size;
|
|
6772
|
+
if (!ctx?.isInChildrenZone && hasChildren && atEnd && !labelEmpty) {
|
|
6773
|
+
const newItem = this.nodeType.createAndFill({ checked: false });
|
|
6774
|
+
if (newItem) {
|
|
6775
|
+
const insertAt = $from.after($from.depth - 1);
|
|
6776
|
+
const tr = state$1.tr.insert(insertAt, newItem);
|
|
6777
|
+
tr.setSelection(state.Selection.near(tr.doc.resolve(insertAt + 2)));
|
|
6778
|
+
view.dispatch(tr.scrollIntoView());
|
|
6779
|
+
return true;
|
|
6780
|
+
}
|
|
6781
|
+
}
|
|
6782
|
+
const skipSplit = !ctx?.isInChildrenZone && labelEmpty && hasChildren;
|
|
6783
|
+
if (!skipSplit && schemaList.splitListItem(this.nodeType, { checked: false })(state$1, view.dispatch)) return true;
|
|
6672
6784
|
if ($from.parent.content.size === 0) {
|
|
6673
6785
|
const listItemType = state$1.schema.nodes["listItem"];
|
|
6674
6786
|
if (listItemType) {
|
|
@@ -6715,9 +6827,11 @@ var TaskItem = Node2.create({
|
|
|
6715
6827
|
},
|
|
6716
6828
|
"Shift-Tab": () => {
|
|
6717
6829
|
if (!this.editor || !this.nodeType) return false;
|
|
6718
|
-
const {
|
|
6830
|
+
const { state, view } = this.editor;
|
|
6831
|
+
const { $from } = state.selection;
|
|
6719
6832
|
if ($from.depth < 1 || $from.node(-1).type !== this.nodeType) return false;
|
|
6720
|
-
|
|
6833
|
+
if (liftCrossTypeListItem(state, view.dispatch)) return true;
|
|
6834
|
+
return schemaList.liftListItem(this.nodeType)(state, view.dispatch);
|
|
6721
6835
|
},
|
|
6722
6836
|
Backspace: () => {
|
|
6723
6837
|
if (!this.editor || !this.nodeType) return false;
|
|
@@ -6739,6 +6853,7 @@ var TaskItem = Node2.create({
|
|
|
6739
6853
|
}
|
|
6740
6854
|
if (taskItemDepth === -1) return false;
|
|
6741
6855
|
if ($from.index(taskItemDepth) !== 0) return false;
|
|
6856
|
+
if (liftCrossTypeListItem(state, view.dispatch)) return true;
|
|
6742
6857
|
return schemaList.liftListItem(this.nodeType)(state, view.dispatch);
|
|
6743
6858
|
},
|
|
6744
6859
|
"Mod-Enter": () => {
|
|
@@ -6765,6 +6880,13 @@ var TaskList = Node2.create({
|
|
|
6765
6880
|
tag: `ul[data-type="${this.name}"]`,
|
|
6766
6881
|
priority: 51
|
|
6767
6882
|
// Higher priority than regular bulletList
|
|
6883
|
+
},
|
|
6884
|
+
// GFM / markdown task lists: `<ul class="contains-task-list">`. Priority
|
|
6885
|
+
// 51 keeps it ahead of the generic `ul` (bulletList, 50); class-scoped so
|
|
6886
|
+
// it only matches real GFM task-list containers, not ordinary bullets.
|
|
6887
|
+
{
|
|
6888
|
+
tag: "ul.contains-task-list",
|
|
6889
|
+
priority: 51
|
|
6768
6890
|
}
|
|
6769
6891
|
];
|
|
6770
6892
|
},
|
|
@@ -8025,12 +8147,12 @@ var Placeholder = Extension.create({
|
|
|
8025
8147
|
];
|
|
8026
8148
|
}
|
|
8027
8149
|
});
|
|
8028
|
-
var
|
|
8029
|
-
var
|
|
8150
|
+
var LIST_ITEM_TYPES5 = /* @__PURE__ */ new Set(["listItem", "taskItem"]);
|
|
8151
|
+
var LIST_WRAPPER_TYPES3 = /* @__PURE__ */ new Set(["bulletList", "orderedList", "taskList"]);
|
|
8030
8152
|
function isCursorInsideListItem(state) {
|
|
8031
8153
|
const { $from } = state.selection;
|
|
8032
8154
|
for (let d = $from.depth; d > 0; d--) {
|
|
8033
|
-
if (
|
|
8155
|
+
if (LIST_ITEM_TYPES5.has($from.node(d).type.name)) return true;
|
|
8034
8156
|
}
|
|
8035
8157
|
return false;
|
|
8036
8158
|
}
|
|
@@ -8061,7 +8183,7 @@ function indentBlockAsListChild(state$1, dispatch) {
|
|
|
8061
8183
|
}
|
|
8062
8184
|
if (blockIndex === 0) return false;
|
|
8063
8185
|
const prevSibling = state$1.doc.child(blockIndex - 1);
|
|
8064
|
-
if (!
|
|
8186
|
+
if (!LIST_WRAPPER_TYPES3.has(prevSibling.type.name)) return false;
|
|
8065
8187
|
let wrapperPos = 0;
|
|
8066
8188
|
for (let i = 0; i < blockIndex - 1; i++) {
|
|
8067
8189
|
wrapperPos += state$1.doc.child(i).nodeSize;
|
|
@@ -8085,7 +8207,7 @@ function outdentBlockFromListItem(state$1, dispatch) {
|
|
|
8085
8207
|
const { $from } = selection;
|
|
8086
8208
|
let listItemDepth = -1;
|
|
8087
8209
|
for (let d = $from.depth; d > 0; d--) {
|
|
8088
|
-
if (
|
|
8210
|
+
if (LIST_ITEM_TYPES5.has($from.node(d).type.name)) {
|
|
8089
8211
|
listItemDepth = d;
|
|
8090
8212
|
break;
|
|
8091
8213
|
}
|
|
@@ -8865,7 +8987,7 @@ var BlockColor = Extension.create({
|
|
|
8865
8987
|
};
|
|
8866
8988
|
}
|
|
8867
8989
|
});
|
|
8868
|
-
var
|
|
8990
|
+
var Selection5 = Extension.create({
|
|
8869
8991
|
name: "selection",
|
|
8870
8992
|
addStorage() {
|
|
8871
8993
|
return {
|
|
@@ -10419,7 +10541,7 @@ exports.NotionColorPicker = NotionColorPicker;
|
|
|
10419
10541
|
exports.OrderedList = OrderedList;
|
|
10420
10542
|
exports.Paragraph = Paragraph;
|
|
10421
10543
|
exports.Placeholder = Placeholder;
|
|
10422
|
-
exports.Selection =
|
|
10544
|
+
exports.Selection = Selection5;
|
|
10423
10545
|
exports.SelectionDecoration = SelectionDecoration;
|
|
10424
10546
|
exports.StarterKit = StarterKit;
|
|
10425
10547
|
exports.Strike = Strike;
|