prosekit 0.0.0-next-20230627094841
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/LICENSE +21 -0
- package/README.md +13 -0
- package/dist/basic/style.css +133 -0
- package/dist/chunk-23S3SZFA.js +46 -0
- package/dist/chunk-2MVHS73Q.js +709 -0
- package/dist/chunk-4GDRVRDP.js +0 -0
- package/dist/chunk-5PFF57NB.js +1546 -0
- package/dist/chunk-6A2XHVFY.js +46 -0
- package/dist/chunk-7OYIOTDD.js +16472 -0
- package/dist/chunk-ARJTWYPA.js +1321 -0
- package/dist/chunk-CDGN4JUS.js +1546 -0
- package/dist/chunk-CG5B6PMC.js +973 -0
- package/dist/chunk-DDN3TFRH.js +185 -0
- package/dist/chunk-EQV3CWHZ.js +2213 -0
- package/dist/chunk-ERNIDFFW.js +1711 -0
- package/dist/chunk-FAVXZAF7.js +3279 -0
- package/dist/chunk-HSPTUO6P.js +53 -0
- package/dist/chunk-JMNJUDT7.js +165 -0
- package/dist/chunk-LXCCO2LO.js +52 -0
- package/dist/chunk-MIPON3OH.js +922 -0
- package/dist/chunk-NAWSCY5F.js +166 -0
- package/dist/chunk-S64NFSV2.js +236 -0
- package/dist/chunk-S65R2BUY.js +15 -0
- package/dist/chunk-T2V5UU6H.js +204 -0
- package/dist/chunk-TWIMWRRZ.js +57 -0
- package/dist/chunk-US2P3K6I.js +185 -0
- package/dist/chunk-UTNVEPBA.js +950 -0
- package/dist/chunk-UWHQRU5N.js +4883 -0
- package/dist/chunk-VIKPJJET.js +662 -0
- package/dist/chunk-WAMZOD5I.js +67 -0
- package/dist/chunk-YUY5I2TY.js +236 -0
- package/dist/core/style.css +54 -0
- package/dist/extension-list/style.css +78 -0
- package/dist/pm/view/style/prosemirror.css +52 -0
- package/dist/prosekit-basic.js +2 -0
- package/dist/prosekit-core.js +2 -0
- package/dist/prosekit-extension-blockquote.js +2 -0
- package/dist/prosekit-extension-bold.js +2 -0
- package/dist/prosekit-extension-code-block.js +2 -0
- package/dist/prosekit-extension-code.js +2 -0
- package/dist/prosekit-extension-heading.js +2 -0
- package/dist/prosekit-extension-horizontal-rule.js +2 -0
- package/dist/prosekit-extension-italic.js +2 -0
- package/dist/prosekit-extension-list.js +2 -0
- package/dist/prosekit-extension-suggestion.js +2 -0
- package/dist/prosekit-lit-elements-menu-item.js +2 -0
- package/dist/prosekit-lit-elements-menu.js +2 -0
- package/dist/prosekit-lit-elements-popover.js +2 -0
- package/dist/prosekit-lit.js +2 -0
- package/dist/prosekit-pm-commands.js +2 -0
- package/dist/prosekit-pm-inputrules.js +2 -0
- package/dist/prosekit-pm-keymap.js +2 -0
- package/dist/prosekit-pm-model.js +2 -0
- package/dist/prosekit-pm-state.js +2 -0
- package/dist/prosekit-pm-transform.js +2 -0
- package/dist/prosekit-pm-view.js +2 -0
- package/dist/prosekit-pm.js +2 -0
- package/dist/prosekit-react-components-menu-item.js +2 -0
- package/dist/prosekit-react-components-menu.js +2 -0
- package/dist/prosekit-react-components-popover-suggestion.js +2 -0
- package/dist/prosekit-react-components-popover.js +2 -0
- package/dist/prosekit-react.js +2 -0
- package/dist/prosekit-vue-components-menu-item.js +2 -0
- package/dist/prosekit-vue-components-menu.js +2 -0
- package/dist/prosekit-vue-components-popover-suggestion.js +2 -0
- package/dist/prosekit-vue-components-popover.js +2 -0
- package/dist/prosekit-vue.js +2 -0
- package/dist/prosekit.js +0 -0
- package/package.json +262 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1,1321 @@
|
|
|
1
|
+
import {
|
|
2
|
+
addInputRule,
|
|
3
|
+
addKeymap,
|
|
4
|
+
addNodeSpec,
|
|
5
|
+
addPlugin,
|
|
6
|
+
defineExtension
|
|
7
|
+
} from "./chunk-2MVHS73Q.js";
|
|
8
|
+
import {
|
|
9
|
+
Decoration,
|
|
10
|
+
DecorationSet
|
|
11
|
+
} from "./chunk-UWHQRU5N.js";
|
|
12
|
+
import {
|
|
13
|
+
chainCommands,
|
|
14
|
+
createParagraphNear,
|
|
15
|
+
deleteSelection,
|
|
16
|
+
joinTextblockBackward,
|
|
17
|
+
joinTextblockForward,
|
|
18
|
+
newlineInCode,
|
|
19
|
+
selectNodeBackward,
|
|
20
|
+
selectNodeForward,
|
|
21
|
+
splitBlock
|
|
22
|
+
} from "./chunk-VIKPJJET.js";
|
|
23
|
+
import {
|
|
24
|
+
InputRule
|
|
25
|
+
} from "./chunk-JMNJUDT7.js";
|
|
26
|
+
import {
|
|
27
|
+
Plugin,
|
|
28
|
+
Selection,
|
|
29
|
+
TextSelection
|
|
30
|
+
} from "./chunk-UTNVEPBA.js";
|
|
31
|
+
import {
|
|
32
|
+
ReplaceAroundStep,
|
|
33
|
+
ReplaceStep,
|
|
34
|
+
canJoin,
|
|
35
|
+
canSplit,
|
|
36
|
+
findWrapping,
|
|
37
|
+
liftTarget,
|
|
38
|
+
replaceStep
|
|
39
|
+
} from "./chunk-ERNIDFFW.js";
|
|
40
|
+
import {
|
|
41
|
+
DOMSerializer,
|
|
42
|
+
Fragment,
|
|
43
|
+
NodeRange,
|
|
44
|
+
Slice
|
|
45
|
+
} from "./chunk-FAVXZAF7.js";
|
|
46
|
+
|
|
47
|
+
// ../../node_modules/.pnpm/prosemirror-flat-list@0.3.13/node_modules/prosemirror-flat-list/dist/prosemirror-flat-list.js
|
|
48
|
+
function parseInteger(attr) {
|
|
49
|
+
if (attr == null)
|
|
50
|
+
return null;
|
|
51
|
+
const int = Number.parseInt(attr, 10);
|
|
52
|
+
if (Number.isInteger(int))
|
|
53
|
+
return int;
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
function createParseDomRules() {
|
|
57
|
+
return [
|
|
58
|
+
{
|
|
59
|
+
tag: "div[data-list-kind]",
|
|
60
|
+
getAttrs: (element) => {
|
|
61
|
+
if (typeof element === "string") {
|
|
62
|
+
return {};
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
kind: element.getAttribute("data-list-kind") || "bullet",
|
|
66
|
+
order: parseInteger(element.getAttribute("data-list-order")),
|
|
67
|
+
checked: element.hasAttribute("data-list-checked"),
|
|
68
|
+
collapsed: element.hasAttribute("data-list-collapsed")
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
tag: "div[data-list]",
|
|
74
|
+
getAttrs: (element) => {
|
|
75
|
+
if (typeof element === "string") {
|
|
76
|
+
return {};
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
kind: element.getAttribute("data-list-kind") || "bullet",
|
|
80
|
+
order: parseInteger(element.getAttribute("data-list-order")),
|
|
81
|
+
checked: element.hasAttribute("data-list-checked"),
|
|
82
|
+
collapsed: element.hasAttribute("data-list-collapsed")
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
tag: "ul > li",
|
|
88
|
+
getAttrs: (element) => {
|
|
89
|
+
var _a;
|
|
90
|
+
if (typeof element !== "string") {
|
|
91
|
+
let checkbox = element.firstChild;
|
|
92
|
+
for (let i = 0; i < 3 && checkbox; i++) {
|
|
93
|
+
if (["INPUT", "UL", "OL", "LI"].includes(checkbox.nodeName)) {
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
checkbox = checkbox.firstChild;
|
|
97
|
+
}
|
|
98
|
+
if (checkbox && checkbox.nodeName === "INPUT" && checkbox.getAttribute("type") === "checkbox") {
|
|
99
|
+
return {
|
|
100
|
+
kind: "task",
|
|
101
|
+
checked: checkbox.hasAttribute("checked")
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
if (element.hasAttribute("data-task-list-item") || element.getAttribute("data-list-kind") === "task") {
|
|
105
|
+
return {
|
|
106
|
+
kind: "task",
|
|
107
|
+
checked: element.hasAttribute("data-list-checked") || element.hasAttribute("data-checked")
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
if (element.hasAttribute("data-toggle-list-item") || element.getAttribute("data-list-kind") === "toggle") {
|
|
111
|
+
return {
|
|
112
|
+
kind: "toggle",
|
|
113
|
+
collapsed: element.hasAttribute("data-list-collapsed")
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
if (((_a = element.firstChild) == null ? void 0 : _a.nodeType) === 3) {
|
|
117
|
+
const textContent = element.firstChild.textContent;
|
|
118
|
+
if (textContent && textContent.match(/^\[[\s|x]\]\s{1,2}/)) {
|
|
119
|
+
element.firstChild.textContent = textContent.replace(
|
|
120
|
+
/^\[[\s|x]\]\s{1,2}/,
|
|
121
|
+
""
|
|
122
|
+
);
|
|
123
|
+
return {
|
|
124
|
+
kind: "task",
|
|
125
|
+
checked: textContent.startsWith("[x]")
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
kind: "bullet"
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
tag: "ol > li",
|
|
137
|
+
getAttrs: (element) => {
|
|
138
|
+
if (typeof element === "string") {
|
|
139
|
+
return {
|
|
140
|
+
kind: "ordered"
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
kind: "ordered",
|
|
145
|
+
order: parseInteger(element.getAttribute("data-list-order"))
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
// This rule is for handling nested lists copied from Dropbox Paper. It's
|
|
151
|
+
// technically invalid HTML structure.
|
|
152
|
+
tag: ":is(ul, ol) > :is(ul, ol)",
|
|
153
|
+
getAttrs: () => {
|
|
154
|
+
return {
|
|
155
|
+
kind: "bullet"
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
];
|
|
160
|
+
}
|
|
161
|
+
var nav = typeof navigator != "undefined" ? navigator : null;
|
|
162
|
+
var agent = nav && nav.userAgent || "";
|
|
163
|
+
var ie_edge = /Edge\/(\d+)/.exec(agent);
|
|
164
|
+
var ie_upto10 = /MSIE \d/.exec(agent);
|
|
165
|
+
var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(agent);
|
|
166
|
+
var ie = !!(ie_upto10 || ie_11up || ie_edge);
|
|
167
|
+
var safari = !ie && !!nav && /Apple Computer/.test(nav.vendor);
|
|
168
|
+
function listToDOM({
|
|
169
|
+
node,
|
|
170
|
+
nativeList = false,
|
|
171
|
+
getMarkers = defaultMarkerGetter,
|
|
172
|
+
getAttributes = defaultAttributesGetter
|
|
173
|
+
}) {
|
|
174
|
+
var _a;
|
|
175
|
+
const attrs = node.attrs;
|
|
176
|
+
const markerHidden = ((_a = node.firstChild) == null ? void 0 : _a.type) === node.type;
|
|
177
|
+
const markers = markerHidden ? null : getMarkers(node);
|
|
178
|
+
const domAttrs = getAttributes(node);
|
|
179
|
+
const contentContainer = ["div", { class: "list-content" }, 0];
|
|
180
|
+
const markerContainer = markers && [
|
|
181
|
+
"div",
|
|
182
|
+
{
|
|
183
|
+
class: "list-marker list-marker-click-target",
|
|
184
|
+
// Set `contenteditable` to `false` so that the cursor won't be
|
|
185
|
+
// moved into the mark container when clicking on it.
|
|
186
|
+
contenteditable: "false"
|
|
187
|
+
},
|
|
188
|
+
...markers
|
|
189
|
+
];
|
|
190
|
+
if (nativeList) {
|
|
191
|
+
const listTag = attrs.kind === "ordered" ? "ol" : "ul";
|
|
192
|
+
if (markerContainer) {
|
|
193
|
+
return [listTag, ["li", domAttrs, markerContainer, contentContainer]];
|
|
194
|
+
} else {
|
|
195
|
+
return [listTag, ["li", domAttrs, 0]];
|
|
196
|
+
}
|
|
197
|
+
} else {
|
|
198
|
+
if (markerContainer) {
|
|
199
|
+
return ["div", domAttrs, markerContainer, contentContainer];
|
|
200
|
+
} else {
|
|
201
|
+
return ["div", domAttrs, contentContainer];
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function defaultMarkerGetter(node) {
|
|
206
|
+
const attrs = node.attrs;
|
|
207
|
+
switch (attrs.kind) {
|
|
208
|
+
case "task":
|
|
209
|
+
return [
|
|
210
|
+
[
|
|
211
|
+
"label",
|
|
212
|
+
[
|
|
213
|
+
"input",
|
|
214
|
+
{ type: "checkbox", checked: attrs.checked ? "" : void 0 }
|
|
215
|
+
]
|
|
216
|
+
]
|
|
217
|
+
];
|
|
218
|
+
case "toggle":
|
|
219
|
+
return [];
|
|
220
|
+
default:
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
function defaultAttributesGetter(node) {
|
|
225
|
+
var _a;
|
|
226
|
+
const attrs = node.attrs;
|
|
227
|
+
const markerHidden = ((_a = node.firstChild) == null ? void 0 : _a.type) === node.type;
|
|
228
|
+
const markerType = markerHidden ? void 0 : attrs.kind || "bullet";
|
|
229
|
+
const domAttrs = {
|
|
230
|
+
class: "prosemirror-flat-list",
|
|
231
|
+
"data-list-kind": markerType,
|
|
232
|
+
"data-list-order": attrs.order != null ? String(attrs.order) : void 0,
|
|
233
|
+
"data-list-checked": attrs.checked ? "" : void 0,
|
|
234
|
+
"data-list-collapsed": attrs.collapsed ? "" : void 0,
|
|
235
|
+
"data-list-collapsable": node.childCount >= 2 ? "" : void 0,
|
|
236
|
+
style: attrs.order != null ? (
|
|
237
|
+
// Safari (at least version <= 16.5) doesn't support `counter-set`
|
|
238
|
+
safari ? `counter-reset: prosemirror-flat-list-counter; counter-increment: prosemirror-flat-list-counter ${attrs.order};` : `counter-set: prosemirror-flat-list-counter ${attrs.order};`
|
|
239
|
+
) : void 0
|
|
240
|
+
};
|
|
241
|
+
return domAttrs;
|
|
242
|
+
}
|
|
243
|
+
var flatListGroup = "flatList";
|
|
244
|
+
function createListSpec() {
|
|
245
|
+
return {
|
|
246
|
+
content: "block+",
|
|
247
|
+
group: `${flatListGroup} block`,
|
|
248
|
+
defining: true,
|
|
249
|
+
attrs: {
|
|
250
|
+
kind: {
|
|
251
|
+
default: "bullet"
|
|
252
|
+
},
|
|
253
|
+
order: {
|
|
254
|
+
default: null
|
|
255
|
+
},
|
|
256
|
+
checked: {
|
|
257
|
+
default: false
|
|
258
|
+
},
|
|
259
|
+
collapsed: {
|
|
260
|
+
default: false
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
toDOM: (node) => {
|
|
264
|
+
return listToDOM({ node });
|
|
265
|
+
},
|
|
266
|
+
parseDOM: createParseDomRules()
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
function getListType(schema) {
|
|
270
|
+
let name = schema.cached["PROSEMIRROR_FLAT_LIST_LIST_TYPE_NAME"];
|
|
271
|
+
if (!name) {
|
|
272
|
+
for (const type of Object.values(schema.nodes)) {
|
|
273
|
+
if ((type.spec.group || "").split(" ").includes(flatListGroup)) {
|
|
274
|
+
name = type.name;
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (!name) {
|
|
279
|
+
throw new TypeError(
|
|
280
|
+
"[prosemirror-flat-list] Unable to find a flat list type in the schema"
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
schema.cached["PROSEMIRROR_FLAT_LIST_LIST_TYPE_NAME"] = name;
|
|
284
|
+
}
|
|
285
|
+
return schema.nodes[name];
|
|
286
|
+
}
|
|
287
|
+
function isListType(type) {
|
|
288
|
+
return getListType(type.schema) === type;
|
|
289
|
+
}
|
|
290
|
+
function isListNode(node) {
|
|
291
|
+
if (!node)
|
|
292
|
+
return false;
|
|
293
|
+
return isListType(node.type);
|
|
294
|
+
}
|
|
295
|
+
function patchCommand(patch) {
|
|
296
|
+
const withPatch = (command) => {
|
|
297
|
+
const patchedCommand = (state, dispatch, view) => {
|
|
298
|
+
return command(
|
|
299
|
+
state,
|
|
300
|
+
dispatch ? (tr) => dispatch(patch(tr)) : void 0,
|
|
301
|
+
view
|
|
302
|
+
);
|
|
303
|
+
};
|
|
304
|
+
return patchedCommand;
|
|
305
|
+
};
|
|
306
|
+
return withPatch;
|
|
307
|
+
}
|
|
308
|
+
function* getTransactionRanges(tr) {
|
|
309
|
+
const ranges = [];
|
|
310
|
+
let i = 0;
|
|
311
|
+
while (true) {
|
|
312
|
+
for (; i < tr.mapping.maps.length; i++) {
|
|
313
|
+
const map = tr.mapping.maps[i];
|
|
314
|
+
for (let j = 0; j < ranges.length; j++) {
|
|
315
|
+
ranges[j] = map.map(ranges[j]);
|
|
316
|
+
}
|
|
317
|
+
map.forEach(
|
|
318
|
+
(_oldStart, _oldEnd, newStart, newEnd) => ranges.push(newStart, newEnd)
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
yield ranges;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
function findBoundaries(positions, doc, prediction) {
|
|
325
|
+
const boundaries = /* @__PURE__ */ new Set();
|
|
326
|
+
const joinable = [];
|
|
327
|
+
for (const pos of positions) {
|
|
328
|
+
const $pos = doc.resolve(pos);
|
|
329
|
+
for (let depth = $pos.depth; depth >= 0; depth--) {
|
|
330
|
+
const boundary = $pos.before(depth + 1);
|
|
331
|
+
if (boundaries.has(boundary)) {
|
|
332
|
+
break;
|
|
333
|
+
}
|
|
334
|
+
boundaries.add(boundary);
|
|
335
|
+
const index = $pos.index(depth);
|
|
336
|
+
const parent = $pos.node(depth);
|
|
337
|
+
const before = parent.maybeChild(index - 1);
|
|
338
|
+
if (!before)
|
|
339
|
+
continue;
|
|
340
|
+
const after = parent.maybeChild(index);
|
|
341
|
+
if (!after)
|
|
342
|
+
continue;
|
|
343
|
+
if (prediction(before, after, parent, index)) {
|
|
344
|
+
joinable.push(boundary);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return joinable.sort((a, b) => b - a);
|
|
349
|
+
}
|
|
350
|
+
function isListJoinable(before, after) {
|
|
351
|
+
return isListNode(before) && isListNode(after) && isListNode(after.firstChild);
|
|
352
|
+
}
|
|
353
|
+
function isListSplitable(before, after, parent, index) {
|
|
354
|
+
if (index === 1 && isListNode(parent) && isListNode(before) && !isListNode(after)) {
|
|
355
|
+
return true;
|
|
356
|
+
}
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
function fixList(tr) {
|
|
360
|
+
const ranges = getTransactionRanges(tr);
|
|
361
|
+
const joinable = findBoundaries(ranges.next().value, tr.doc, isListJoinable);
|
|
362
|
+
for (const pos of joinable) {
|
|
363
|
+
if (canJoin(tr.doc, pos)) {
|
|
364
|
+
tr.join(pos);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
const splitable = findBoundaries(ranges.next().value, tr.doc, isListSplitable);
|
|
368
|
+
for (const pos of splitable) {
|
|
369
|
+
if (canSplit(tr.doc, pos)) {
|
|
370
|
+
tr.split(pos);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return tr;
|
|
374
|
+
}
|
|
375
|
+
var withAutoFixList = patchCommand(fixList);
|
|
376
|
+
function atStartBlockBoundary($pos, depth) {
|
|
377
|
+
for (let d = depth; d <= $pos.depth; d++) {
|
|
378
|
+
if ($pos.node(d).isTextblock) {
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
const index = $pos.index(d);
|
|
382
|
+
if (index !== 0) {
|
|
383
|
+
return false;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
return true;
|
|
387
|
+
}
|
|
388
|
+
function atEndBlockBoundary($pos, depth) {
|
|
389
|
+
for (let d = depth; d <= $pos.depth; d++) {
|
|
390
|
+
if ($pos.node(d).isTextblock) {
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
const index = $pos.index(d);
|
|
394
|
+
if (index !== $pos.node(d).childCount - 1) {
|
|
395
|
+
return false;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
return true;
|
|
399
|
+
}
|
|
400
|
+
function findListsRange($from, $to = $from) {
|
|
401
|
+
if ($to.pos < $from.pos) {
|
|
402
|
+
return findListsRange($to, $from);
|
|
403
|
+
}
|
|
404
|
+
let range = $from.blockRange($to);
|
|
405
|
+
while (range) {
|
|
406
|
+
if (isListsRange(range)) {
|
|
407
|
+
return range;
|
|
408
|
+
}
|
|
409
|
+
if (range.depth <= 0) {
|
|
410
|
+
break;
|
|
411
|
+
}
|
|
412
|
+
range = new NodeRange($from, $to, range.depth - 1);
|
|
413
|
+
}
|
|
414
|
+
return null;
|
|
415
|
+
}
|
|
416
|
+
function isListsRange(range) {
|
|
417
|
+
const { startIndex, endIndex, parent } = range;
|
|
418
|
+
for (let i = startIndex; i < endIndex; i++) {
|
|
419
|
+
if (!isListNode(parent.child(i))) {
|
|
420
|
+
return false;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return true;
|
|
424
|
+
}
|
|
425
|
+
function mapPos(tr, pos) {
|
|
426
|
+
let nextStepIndex = tr.steps.length;
|
|
427
|
+
const getPos = () => {
|
|
428
|
+
if (nextStepIndex < tr.steps.length) {
|
|
429
|
+
const mapping = tr.mapping.slice(nextStepIndex);
|
|
430
|
+
nextStepIndex = tr.steps.length;
|
|
431
|
+
pos = mapping.map(pos);
|
|
432
|
+
}
|
|
433
|
+
return pos;
|
|
434
|
+
};
|
|
435
|
+
return getPos;
|
|
436
|
+
}
|
|
437
|
+
function safeLift(tr, range) {
|
|
438
|
+
const target = liftTarget(range);
|
|
439
|
+
if (target == null) {
|
|
440
|
+
return false;
|
|
441
|
+
}
|
|
442
|
+
tr.lift(range, target);
|
|
443
|
+
return true;
|
|
444
|
+
}
|
|
445
|
+
function zoomInRange(range) {
|
|
446
|
+
const { $from, $to, depth, start, end } = range;
|
|
447
|
+
const doc = $from.doc;
|
|
448
|
+
const deeper = ($from.pos > start ? $from : doc.resolve(start + 1)).blockRange($to.pos < end ? $to : doc.resolve(end - 1));
|
|
449
|
+
if (deeper && deeper.depth > depth) {
|
|
450
|
+
return deeper;
|
|
451
|
+
}
|
|
452
|
+
return null;
|
|
453
|
+
}
|
|
454
|
+
function isCollapsedListNode(node) {
|
|
455
|
+
return !!(isListNode(node) && node.attrs.collapsed);
|
|
456
|
+
}
|
|
457
|
+
function setNodeAttributes(tr, pos, oldAttrs, newAttrs) {
|
|
458
|
+
let needUpdate = false;
|
|
459
|
+
for (const key of Object.keys(newAttrs)) {
|
|
460
|
+
if (newAttrs[key] !== oldAttrs[key]) {
|
|
461
|
+
tr.setNodeAttribute(pos, key, newAttrs[key]);
|
|
462
|
+
needUpdate = true;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
return needUpdate;
|
|
466
|
+
}
|
|
467
|
+
function setListAttributes(tr, pos, attrs) {
|
|
468
|
+
const $pos = tr.doc.resolve(pos);
|
|
469
|
+
const node = $pos.nodeAfter;
|
|
470
|
+
if (node && isListNode(node)) {
|
|
471
|
+
const oldAttrs = node.attrs;
|
|
472
|
+
const newAttrs = { ...oldAttrs, ...attrs };
|
|
473
|
+
return setNodeAttributes(tr, pos, oldAttrs, newAttrs);
|
|
474
|
+
}
|
|
475
|
+
return false;
|
|
476
|
+
}
|
|
477
|
+
function moveOutOfCollapsed($pos, minDepth) {
|
|
478
|
+
for (let depth = minDepth; depth <= $pos.depth; depth++) {
|
|
479
|
+
if (isCollapsedListNode($pos.node(depth)) && $pos.index(depth) >= 1) {
|
|
480
|
+
const before = $pos.posAtIndex(1, depth);
|
|
481
|
+
const $before = $pos.doc.resolve(before);
|
|
482
|
+
return TextSelection.near($before, -1);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
return null;
|
|
486
|
+
}
|
|
487
|
+
function setSafeSelection(tr) {
|
|
488
|
+
const { $from, $to, to } = tr.selection;
|
|
489
|
+
const selection = moveOutOfCollapsed($from, 0) || moveOutOfCollapsed($to, $from.sharedDepth(to));
|
|
490
|
+
if (selection) {
|
|
491
|
+
tr.setSelection(selection);
|
|
492
|
+
}
|
|
493
|
+
return tr;
|
|
494
|
+
}
|
|
495
|
+
var withSafeSelection = patchCommand(setSafeSelection);
|
|
496
|
+
function getCollapsedPosition($pos, minDepth) {
|
|
497
|
+
for (let depth = minDepth; depth <= $pos.depth; depth++) {
|
|
498
|
+
if (isCollapsedListNode($pos.node(depth)) && $pos.index(depth) >= 1) {
|
|
499
|
+
return $pos.before(depth);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
return null;
|
|
503
|
+
}
|
|
504
|
+
function setVisibleSelection(tr) {
|
|
505
|
+
var _a;
|
|
506
|
+
const { $from, $to, to } = tr.selection;
|
|
507
|
+
const pos = (_a = getCollapsedPosition($from, 0)) != null ? _a : getCollapsedPosition($to, $from.sharedDepth(to));
|
|
508
|
+
if (pos != null) {
|
|
509
|
+
tr.doc.resolve(pos);
|
|
510
|
+
setListAttributes(tr, pos, { collapsed: false });
|
|
511
|
+
}
|
|
512
|
+
return tr;
|
|
513
|
+
}
|
|
514
|
+
var withVisibleSelection = patchCommand(setVisibleSelection);
|
|
515
|
+
function createDedentListCommand(options) {
|
|
516
|
+
const dedentListCommand = (state, dispatch) => {
|
|
517
|
+
const tr = state.tr;
|
|
518
|
+
const $from = (options == null ? void 0 : options.from) == null ? tr.selection.$from : tr.doc.resolve(options.from);
|
|
519
|
+
const $to = (options == null ? void 0 : options.to) == null ? tr.selection.$to : tr.doc.resolve(options.to);
|
|
520
|
+
const range = findListsRange($from, $to);
|
|
521
|
+
if (!range)
|
|
522
|
+
return false;
|
|
523
|
+
if (dedentRange(range, tr)) {
|
|
524
|
+
dispatch == null ? void 0 : dispatch(tr);
|
|
525
|
+
return true;
|
|
526
|
+
}
|
|
527
|
+
return false;
|
|
528
|
+
};
|
|
529
|
+
return withVisibleSelection(withAutoFixList(dedentListCommand));
|
|
530
|
+
}
|
|
531
|
+
function dedentRange(range, tr, startBoundary, endBoundary) {
|
|
532
|
+
const { depth, $from, $to } = range;
|
|
533
|
+
startBoundary = startBoundary || atStartBlockBoundary($from, depth + 1);
|
|
534
|
+
if (!startBoundary) {
|
|
535
|
+
const { startIndex, endIndex } = range;
|
|
536
|
+
if (endIndex - startIndex === 1) {
|
|
537
|
+
const contentRange = zoomInRange(range);
|
|
538
|
+
return contentRange ? dedentRange(contentRange, tr) : false;
|
|
539
|
+
} else {
|
|
540
|
+
return splitAndDedentRange(range, tr, startIndex + 1);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
endBoundary = endBoundary || atEndBlockBoundary($to, depth + 1);
|
|
544
|
+
if (!endBoundary) {
|
|
545
|
+
fixEndBoundary(range, tr);
|
|
546
|
+
const endOfParent = $to.end(depth);
|
|
547
|
+
range = new NodeRange(
|
|
548
|
+
tr.doc.resolve($from.pos),
|
|
549
|
+
tr.doc.resolve(endOfParent),
|
|
550
|
+
depth
|
|
551
|
+
);
|
|
552
|
+
return dedentRange(range, tr, void 0, true);
|
|
553
|
+
}
|
|
554
|
+
if (range.startIndex === 0 && range.endIndex === range.parent.childCount && isListNode(range.parent)) {
|
|
555
|
+
return dedentNodeRange(new NodeRange($from, $to, depth - 1), tr);
|
|
556
|
+
}
|
|
557
|
+
return dedentNodeRange(range, tr);
|
|
558
|
+
}
|
|
559
|
+
function splitAndDedentRange(range, tr, splitIndex) {
|
|
560
|
+
const { $from, $to, depth } = range;
|
|
561
|
+
const splitPos = $from.posAtIndex(splitIndex, depth);
|
|
562
|
+
const range1 = $from.blockRange(tr.doc.resolve(splitPos - 1));
|
|
563
|
+
if (!range1)
|
|
564
|
+
return false;
|
|
565
|
+
const getRange2From = mapPos(tr, splitPos + 1);
|
|
566
|
+
const getRange2To = mapPos(tr, $to.pos);
|
|
567
|
+
dedentRange(range1, tr, void 0, true);
|
|
568
|
+
let range2 = tr.doc.resolve(getRange2From()).blockRange(tr.doc.resolve(getRange2To()));
|
|
569
|
+
if (range2 && range2.depth >= depth) {
|
|
570
|
+
range2 = new NodeRange(range2.$from, range2.$to, depth);
|
|
571
|
+
dedentRange(range2, tr, true, void 0);
|
|
572
|
+
}
|
|
573
|
+
return true;
|
|
574
|
+
}
|
|
575
|
+
function dedentNodeRange(range, tr) {
|
|
576
|
+
if (isListNode(range.parent)) {
|
|
577
|
+
return safeLiftRange(tr, range);
|
|
578
|
+
} else if (isListsRange(range)) {
|
|
579
|
+
return dedentOutOfList(tr, range);
|
|
580
|
+
} else {
|
|
581
|
+
return safeLiftRange(tr, range);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
function safeLiftRange(tr, range) {
|
|
585
|
+
if (moveRangeSiblings(tr, range)) {
|
|
586
|
+
const $from = tr.doc.resolve(range.$from.pos);
|
|
587
|
+
const $to = tr.doc.resolve(range.$to.pos);
|
|
588
|
+
range = new NodeRange($from, $to, range.depth);
|
|
589
|
+
}
|
|
590
|
+
return safeLift(tr, range);
|
|
591
|
+
}
|
|
592
|
+
function moveRangeSiblings(tr, range) {
|
|
593
|
+
const listType = getListType(tr.doc.type.schema);
|
|
594
|
+
const { $to, depth, end, parent, endIndex } = range;
|
|
595
|
+
const endOfParent = $to.end(depth);
|
|
596
|
+
if (end < endOfParent) {
|
|
597
|
+
const lastChild = parent.maybeChild(endIndex - 1);
|
|
598
|
+
if (!lastChild)
|
|
599
|
+
return false;
|
|
600
|
+
const canAppend = endIndex < parent.childCount && lastChild.canReplace(
|
|
601
|
+
lastChild.childCount,
|
|
602
|
+
lastChild.childCount,
|
|
603
|
+
parent.content,
|
|
604
|
+
endIndex,
|
|
605
|
+
parent.childCount
|
|
606
|
+
);
|
|
607
|
+
if (canAppend) {
|
|
608
|
+
tr.step(
|
|
609
|
+
new ReplaceAroundStep(
|
|
610
|
+
end - 1,
|
|
611
|
+
endOfParent,
|
|
612
|
+
end,
|
|
613
|
+
endOfParent,
|
|
614
|
+
new Slice(Fragment.from(listType.create(null)), 1, 0),
|
|
615
|
+
0,
|
|
616
|
+
true
|
|
617
|
+
)
|
|
618
|
+
);
|
|
619
|
+
return true;
|
|
620
|
+
} else {
|
|
621
|
+
tr.step(
|
|
622
|
+
new ReplaceAroundStep(
|
|
623
|
+
end,
|
|
624
|
+
endOfParent,
|
|
625
|
+
end,
|
|
626
|
+
endOfParent,
|
|
627
|
+
new Slice(Fragment.from(listType.create(null)), 0, 0),
|
|
628
|
+
1,
|
|
629
|
+
true
|
|
630
|
+
)
|
|
631
|
+
);
|
|
632
|
+
return true;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
return false;
|
|
636
|
+
}
|
|
637
|
+
function fixEndBoundary(range, tr) {
|
|
638
|
+
if (range.endIndex - range.startIndex >= 2) {
|
|
639
|
+
range = new NodeRange(
|
|
640
|
+
range.$to.doc.resolve(
|
|
641
|
+
range.$to.posAtIndex(range.endIndex - 1, range.depth)
|
|
642
|
+
),
|
|
643
|
+
range.$to,
|
|
644
|
+
range.depth
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
const contentRange = zoomInRange(range);
|
|
648
|
+
if (contentRange) {
|
|
649
|
+
fixEndBoundary(contentRange, tr);
|
|
650
|
+
range = new NodeRange(
|
|
651
|
+
tr.doc.resolve(range.$from.pos),
|
|
652
|
+
tr.doc.resolve(range.$to.pos),
|
|
653
|
+
range.depth
|
|
654
|
+
);
|
|
655
|
+
}
|
|
656
|
+
moveRangeSiblings(tr, range);
|
|
657
|
+
}
|
|
658
|
+
function dedentOutOfList(tr, range) {
|
|
659
|
+
const { startIndex, endIndex, parent } = range;
|
|
660
|
+
const getRangeStart = mapPos(tr, range.start);
|
|
661
|
+
const getRangeEnd = mapPos(tr, range.end);
|
|
662
|
+
for (let end2 = getRangeEnd(), i = endIndex - 1; i > startIndex; i--) {
|
|
663
|
+
end2 -= parent.child(i).nodeSize;
|
|
664
|
+
tr.delete(end2 - 1, end2 + 1);
|
|
665
|
+
}
|
|
666
|
+
const $start = tr.doc.resolve(getRangeStart());
|
|
667
|
+
const listNode = $start.nodeAfter;
|
|
668
|
+
if (!listNode)
|
|
669
|
+
return false;
|
|
670
|
+
const start = range.start;
|
|
671
|
+
const end = start + listNode.nodeSize;
|
|
672
|
+
if (getRangeEnd() !== end)
|
|
673
|
+
return false;
|
|
674
|
+
if (!$start.parent.canReplace(
|
|
675
|
+
startIndex,
|
|
676
|
+
startIndex + 1,
|
|
677
|
+
Fragment.from(listNode)
|
|
678
|
+
)) {
|
|
679
|
+
return false;
|
|
680
|
+
}
|
|
681
|
+
tr.step(
|
|
682
|
+
new ReplaceAroundStep(
|
|
683
|
+
start,
|
|
684
|
+
end,
|
|
685
|
+
start + 1,
|
|
686
|
+
end - 1,
|
|
687
|
+
new Slice(Fragment.empty, 0, 0),
|
|
688
|
+
0,
|
|
689
|
+
true
|
|
690
|
+
)
|
|
691
|
+
);
|
|
692
|
+
return true;
|
|
693
|
+
}
|
|
694
|
+
var enterWithoutLift = chainCommands(
|
|
695
|
+
newlineInCode,
|
|
696
|
+
createParagraphNear,
|
|
697
|
+
splitBlock
|
|
698
|
+
);
|
|
699
|
+
function inCollapsedList($pos) {
|
|
700
|
+
for (let depth = $pos.depth; depth >= 0; depth--) {
|
|
701
|
+
const node = $pos.node(depth);
|
|
702
|
+
if (isListNode(node)) {
|
|
703
|
+
const attrs = node.attrs;
|
|
704
|
+
if (attrs.collapsed) {
|
|
705
|
+
return true;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
return false;
|
|
710
|
+
}
|
|
711
|
+
function createIndentListCommand(options) {
|
|
712
|
+
const indentListCommand = (state, dispatch) => {
|
|
713
|
+
const tr = state.tr;
|
|
714
|
+
const $from = (options == null ? void 0 : options.from) == null ? tr.selection.$from : tr.doc.resolve(options.from);
|
|
715
|
+
const $to = (options == null ? void 0 : options.to) == null ? tr.selection.$to : tr.doc.resolve(options.to);
|
|
716
|
+
const range = findListsRange($from, $to) || $from.blockRange($to);
|
|
717
|
+
if (!range)
|
|
718
|
+
return false;
|
|
719
|
+
if (indentRange(range, tr)) {
|
|
720
|
+
dispatch == null ? void 0 : dispatch(tr);
|
|
721
|
+
return true;
|
|
722
|
+
}
|
|
723
|
+
return false;
|
|
724
|
+
};
|
|
725
|
+
return withVisibleSelection(withAutoFixList(indentListCommand));
|
|
726
|
+
}
|
|
727
|
+
function indentRange(range, tr, startBoundary, endBoundary) {
|
|
728
|
+
const { depth, $from, $to } = range;
|
|
729
|
+
startBoundary = startBoundary || atStartBlockBoundary($from, depth + 1);
|
|
730
|
+
if (!startBoundary) {
|
|
731
|
+
const { startIndex, endIndex } = range;
|
|
732
|
+
if (endIndex - startIndex === 1) {
|
|
733
|
+
const contentRange = zoomInRange(range);
|
|
734
|
+
return contentRange ? indentRange(contentRange, tr) : false;
|
|
735
|
+
} else {
|
|
736
|
+
return splitAndIndentRange(range, tr, startIndex + 1);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
endBoundary = endBoundary || atEndBlockBoundary($to, depth + 1);
|
|
740
|
+
if (!endBoundary && !inCollapsedList($to)) {
|
|
741
|
+
const { startIndex, endIndex } = range;
|
|
742
|
+
if (endIndex - startIndex === 1) {
|
|
743
|
+
const contentRange = zoomInRange(range);
|
|
744
|
+
return contentRange ? indentRange(contentRange, tr) : false;
|
|
745
|
+
} else {
|
|
746
|
+
return splitAndIndentRange(range, tr, endIndex - 1);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
return indentNodeRange(range, tr);
|
|
750
|
+
}
|
|
751
|
+
function splitAndIndentRange(range, tr, splitIndex) {
|
|
752
|
+
const { $from, $to, depth } = range;
|
|
753
|
+
const splitPos = $from.posAtIndex(splitIndex, depth);
|
|
754
|
+
const range1 = $from.blockRange(tr.doc.resolve(splitPos - 1));
|
|
755
|
+
if (!range1)
|
|
756
|
+
return false;
|
|
757
|
+
const getRange2From = mapPos(tr, splitPos + 1);
|
|
758
|
+
const getRange2To = mapPos(tr, $to.pos);
|
|
759
|
+
indentRange(range1, tr, void 0, true);
|
|
760
|
+
const range2 = tr.doc.resolve(getRange2From()).blockRange(tr.doc.resolve(getRange2To()));
|
|
761
|
+
range2 && indentRange(range2, tr, true, void 0);
|
|
762
|
+
return true;
|
|
763
|
+
}
|
|
764
|
+
function indentNodeRange(range, tr) {
|
|
765
|
+
const listType = getListType(tr.doc.type.schema);
|
|
766
|
+
const { parent, startIndex } = range;
|
|
767
|
+
const prevChild = startIndex >= 1 && parent.child(startIndex - 1);
|
|
768
|
+
if (prevChild && isListNode(prevChild)) {
|
|
769
|
+
const { start, end } = range;
|
|
770
|
+
tr.step(
|
|
771
|
+
new ReplaceAroundStep(
|
|
772
|
+
start - 1,
|
|
773
|
+
end,
|
|
774
|
+
start,
|
|
775
|
+
end,
|
|
776
|
+
new Slice(Fragment.from(listType.create(null)), 1, 0),
|
|
777
|
+
0,
|
|
778
|
+
true
|
|
779
|
+
)
|
|
780
|
+
);
|
|
781
|
+
return true;
|
|
782
|
+
}
|
|
783
|
+
const isParentListNode = isListNode(parent);
|
|
784
|
+
const isFirstChildListNode = isListNode(parent.maybeChild(startIndex));
|
|
785
|
+
if (startIndex === 0 && isParentListNode || isFirstChildListNode) {
|
|
786
|
+
const { start, end } = range;
|
|
787
|
+
const listAttrs = isFirstChildListNode ? parent.child(startIndex).attrs : isParentListNode ? parent.attrs : null;
|
|
788
|
+
tr.step(
|
|
789
|
+
new ReplaceAroundStep(
|
|
790
|
+
start,
|
|
791
|
+
end,
|
|
792
|
+
start,
|
|
793
|
+
end,
|
|
794
|
+
new Slice(Fragment.from(listType.create(listAttrs)), 0, 0),
|
|
795
|
+
1,
|
|
796
|
+
true
|
|
797
|
+
)
|
|
798
|
+
);
|
|
799
|
+
return true;
|
|
800
|
+
}
|
|
801
|
+
return false;
|
|
802
|
+
}
|
|
803
|
+
function atTextblockStart(state, view) {
|
|
804
|
+
const { $cursor } = state.selection;
|
|
805
|
+
if (!$cursor || (view ? !view.endOfTextblock("backward", state) : $cursor.parentOffset > 0))
|
|
806
|
+
return null;
|
|
807
|
+
return $cursor;
|
|
808
|
+
}
|
|
809
|
+
function joinTextblocksAround(tr, $cut, dispatch) {
|
|
810
|
+
let before = $cut.nodeBefore, beforeText = before, beforePos = $cut.pos - 1;
|
|
811
|
+
for (; !beforeText.isTextblock; beforePos--) {
|
|
812
|
+
if (beforeText.type.spec.isolating)
|
|
813
|
+
return false;
|
|
814
|
+
let child = beforeText.lastChild;
|
|
815
|
+
if (!child)
|
|
816
|
+
return false;
|
|
817
|
+
beforeText = child;
|
|
818
|
+
}
|
|
819
|
+
let after = $cut.nodeAfter, afterText = after, afterPos = $cut.pos + 1;
|
|
820
|
+
for (; !afterText.isTextblock; afterPos++) {
|
|
821
|
+
if (afterText.type.spec.isolating)
|
|
822
|
+
return false;
|
|
823
|
+
let child = afterText.firstChild;
|
|
824
|
+
if (!child)
|
|
825
|
+
return false;
|
|
826
|
+
afterText = child;
|
|
827
|
+
}
|
|
828
|
+
let step = replaceStep(tr.doc, beforePos, afterPos, Slice.empty);
|
|
829
|
+
if (!step || step.from != beforePos || step instanceof ReplaceStep && step.slice.size >= afterPos - beforePos)
|
|
830
|
+
return false;
|
|
831
|
+
if (dispatch) {
|
|
832
|
+
tr.step(step);
|
|
833
|
+
tr.setSelection(TextSelection.create(tr.doc, beforePos));
|
|
834
|
+
dispatch(tr.scrollIntoView());
|
|
835
|
+
}
|
|
836
|
+
return true;
|
|
837
|
+
}
|
|
838
|
+
var joinCollapsedListBackward = (state, dispatch, view) => {
|
|
839
|
+
const $cursor = atTextblockStart(state, view);
|
|
840
|
+
if (!$cursor)
|
|
841
|
+
return false;
|
|
842
|
+
const $cut = findCutBefore($cursor);
|
|
843
|
+
if (!$cut)
|
|
844
|
+
return false;
|
|
845
|
+
const { nodeBefore, nodeAfter } = $cut;
|
|
846
|
+
if (nodeBefore && nodeAfter && isListNode(nodeBefore) && nodeBefore.attrs.collapsed && nodeAfter.isBlock) {
|
|
847
|
+
const tr = state.tr;
|
|
848
|
+
const listPos = $cut.pos - nodeBefore.nodeSize;
|
|
849
|
+
tr.delete($cut.pos, $cut.pos + nodeAfter.nodeSize);
|
|
850
|
+
const insert = listPos + 1 + nodeBefore.child(0).nodeSize;
|
|
851
|
+
tr.insert(insert, nodeAfter);
|
|
852
|
+
const $insert = tr.doc.resolve(insert);
|
|
853
|
+
tr.setSelection(TextSelection.near($insert));
|
|
854
|
+
if (joinTextblocksAround(tr, $insert, dispatch)) {
|
|
855
|
+
return true;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
return false;
|
|
859
|
+
};
|
|
860
|
+
function findCutBefore($pos) {
|
|
861
|
+
if (!$pos.parent.type.spec.isolating)
|
|
862
|
+
for (let i = $pos.depth - 1; i >= 0; i--) {
|
|
863
|
+
if ($pos.index(i) > 0)
|
|
864
|
+
return $pos.doc.resolve($pos.before(i + 1));
|
|
865
|
+
if ($pos.node(i).type.spec.isolating)
|
|
866
|
+
break;
|
|
867
|
+
}
|
|
868
|
+
return null;
|
|
869
|
+
}
|
|
870
|
+
var joinListUp = (state, dispatch, view) => {
|
|
871
|
+
const $cursor = atTextblockStart(state, view);
|
|
872
|
+
if (!$cursor)
|
|
873
|
+
return false;
|
|
874
|
+
const { depth } = $cursor;
|
|
875
|
+
if (depth < 2)
|
|
876
|
+
return false;
|
|
877
|
+
const listDepth = depth - 1;
|
|
878
|
+
const listNode = $cursor.node(listDepth);
|
|
879
|
+
if (!isListNode(listNode))
|
|
880
|
+
return false;
|
|
881
|
+
const indexInList = $cursor.index(listDepth);
|
|
882
|
+
if (indexInList === 0) {
|
|
883
|
+
if (dispatch) {
|
|
884
|
+
liftListContent(state, dispatch, $cursor);
|
|
885
|
+
}
|
|
886
|
+
return true;
|
|
887
|
+
}
|
|
888
|
+
if (indexInList === listNode.childCount - 1) {
|
|
889
|
+
if (dispatch) {
|
|
890
|
+
liftParent(state, dispatch, $cursor);
|
|
891
|
+
}
|
|
892
|
+
return true;
|
|
893
|
+
}
|
|
894
|
+
return false;
|
|
895
|
+
};
|
|
896
|
+
function liftListContent(state, dispatch, $cursor) {
|
|
897
|
+
const tr = state.tr;
|
|
898
|
+
const listDepth = $cursor.depth - 1;
|
|
899
|
+
const range = new NodeRange(
|
|
900
|
+
$cursor,
|
|
901
|
+
tr.doc.resolve($cursor.end(listDepth)),
|
|
902
|
+
listDepth
|
|
903
|
+
);
|
|
904
|
+
if (safeLift(tr, range)) {
|
|
905
|
+
dispatch(tr);
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
function liftParent(state, dispatch, $cursor) {
|
|
909
|
+
const tr = state.tr;
|
|
910
|
+
const range = $cursor.blockRange();
|
|
911
|
+
if (range && safeLift(tr, range)) {
|
|
912
|
+
dispatch(tr);
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
var protectCollapsed = (state, dispatch) => {
|
|
916
|
+
const tr = state.tr;
|
|
917
|
+
let found = false;
|
|
918
|
+
const { from, to } = state.selection;
|
|
919
|
+
state.doc.nodesBetween(from, to, (node, pos, parent, index) => {
|
|
920
|
+
if (found && !dispatch) {
|
|
921
|
+
return false;
|
|
922
|
+
}
|
|
923
|
+
if (parent && isCollapsedListNode(parent) && index >= 1) {
|
|
924
|
+
found = true;
|
|
925
|
+
if (!dispatch) {
|
|
926
|
+
return false;
|
|
927
|
+
}
|
|
928
|
+
const $pos = state.doc.resolve(pos);
|
|
929
|
+
tr.setNodeAttribute($pos.before($pos.depth), "collapsed", false);
|
|
930
|
+
}
|
|
931
|
+
});
|
|
932
|
+
if (found) {
|
|
933
|
+
dispatch == null ? void 0 : dispatch(tr);
|
|
934
|
+
}
|
|
935
|
+
return found;
|
|
936
|
+
};
|
|
937
|
+
function createAndFill(type, attrs, content, marks) {
|
|
938
|
+
const node = type.createAndFill(attrs, content, marks);
|
|
939
|
+
if (!node) {
|
|
940
|
+
throw new RangeError(`Failed to create '${type.name}' node`);
|
|
941
|
+
}
|
|
942
|
+
node.check();
|
|
943
|
+
return node;
|
|
944
|
+
}
|
|
945
|
+
function isBlockNodeSelection(selection) {
|
|
946
|
+
var _a, _b;
|
|
947
|
+
return Boolean((_b = (_a = selection.node) == null ? void 0 : _a.type) == null ? void 0 : _b.isBlock);
|
|
948
|
+
}
|
|
949
|
+
function createSplitListCommand() {
|
|
950
|
+
const splitListCommand = (state, dispatch) => {
|
|
951
|
+
const { selection } = state;
|
|
952
|
+
const { $from, $to } = selection;
|
|
953
|
+
if (isBlockNodeSelection(selection)) {
|
|
954
|
+
return false;
|
|
955
|
+
}
|
|
956
|
+
if (!$from.sameParent($to)) {
|
|
957
|
+
return false;
|
|
958
|
+
}
|
|
959
|
+
if ($from.depth < 2) {
|
|
960
|
+
return false;
|
|
961
|
+
}
|
|
962
|
+
const listDepth = $from.depth - 1;
|
|
963
|
+
const listNode = $from.node(listDepth);
|
|
964
|
+
if (!isListNode(listNode)) {
|
|
965
|
+
return false;
|
|
966
|
+
}
|
|
967
|
+
const parent = $from.parent;
|
|
968
|
+
const indexInList = $from.index(listDepth);
|
|
969
|
+
const parentEmpty = parent.content.size === 0;
|
|
970
|
+
if (indexInList === 0) {
|
|
971
|
+
if (parentEmpty) {
|
|
972
|
+
const $listEnd = state.doc.resolve($from.end(listDepth));
|
|
973
|
+
const listParentDepth = listDepth - 1;
|
|
974
|
+
const listParent = $from.node(listParentDepth);
|
|
975
|
+
const indexInListParent = $from.index(listParentDepth);
|
|
976
|
+
const isLastChildInListParent = indexInListParent === listParent.childCount - 1;
|
|
977
|
+
const range = isLastChildInListParent ? new NodeRange($from, $listEnd, listParentDepth) : new NodeRange($from, $listEnd, listDepth);
|
|
978
|
+
const tr = state.tr;
|
|
979
|
+
if (range && dedentNodeRange(range, tr)) {
|
|
980
|
+
dispatch == null ? void 0 : dispatch(tr);
|
|
981
|
+
return true;
|
|
982
|
+
}
|
|
983
|
+
return false;
|
|
984
|
+
} else {
|
|
985
|
+
return doSplitList(state, listNode, dispatch);
|
|
986
|
+
}
|
|
987
|
+
} else {
|
|
988
|
+
if (parentEmpty) {
|
|
989
|
+
return enterWithoutLift(state, dispatch);
|
|
990
|
+
} else {
|
|
991
|
+
return false;
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
};
|
|
995
|
+
return withAutoFixList(splitListCommand);
|
|
996
|
+
}
|
|
997
|
+
function doSplitList(state, listNode, dispatch) {
|
|
998
|
+
const tr = state.tr;
|
|
999
|
+
const listType = listNode.type;
|
|
1000
|
+
const attrs = listNode.attrs;
|
|
1001
|
+
const newAttrs = { kind: attrs.kind };
|
|
1002
|
+
tr.delete(tr.selection.from, tr.selection.to);
|
|
1003
|
+
const { $from, $to } = tr.selection;
|
|
1004
|
+
const { parentOffset } = $to;
|
|
1005
|
+
const atStart = parentOffset == 0;
|
|
1006
|
+
const atEnd = parentOffset == $to.parent.content.size;
|
|
1007
|
+
if (atStart) {
|
|
1008
|
+
if (dispatch) {
|
|
1009
|
+
const pos = $from.before(-1);
|
|
1010
|
+
tr.insert(pos, createAndFill(listType, newAttrs));
|
|
1011
|
+
dispatch(tr.scrollIntoView());
|
|
1012
|
+
}
|
|
1013
|
+
return true;
|
|
1014
|
+
}
|
|
1015
|
+
if (atEnd && attrs.collapsed) {
|
|
1016
|
+
if (dispatch) {
|
|
1017
|
+
const pos = $from.after(-1);
|
|
1018
|
+
tr.insert(pos, createAndFill(listType, newAttrs));
|
|
1019
|
+
tr.setSelection(Selection.near(tr.doc.resolve(pos)));
|
|
1020
|
+
dispatch(tr.scrollIntoView());
|
|
1021
|
+
}
|
|
1022
|
+
return true;
|
|
1023
|
+
}
|
|
1024
|
+
const nextType = atEnd ? listNode.contentMatchAt(0).defaultType : void 0;
|
|
1025
|
+
const typesAfter = [
|
|
1026
|
+
{ type: listType, attrs: newAttrs },
|
|
1027
|
+
nextType ? { type: nextType } : null
|
|
1028
|
+
];
|
|
1029
|
+
if (!canSplit(tr.doc, $from.pos, 2, typesAfter)) {
|
|
1030
|
+
return false;
|
|
1031
|
+
}
|
|
1032
|
+
dispatch == null ? void 0 : dispatch(tr.split($from.pos, 2, typesAfter).scrollIntoView());
|
|
1033
|
+
return true;
|
|
1034
|
+
}
|
|
1035
|
+
var enterCommand = chainCommands(
|
|
1036
|
+
protectCollapsed,
|
|
1037
|
+
createSplitListCommand()
|
|
1038
|
+
);
|
|
1039
|
+
var backspaceCommand = chainCommands(
|
|
1040
|
+
protectCollapsed,
|
|
1041
|
+
deleteSelection,
|
|
1042
|
+
joinListUp,
|
|
1043
|
+
joinCollapsedListBackward,
|
|
1044
|
+
joinTextblockBackward,
|
|
1045
|
+
selectNodeBackward
|
|
1046
|
+
);
|
|
1047
|
+
var deleteCommand = chainCommands(
|
|
1048
|
+
protectCollapsed,
|
|
1049
|
+
deleteSelection,
|
|
1050
|
+
joinTextblockForward,
|
|
1051
|
+
selectNodeForward
|
|
1052
|
+
);
|
|
1053
|
+
var listKeymap = {
|
|
1054
|
+
Enter: enterCommand,
|
|
1055
|
+
Backspace: backspaceCommand,
|
|
1056
|
+
Delete: deleteCommand,
|
|
1057
|
+
"Mod-[": createDedentListCommand(),
|
|
1058
|
+
"Mod-]": createIndentListCommand()
|
|
1059
|
+
};
|
|
1060
|
+
function handleListMarkerMouseDown({
|
|
1061
|
+
view,
|
|
1062
|
+
event,
|
|
1063
|
+
onListClick = defaultListClickHandler
|
|
1064
|
+
}) {
|
|
1065
|
+
const target = event.target;
|
|
1066
|
+
if (target == null ? void 0 : target.closest(".list-marker-click-target")) {
|
|
1067
|
+
event.preventDefault();
|
|
1068
|
+
const pos = view.posAtDOM(target, -10, -10);
|
|
1069
|
+
return handleMouseDown(pos, onListClick)(view.state, view.dispatch);
|
|
1070
|
+
}
|
|
1071
|
+
return false;
|
|
1072
|
+
}
|
|
1073
|
+
function handleMouseDown(pos, onListClick) {
|
|
1074
|
+
const mouseDown = (state, dispatch) => {
|
|
1075
|
+
const tr = state.tr;
|
|
1076
|
+
const $pos = tr.doc.resolve(pos);
|
|
1077
|
+
const list = $pos.parent;
|
|
1078
|
+
if (!isListNode(list)) {
|
|
1079
|
+
return false;
|
|
1080
|
+
}
|
|
1081
|
+
const listPos = $pos.before($pos.depth);
|
|
1082
|
+
const attrs = onListClick(list);
|
|
1083
|
+
if (setNodeAttributes(tr, listPos, list.attrs, attrs)) {
|
|
1084
|
+
dispatch == null ? void 0 : dispatch(tr);
|
|
1085
|
+
}
|
|
1086
|
+
return true;
|
|
1087
|
+
};
|
|
1088
|
+
return withSafeSelection(mouseDown);
|
|
1089
|
+
}
|
|
1090
|
+
var defaultListClickHandler = (node) => {
|
|
1091
|
+
const attrs = node.attrs;
|
|
1092
|
+
if (attrs.kind === "task") {
|
|
1093
|
+
return { ...attrs, checked: !attrs.checked };
|
|
1094
|
+
} else if (attrs.kind === "toggle") {
|
|
1095
|
+
return { ...attrs, collapsed: !attrs.collapsed };
|
|
1096
|
+
} else {
|
|
1097
|
+
return attrs;
|
|
1098
|
+
}
|
|
1099
|
+
};
|
|
1100
|
+
function wrappingListInputRule(regexp, getAttrs) {
|
|
1101
|
+
return new InputRule(
|
|
1102
|
+
regexp,
|
|
1103
|
+
(state, match, start, end) => {
|
|
1104
|
+
const tr = state.tr;
|
|
1105
|
+
tr.deleteRange(start, end);
|
|
1106
|
+
const attrs = typeof getAttrs === "function" ? getAttrs(match) : getAttrs;
|
|
1107
|
+
const $pos = tr.selection.$from;
|
|
1108
|
+
const listNode = $pos.index(-1) === 0 && $pos.node(-1);
|
|
1109
|
+
if (listNode && isListNode(listNode)) {
|
|
1110
|
+
const oldAttrs = listNode.attrs;
|
|
1111
|
+
const newAttrs = { ...oldAttrs, ...attrs };
|
|
1112
|
+
const needUpdate = Object.keys(newAttrs).some(
|
|
1113
|
+
(key) => newAttrs[key] !== oldAttrs[key]
|
|
1114
|
+
);
|
|
1115
|
+
if (needUpdate) {
|
|
1116
|
+
return tr.setNodeMarkup($pos.before(-1), void 0, newAttrs);
|
|
1117
|
+
} else {
|
|
1118
|
+
return null;
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
const $start = tr.doc.resolve(start);
|
|
1122
|
+
const range = $start.blockRange();
|
|
1123
|
+
if (!range) {
|
|
1124
|
+
return null;
|
|
1125
|
+
}
|
|
1126
|
+
const wrapping = findWrapping(range, getListType(state.schema), attrs);
|
|
1127
|
+
if (!wrapping) {
|
|
1128
|
+
return null;
|
|
1129
|
+
}
|
|
1130
|
+
return tr.wrap(range, wrapping);
|
|
1131
|
+
}
|
|
1132
|
+
);
|
|
1133
|
+
}
|
|
1134
|
+
var listInputRules = [
|
|
1135
|
+
wrappingListInputRule(/^\s?([*-])\s$/, {
|
|
1136
|
+
kind: "bullet",
|
|
1137
|
+
collapsed: false
|
|
1138
|
+
}),
|
|
1139
|
+
wrappingListInputRule(/^\s?(\d+)\.\s$/, (match) => {
|
|
1140
|
+
const order = parseInteger(match[1]);
|
|
1141
|
+
return {
|
|
1142
|
+
kind: "ordered",
|
|
1143
|
+
collapsed: false,
|
|
1144
|
+
order: order != null && order >= 2 ? order : null
|
|
1145
|
+
};
|
|
1146
|
+
}),
|
|
1147
|
+
wrappingListInputRule(/^\s?\[([\sXx]?)]\s$/, (match) => {
|
|
1148
|
+
return {
|
|
1149
|
+
kind: "task",
|
|
1150
|
+
checked: ["x", "X"].includes(match[1]),
|
|
1151
|
+
collapsed: false
|
|
1152
|
+
};
|
|
1153
|
+
}),
|
|
1154
|
+
wrappingListInputRule(/^\s?>>\s$/, {
|
|
1155
|
+
kind: "toggle"
|
|
1156
|
+
})
|
|
1157
|
+
];
|
|
1158
|
+
var createListNodeView = (node) => {
|
|
1159
|
+
var _a, _b;
|
|
1160
|
+
let prevNode = node;
|
|
1161
|
+
const prevNested = ((_a = node.firstChild) == null ? void 0 : _a.type) === node.type;
|
|
1162
|
+
const prevSingleChild = node.childCount === 1;
|
|
1163
|
+
const spec = node.type.spec.toDOM(node);
|
|
1164
|
+
const { dom, contentDOM } = DOMSerializer.renderSpec(document, spec);
|
|
1165
|
+
if (safari && node.attrs.kind === "toggle") {
|
|
1166
|
+
;
|
|
1167
|
+
(_b = dom.querySelector(".list-marker-click-target")) == null ? void 0 : _b.appendChild(document.createElement("span"));
|
|
1168
|
+
}
|
|
1169
|
+
const update = (node2) => {
|
|
1170
|
+
var _a2;
|
|
1171
|
+
if (!node2.sameMarkup(prevNode))
|
|
1172
|
+
return false;
|
|
1173
|
+
const nested = ((_a2 = node2.firstChild) == null ? void 0 : _a2.type) === node2.type;
|
|
1174
|
+
const singleChild = node2.childCount === 1;
|
|
1175
|
+
if (prevNested !== nested || prevSingleChild !== singleChild)
|
|
1176
|
+
return false;
|
|
1177
|
+
prevNode = node2;
|
|
1178
|
+
return true;
|
|
1179
|
+
};
|
|
1180
|
+
return { dom, contentDOM, update };
|
|
1181
|
+
};
|
|
1182
|
+
var ListDOMSerializer = class extends DOMSerializer {
|
|
1183
|
+
static nodesFromSchema(schema) {
|
|
1184
|
+
const nodes = DOMSerializer.nodesFromSchema(schema);
|
|
1185
|
+
return {
|
|
1186
|
+
...nodes,
|
|
1187
|
+
list: (node) => listToDOM({ node, nativeList: true, getMarkers: () => null })
|
|
1188
|
+
};
|
|
1189
|
+
}
|
|
1190
|
+
static fromSchema(schema) {
|
|
1191
|
+
return schema.cached.listDomSerializer || (schema.cached.listDomSerializer = new ListDOMSerializer(
|
|
1192
|
+
this.nodesFromSchema(schema),
|
|
1193
|
+
this.marksFromSchema(schema)
|
|
1194
|
+
));
|
|
1195
|
+
}
|
|
1196
|
+
serializeFragment(fragment, options, target) {
|
|
1197
|
+
const dom = super.serializeFragment(fragment, options, target);
|
|
1198
|
+
return joinListElements(dom);
|
|
1199
|
+
}
|
|
1200
|
+
};
|
|
1201
|
+
function joinListElements(parent) {
|
|
1202
|
+
for (let i = 0; i < parent.childNodes.length; i++) {
|
|
1203
|
+
const child = parent.children.item(i);
|
|
1204
|
+
if (!child)
|
|
1205
|
+
continue;
|
|
1206
|
+
if (child.tagName === "UL" || child.tagName === "OL") {
|
|
1207
|
+
let next = null;
|
|
1208
|
+
while (next = child.nextElementSibling, (next == null ? void 0 : next.tagName) === child.tagName) {
|
|
1209
|
+
child.append(...Array.from(next.children));
|
|
1210
|
+
next.remove();
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
joinListElements(child);
|
|
1214
|
+
}
|
|
1215
|
+
return parent;
|
|
1216
|
+
}
|
|
1217
|
+
function unwrapListSlice(slice) {
|
|
1218
|
+
while (slice.openStart >= 2 && slice.openEnd >= 2 && slice.content.childCount === 1 && isListNode(slice.content.child(0))) {
|
|
1219
|
+
slice = new Slice(
|
|
1220
|
+
slice.content.child(0).content,
|
|
1221
|
+
slice.openStart - 1,
|
|
1222
|
+
slice.openEnd - 1
|
|
1223
|
+
);
|
|
1224
|
+
}
|
|
1225
|
+
return slice;
|
|
1226
|
+
}
|
|
1227
|
+
function createListClipboardPlugin(schema) {
|
|
1228
|
+
return new Plugin({
|
|
1229
|
+
props: {
|
|
1230
|
+
clipboardSerializer: ListDOMSerializer.fromSchema(schema),
|
|
1231
|
+
transformCopied: unwrapListSlice
|
|
1232
|
+
}
|
|
1233
|
+
});
|
|
1234
|
+
}
|
|
1235
|
+
function createListEventPlugin() {
|
|
1236
|
+
return new Plugin({
|
|
1237
|
+
props: {
|
|
1238
|
+
handleDOMEvents: {
|
|
1239
|
+
mousedown: (view, event) => handleListMarkerMouseDown({ view, event })
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
});
|
|
1243
|
+
}
|
|
1244
|
+
function createListRenderingPlugin() {
|
|
1245
|
+
return new Plugin({
|
|
1246
|
+
props: {
|
|
1247
|
+
nodeViews: {
|
|
1248
|
+
list: createListNodeView
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
});
|
|
1252
|
+
}
|
|
1253
|
+
function createSafariInputMethodWorkaroundPlugin() {
|
|
1254
|
+
let view = null;
|
|
1255
|
+
let span = null;
|
|
1256
|
+
const getSpan = () => {
|
|
1257
|
+
if (!span) {
|
|
1258
|
+
span = document.createElement("span");
|
|
1259
|
+
span.className = "prosemirror-flat-list-safari-workaround";
|
|
1260
|
+
}
|
|
1261
|
+
return span;
|
|
1262
|
+
};
|
|
1263
|
+
const createDecorations = () => {
|
|
1264
|
+
if (view == null ? void 0 : view.composing) {
|
|
1265
|
+
const state = view.state;
|
|
1266
|
+
const selection = state.selection;
|
|
1267
|
+
const { $from, $to, to } = selection;
|
|
1268
|
+
if ($from.sameParent($to)) {
|
|
1269
|
+
return DecorationSet.create(state.doc, [Decoration.widget(to, getSpan)]);
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
return null;
|
|
1273
|
+
};
|
|
1274
|
+
return new Plugin({
|
|
1275
|
+
props: {
|
|
1276
|
+
decorations: safari ? createDecorations : void 0
|
|
1277
|
+
},
|
|
1278
|
+
view: (v) => {
|
|
1279
|
+
view = v;
|
|
1280
|
+
return {};
|
|
1281
|
+
}
|
|
1282
|
+
});
|
|
1283
|
+
}
|
|
1284
|
+
function createListPlugins({ schema }) {
|
|
1285
|
+
return [
|
|
1286
|
+
createListEventPlugin(),
|
|
1287
|
+
createListRenderingPlugin(),
|
|
1288
|
+
createListClipboardPlugin(schema),
|
|
1289
|
+
createSafariInputMethodWorkaroundPlugin()
|
|
1290
|
+
];
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
// ../extension-list/src/index.ts
|
|
1294
|
+
function addListSpec() {
|
|
1295
|
+
return addNodeSpec({ name: "list", spec: createListSpec() });
|
|
1296
|
+
}
|
|
1297
|
+
function addListPlugins() {
|
|
1298
|
+
return addPlugin({ plugins: ({ schema }) => createListPlugins({ schema }) });
|
|
1299
|
+
}
|
|
1300
|
+
function addListKeymap() {
|
|
1301
|
+
return addKeymap(listKeymap);
|
|
1302
|
+
}
|
|
1303
|
+
function addListInputRules() {
|
|
1304
|
+
return addInputRule(() => listInputRules);
|
|
1305
|
+
}
|
|
1306
|
+
function addList() {
|
|
1307
|
+
return defineExtension([
|
|
1308
|
+
addListSpec(),
|
|
1309
|
+
addListPlugins(),
|
|
1310
|
+
addListKeymap(),
|
|
1311
|
+
addListInputRules()
|
|
1312
|
+
]);
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
export {
|
|
1316
|
+
addListSpec,
|
|
1317
|
+
addListPlugins,
|
|
1318
|
+
addListKeymap,
|
|
1319
|
+
addListInputRules,
|
|
1320
|
+
addList
|
|
1321
|
+
};
|