@liveblocks/node-prosemirror 0.0.1 → 2.11.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.js ADDED
@@ -0,0 +1,3228 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }// src/index.ts
2
+ var _core = require('@liveblocks/core');
3
+
4
+ // src/version.ts
5
+ var PKG_NAME = "@liveblocks/node-prosemirror";
6
+ var PKG_VERSION = "2.11.1";
7
+ var PKG_FORMAT = "cjs";
8
+
9
+ // ../../node_modules/@tiptap/core/dist/index.js
10
+ var _state = require('@tiptap/pm/state');
11
+ var _view2 = require('@tiptap/pm/view');
12
+ var _keymap = require('@tiptap/pm/keymap');
13
+ var _model = require('@tiptap/pm/model');
14
+ var _transform = require('@tiptap/pm/transform');
15
+ var _commands = require('@tiptap/pm/commands');
16
+ var _schemalist = require('@tiptap/pm/schema-list');
17
+ function createChainableState(config) {
18
+ const { state, transaction } = config;
19
+ let { selection } = transaction;
20
+ let { doc } = transaction;
21
+ let { storedMarks } = transaction;
22
+ return {
23
+ ...state,
24
+ apply: state.apply.bind(state),
25
+ applyTransaction: state.applyTransaction.bind(state),
26
+ plugins: state.plugins,
27
+ schema: state.schema,
28
+ reconfigure: state.reconfigure.bind(state),
29
+ toJSON: state.toJSON.bind(state),
30
+ get storedMarks() {
31
+ return storedMarks;
32
+ },
33
+ get selection() {
34
+ return selection;
35
+ },
36
+ get doc() {
37
+ return doc;
38
+ },
39
+ get tr() {
40
+ selection = transaction.selection;
41
+ doc = transaction.doc;
42
+ storedMarks = transaction.storedMarks;
43
+ return transaction;
44
+ }
45
+ };
46
+ }
47
+ var CommandManager = class {
48
+ constructor(props) {
49
+ this.editor = props.editor;
50
+ this.rawCommands = this.editor.extensionManager.commands;
51
+ this.customState = props.state;
52
+ }
53
+ get hasCustomState() {
54
+ return !!this.customState;
55
+ }
56
+ get state() {
57
+ return this.customState || this.editor.state;
58
+ }
59
+ get commands() {
60
+ const { rawCommands, editor, state } = this;
61
+ const { view } = editor;
62
+ const { tr } = state;
63
+ const props = this.buildProps(tr);
64
+ return Object.fromEntries(Object.entries(rawCommands).map(([name, command2]) => {
65
+ const method = (...args) => {
66
+ const callback = command2(...args)(props);
67
+ if (!tr.getMeta("preventDispatch") && !this.hasCustomState) {
68
+ view.dispatch(tr);
69
+ }
70
+ return callback;
71
+ };
72
+ return [name, method];
73
+ }));
74
+ }
75
+ get chain() {
76
+ return () => this.createChain();
77
+ }
78
+ get can() {
79
+ return () => this.createCan();
80
+ }
81
+ createChain(startTr, shouldDispatch = true) {
82
+ const { rawCommands, editor, state } = this;
83
+ const { view } = editor;
84
+ const callbacks = [];
85
+ const hasStartTransaction = !!startTr;
86
+ const tr = startTr || state.tr;
87
+ const run2 = () => {
88
+ if (!hasStartTransaction && shouldDispatch && !tr.getMeta("preventDispatch") && !this.hasCustomState) {
89
+ view.dispatch(tr);
90
+ }
91
+ return callbacks.every((callback) => callback === true);
92
+ };
93
+ const chain = {
94
+ ...Object.fromEntries(Object.entries(rawCommands).map(([name, command2]) => {
95
+ const chainedCommand = (...args) => {
96
+ const props = this.buildProps(tr, shouldDispatch);
97
+ const callback = command2(...args)(props);
98
+ callbacks.push(callback);
99
+ return chain;
100
+ };
101
+ return [name, chainedCommand];
102
+ })),
103
+ run: run2
104
+ };
105
+ return chain;
106
+ }
107
+ createCan(startTr) {
108
+ const { rawCommands, state } = this;
109
+ const dispatch = false;
110
+ const tr = startTr || state.tr;
111
+ const props = this.buildProps(tr, dispatch);
112
+ const formattedCommands = Object.fromEntries(Object.entries(rawCommands).map(([name, command2]) => {
113
+ return [name, (...args) => command2(...args)({ ...props, dispatch: void 0 })];
114
+ }));
115
+ return {
116
+ ...formattedCommands,
117
+ chain: () => this.createChain(tr, dispatch)
118
+ };
119
+ }
120
+ buildProps(tr, shouldDispatch = true) {
121
+ const { rawCommands, editor, state } = this;
122
+ const { view } = editor;
123
+ const props = {
124
+ tr,
125
+ editor,
126
+ view,
127
+ state: createChainableState({
128
+ state,
129
+ transaction: tr
130
+ }),
131
+ dispatch: shouldDispatch ? () => void 0 : void 0,
132
+ chain: () => this.createChain(tr, shouldDispatch),
133
+ can: () => this.createCan(tr),
134
+ get commands() {
135
+ return Object.fromEntries(Object.entries(rawCommands).map(([name, command2]) => {
136
+ return [name, (...args) => command2(...args)(props)];
137
+ }));
138
+ }
139
+ };
140
+ return props;
141
+ }
142
+ };
143
+ function getExtensionField(extension, field, context) {
144
+ if (extension.config[field] === void 0 && extension.parent) {
145
+ return getExtensionField(extension.parent, field, context);
146
+ }
147
+ if (typeof extension.config[field] === "function") {
148
+ const value = extension.config[field].bind({
149
+ ...context,
150
+ parent: extension.parent ? getExtensionField(extension.parent, field, context) : null
151
+ });
152
+ return value;
153
+ }
154
+ return extension.config[field];
155
+ }
156
+ function splitExtensions(extensions) {
157
+ const baseExtensions = extensions.filter((extension) => extension.type === "extension");
158
+ const nodeExtensions = extensions.filter((extension) => extension.type === "node");
159
+ const markExtensions = extensions.filter((extension) => extension.type === "mark");
160
+ return {
161
+ baseExtensions,
162
+ nodeExtensions,
163
+ markExtensions
164
+ };
165
+ }
166
+ function getAttributesFromExtensions(extensions) {
167
+ const extensionAttributes = [];
168
+ const { nodeExtensions, markExtensions } = splitExtensions(extensions);
169
+ const nodeAndMarkExtensions = [...nodeExtensions, ...markExtensions];
170
+ const defaultAttribute = {
171
+ default: null,
172
+ rendered: true,
173
+ renderHTML: null,
174
+ parseHTML: null,
175
+ keepOnSplit: true,
176
+ isRequired: false
177
+ };
178
+ extensions.forEach((extension) => {
179
+ const context = {
180
+ name: extension.name,
181
+ options: extension.options,
182
+ storage: extension.storage,
183
+ extensions: nodeAndMarkExtensions
184
+ };
185
+ const addGlobalAttributes = getExtensionField(extension, "addGlobalAttributes", context);
186
+ if (!addGlobalAttributes) {
187
+ return;
188
+ }
189
+ const globalAttributes = addGlobalAttributes();
190
+ globalAttributes.forEach((globalAttribute) => {
191
+ globalAttribute.types.forEach((type) => {
192
+ Object.entries(globalAttribute.attributes).forEach(([name, attribute]) => {
193
+ extensionAttributes.push({
194
+ type,
195
+ name,
196
+ attribute: {
197
+ ...defaultAttribute,
198
+ ...attribute
199
+ }
200
+ });
201
+ });
202
+ });
203
+ });
204
+ });
205
+ nodeAndMarkExtensions.forEach((extension) => {
206
+ const context = {
207
+ name: extension.name,
208
+ options: extension.options,
209
+ storage: extension.storage
210
+ };
211
+ const addAttributes = getExtensionField(extension, "addAttributes", context);
212
+ if (!addAttributes) {
213
+ return;
214
+ }
215
+ const attributes = addAttributes();
216
+ Object.entries(attributes).forEach(([name, attribute]) => {
217
+ const mergedAttr = {
218
+ ...defaultAttribute,
219
+ ...attribute
220
+ };
221
+ if (typeof (mergedAttr === null || mergedAttr === void 0 ? void 0 : mergedAttr.default) === "function") {
222
+ mergedAttr.default = mergedAttr.default();
223
+ }
224
+ if ((mergedAttr === null || mergedAttr === void 0 ? void 0 : mergedAttr.isRequired) && (mergedAttr === null || mergedAttr === void 0 ? void 0 : mergedAttr.default) === void 0) {
225
+ delete mergedAttr.default;
226
+ }
227
+ extensionAttributes.push({
228
+ type: extension.name,
229
+ name,
230
+ attribute: mergedAttr
231
+ });
232
+ });
233
+ });
234
+ return extensionAttributes;
235
+ }
236
+ function getNodeType(nameOrType, schema) {
237
+ if (typeof nameOrType === "string") {
238
+ if (!schema.nodes[nameOrType]) {
239
+ throw Error(`There is no node type named '${nameOrType}'. Maybe you forgot to add the extension?`);
240
+ }
241
+ return schema.nodes[nameOrType];
242
+ }
243
+ return nameOrType;
244
+ }
245
+ function mergeAttributes(...objects) {
246
+ return objects.filter((item) => !!item).reduce((items, item) => {
247
+ const mergedAttributes = { ...items };
248
+ Object.entries(item).forEach(([key, value]) => {
249
+ const exists = mergedAttributes[key];
250
+ if (!exists) {
251
+ mergedAttributes[key] = value;
252
+ return;
253
+ }
254
+ if (key === "class") {
255
+ const valueClasses = value ? value.split(" ") : [];
256
+ const existingClasses = mergedAttributes[key] ? mergedAttributes[key].split(" ") : [];
257
+ const insertClasses = valueClasses.filter((valueClass) => !existingClasses.includes(valueClass));
258
+ mergedAttributes[key] = [...existingClasses, ...insertClasses].join(" ");
259
+ } else if (key === "style") {
260
+ const newStyles = value ? value.split(";").map((style) => style.trim()).filter(Boolean) : [];
261
+ const existingStyles = mergedAttributes[key] ? mergedAttributes[key].split(";").map((style) => style.trim()).filter(Boolean) : [];
262
+ const styleMap = /* @__PURE__ */ new Map();
263
+ existingStyles.forEach((style) => {
264
+ const [property, val] = style.split(":").map((part) => part.trim());
265
+ styleMap.set(property, val);
266
+ });
267
+ newStyles.forEach((style) => {
268
+ const [property, val] = style.split(":").map((part) => part.trim());
269
+ styleMap.set(property, val);
270
+ });
271
+ mergedAttributes[key] = Array.from(styleMap.entries()).map(([property, val]) => `${property}: ${val}`).join("; ");
272
+ } else {
273
+ mergedAttributes[key] = value;
274
+ }
275
+ });
276
+ return mergedAttributes;
277
+ }, {});
278
+ }
279
+ function getRenderedAttributes(nodeOrMark, extensionAttributes) {
280
+ return extensionAttributes.filter((attribute) => attribute.type === nodeOrMark.type.name).filter((item) => item.attribute.rendered).map((item) => {
281
+ if (!item.attribute.renderHTML) {
282
+ return {
283
+ [item.name]: nodeOrMark.attrs[item.name]
284
+ };
285
+ }
286
+ return item.attribute.renderHTML(nodeOrMark.attrs) || {};
287
+ }).reduce((attributes, attribute) => mergeAttributes(attributes, attribute), {});
288
+ }
289
+ function isFunction(value) {
290
+ return typeof value === "function";
291
+ }
292
+ function callOrReturn(value, context = void 0, ...props) {
293
+ if (isFunction(value)) {
294
+ if (context) {
295
+ return value.bind(context)(...props);
296
+ }
297
+ return value(...props);
298
+ }
299
+ return value;
300
+ }
301
+ function isEmptyObject(value = {}) {
302
+ return Object.keys(value).length === 0 && value.constructor === Object;
303
+ }
304
+ function fromString(value) {
305
+ if (typeof value !== "string") {
306
+ return value;
307
+ }
308
+ if (value.match(/^[+-]?(?:\d*\.)?\d+$/)) {
309
+ return Number(value);
310
+ }
311
+ if (value === "true") {
312
+ return true;
313
+ }
314
+ if (value === "false") {
315
+ return false;
316
+ }
317
+ return value;
318
+ }
319
+ function injectExtensionAttributesToParseRule(parseRule, extensionAttributes) {
320
+ if ("style" in parseRule) {
321
+ return parseRule;
322
+ }
323
+ return {
324
+ ...parseRule,
325
+ getAttrs: (node) => {
326
+ const oldAttributes = parseRule.getAttrs ? parseRule.getAttrs(node) : parseRule.attrs;
327
+ if (oldAttributes === false) {
328
+ return false;
329
+ }
330
+ const newAttributes = extensionAttributes.reduce((items, item) => {
331
+ const value = item.attribute.parseHTML ? item.attribute.parseHTML(node) : fromString(node.getAttribute(item.name));
332
+ if (value === null || value === void 0) {
333
+ return items;
334
+ }
335
+ return {
336
+ ...items,
337
+ [item.name]: value
338
+ };
339
+ }, {});
340
+ return { ...oldAttributes, ...newAttributes };
341
+ }
342
+ };
343
+ }
344
+ function cleanUpSchemaItem(data) {
345
+ return Object.fromEntries(
346
+ // @ts-ignore
347
+ Object.entries(data).filter(([key, value]) => {
348
+ if (key === "attrs" && isEmptyObject(value)) {
349
+ return false;
350
+ }
351
+ return value !== null && value !== void 0;
352
+ })
353
+ );
354
+ }
355
+ function getSchemaByResolvedExtensions(extensions, editor) {
356
+ var _a;
357
+ const allAttributes = getAttributesFromExtensions(extensions);
358
+ const { nodeExtensions, markExtensions } = splitExtensions(extensions);
359
+ const topNode = (_a = nodeExtensions.find((extension) => getExtensionField(extension, "topNode"))) === null || _a === void 0 ? void 0 : _a.name;
360
+ const nodes = Object.fromEntries(nodeExtensions.map((extension) => {
361
+ const extensionAttributes = allAttributes.filter((attribute) => attribute.type === extension.name);
362
+ const context = {
363
+ name: extension.name,
364
+ options: extension.options,
365
+ storage: extension.storage,
366
+ editor
367
+ };
368
+ const extraNodeFields = extensions.reduce((fields, e) => {
369
+ const extendNodeSchema = getExtensionField(e, "extendNodeSchema", context);
370
+ return {
371
+ ...fields,
372
+ ...extendNodeSchema ? extendNodeSchema(extension) : {}
373
+ };
374
+ }, {});
375
+ const schema = cleanUpSchemaItem({
376
+ ...extraNodeFields,
377
+ content: callOrReturn(getExtensionField(extension, "content", context)),
378
+ marks: callOrReturn(getExtensionField(extension, "marks", context)),
379
+ group: callOrReturn(getExtensionField(extension, "group", context)),
380
+ inline: callOrReturn(getExtensionField(extension, "inline", context)),
381
+ atom: callOrReturn(getExtensionField(extension, "atom", context)),
382
+ selectable: callOrReturn(getExtensionField(extension, "selectable", context)),
383
+ draggable: callOrReturn(getExtensionField(extension, "draggable", context)),
384
+ code: callOrReturn(getExtensionField(extension, "code", context)),
385
+ whitespace: callOrReturn(getExtensionField(extension, "whitespace", context)),
386
+ defining: callOrReturn(getExtensionField(extension, "defining", context)),
387
+ isolating: callOrReturn(getExtensionField(extension, "isolating", context)),
388
+ attrs: Object.fromEntries(extensionAttributes.map((extensionAttribute) => {
389
+ var _a2;
390
+ return [extensionAttribute.name, { default: (_a2 = extensionAttribute === null || extensionAttribute === void 0 ? void 0 : extensionAttribute.attribute) === null || _a2 === void 0 ? void 0 : _a2.default }];
391
+ }))
392
+ });
393
+ const parseHTML = callOrReturn(getExtensionField(extension, "parseHTML", context));
394
+ if (parseHTML) {
395
+ schema.parseDOM = parseHTML.map((parseRule) => injectExtensionAttributesToParseRule(parseRule, extensionAttributes));
396
+ }
397
+ const renderHTML = getExtensionField(extension, "renderHTML", context);
398
+ if (renderHTML) {
399
+ schema.toDOM = (node) => renderHTML({
400
+ node,
401
+ HTMLAttributes: getRenderedAttributes(node, extensionAttributes)
402
+ });
403
+ }
404
+ const renderText = getExtensionField(extension, "renderText", context);
405
+ if (renderText) {
406
+ schema.toText = renderText;
407
+ }
408
+ return [extension.name, schema];
409
+ }));
410
+ const marks = Object.fromEntries(markExtensions.map((extension) => {
411
+ const extensionAttributes = allAttributes.filter((attribute) => attribute.type === extension.name);
412
+ const context = {
413
+ name: extension.name,
414
+ options: extension.options,
415
+ storage: extension.storage,
416
+ editor
417
+ };
418
+ const extraMarkFields = extensions.reduce((fields, e) => {
419
+ const extendMarkSchema = getExtensionField(e, "extendMarkSchema", context);
420
+ return {
421
+ ...fields,
422
+ ...extendMarkSchema ? extendMarkSchema(extension) : {}
423
+ };
424
+ }, {});
425
+ const schema = cleanUpSchemaItem({
426
+ ...extraMarkFields,
427
+ inclusive: callOrReturn(getExtensionField(extension, "inclusive", context)),
428
+ excludes: callOrReturn(getExtensionField(extension, "excludes", context)),
429
+ group: callOrReturn(getExtensionField(extension, "group", context)),
430
+ spanning: callOrReturn(getExtensionField(extension, "spanning", context)),
431
+ code: callOrReturn(getExtensionField(extension, "code", context)),
432
+ attrs: Object.fromEntries(extensionAttributes.map((extensionAttribute) => {
433
+ var _a2;
434
+ return [extensionAttribute.name, { default: (_a2 = extensionAttribute === null || extensionAttribute === void 0 ? void 0 : extensionAttribute.attribute) === null || _a2 === void 0 ? void 0 : _a2.default }];
435
+ }))
436
+ });
437
+ const parseHTML = callOrReturn(getExtensionField(extension, "parseHTML", context));
438
+ if (parseHTML) {
439
+ schema.parseDOM = parseHTML.map((parseRule) => injectExtensionAttributesToParseRule(parseRule, extensionAttributes));
440
+ }
441
+ const renderHTML = getExtensionField(extension, "renderHTML", context);
442
+ if (renderHTML) {
443
+ schema.toDOM = (mark) => renderHTML({
444
+ mark,
445
+ HTMLAttributes: getRenderedAttributes(mark, extensionAttributes)
446
+ });
447
+ }
448
+ return [extension.name, schema];
449
+ }));
450
+ return new (0, _model.Schema)({
451
+ topNode,
452
+ nodes,
453
+ marks
454
+ });
455
+ }
456
+ function getSchemaTypeByName(name, schema) {
457
+ return schema.nodes[name] || schema.marks[name] || null;
458
+ }
459
+ function isExtensionRulesEnabled(extension, enabled) {
460
+ if (Array.isArray(enabled)) {
461
+ return enabled.some((enabledExtension) => {
462
+ const name = typeof enabledExtension === "string" ? enabledExtension : enabledExtension.name;
463
+ return name === extension.name;
464
+ });
465
+ }
466
+ return enabled;
467
+ }
468
+ var getTextContentFromNodes = ($from, maxMatch = 500) => {
469
+ let textBefore = "";
470
+ const sliceEndPos = $from.parentOffset;
471
+ $from.parent.nodesBetween(Math.max(0, sliceEndPos - maxMatch), sliceEndPos, (node, pos, parent, index) => {
472
+ var _a, _b;
473
+ const chunk = ((_b = (_a = node.type.spec).toText) === null || _b === void 0 ? void 0 : _b.call(_a, {
474
+ node,
475
+ pos,
476
+ parent,
477
+ index
478
+ })) || node.textContent || "%leaf%";
479
+ textBefore += node.isAtom && !node.isText ? chunk : chunk.slice(0, Math.max(0, sliceEndPos - pos));
480
+ });
481
+ return textBefore;
482
+ };
483
+ function isRegExp(value) {
484
+ return Object.prototype.toString.call(value) === "[object RegExp]";
485
+ }
486
+ var inputRuleMatcherHandler = (text, find) => {
487
+ if (isRegExp(find)) {
488
+ return find.exec(text);
489
+ }
490
+ const inputRuleMatch = find(text);
491
+ if (!inputRuleMatch) {
492
+ return null;
493
+ }
494
+ const result = [inputRuleMatch.text];
495
+ result.index = inputRuleMatch.index;
496
+ result.input = text;
497
+ result.data = inputRuleMatch.data;
498
+ if (inputRuleMatch.replaceWith) {
499
+ if (!inputRuleMatch.text.includes(inputRuleMatch.replaceWith)) {
500
+ console.warn('[tiptap warn]: "inputRuleMatch.replaceWith" must be part of "inputRuleMatch.text".');
501
+ }
502
+ result.push(inputRuleMatch.replaceWith);
503
+ }
504
+ return result;
505
+ };
506
+ function run$1(config) {
507
+ var _a;
508
+ const { editor, from, to, text, rules, plugin } = config;
509
+ const { view } = editor;
510
+ if (view.composing) {
511
+ return false;
512
+ }
513
+ const $from = view.state.doc.resolve(from);
514
+ if (
515
+ // check for code node
516
+ $from.parent.type.spec.code || !!((_a = $from.nodeBefore || $from.nodeAfter) === null || _a === void 0 ? void 0 : _a.marks.find((mark) => mark.type.spec.code))
517
+ ) {
518
+ return false;
519
+ }
520
+ let matched = false;
521
+ const textBefore = getTextContentFromNodes($from) + text;
522
+ rules.forEach((rule) => {
523
+ if (matched) {
524
+ return;
525
+ }
526
+ const match = inputRuleMatcherHandler(textBefore, rule.find);
527
+ if (!match) {
528
+ return;
529
+ }
530
+ const tr = view.state.tr;
531
+ const state = createChainableState({
532
+ state: view.state,
533
+ transaction: tr
534
+ });
535
+ const range = {
536
+ from: from - (match[0].length - text.length),
537
+ to
538
+ };
539
+ const { commands: commands2, chain, can } = new CommandManager({
540
+ editor,
541
+ state
542
+ });
543
+ const handler = rule.handler({
544
+ state,
545
+ range,
546
+ match,
547
+ commands: commands2,
548
+ chain,
549
+ can
550
+ });
551
+ if (handler === null || !tr.steps.length) {
552
+ return;
553
+ }
554
+ tr.setMeta(plugin, {
555
+ transform: tr,
556
+ from,
557
+ to,
558
+ text
559
+ });
560
+ view.dispatch(tr);
561
+ matched = true;
562
+ });
563
+ return matched;
564
+ }
565
+ function inputRulesPlugin(props) {
566
+ const { editor, rules } = props;
567
+ const plugin = new (0, _state.Plugin)({
568
+ state: {
569
+ init() {
570
+ return null;
571
+ },
572
+ apply(tr, prev) {
573
+ const stored = tr.getMeta(plugin);
574
+ if (stored) {
575
+ return stored;
576
+ }
577
+ const simulatedInputMeta = tr.getMeta("applyInputRules");
578
+ const isSimulatedInput = !!simulatedInputMeta;
579
+ if (isSimulatedInput) {
580
+ setTimeout(() => {
581
+ const { from, text } = simulatedInputMeta;
582
+ const to = from + text.length;
583
+ run$1({
584
+ editor,
585
+ from,
586
+ to,
587
+ text,
588
+ rules,
589
+ plugin
590
+ });
591
+ });
592
+ }
593
+ return tr.selectionSet || tr.docChanged ? null : prev;
594
+ }
595
+ },
596
+ props: {
597
+ handleTextInput(view, from, to, text) {
598
+ return run$1({
599
+ editor,
600
+ from,
601
+ to,
602
+ text,
603
+ rules,
604
+ plugin
605
+ });
606
+ },
607
+ handleDOMEvents: {
608
+ compositionend: (view) => {
609
+ setTimeout(() => {
610
+ const { $cursor } = view.state.selection;
611
+ if ($cursor) {
612
+ run$1({
613
+ editor,
614
+ from: $cursor.pos,
615
+ to: $cursor.pos,
616
+ text: "",
617
+ rules,
618
+ plugin
619
+ });
620
+ }
621
+ });
622
+ return false;
623
+ }
624
+ },
625
+ // add support for input rules to trigger on enter
626
+ // this is useful for example for code blocks
627
+ handleKeyDown(view, event) {
628
+ if (event.key !== "Enter") {
629
+ return false;
630
+ }
631
+ const { $cursor } = view.state.selection;
632
+ if ($cursor) {
633
+ return run$1({
634
+ editor,
635
+ from: $cursor.pos,
636
+ to: $cursor.pos,
637
+ text: "\n",
638
+ rules,
639
+ plugin
640
+ });
641
+ }
642
+ return false;
643
+ }
644
+ },
645
+ // @ts-ignore
646
+ isInputRules: true
647
+ });
648
+ return plugin;
649
+ }
650
+ function getType(value) {
651
+ return Object.prototype.toString.call(value).slice(8, -1);
652
+ }
653
+ function isPlainObject(value) {
654
+ if (getType(value) !== "Object") {
655
+ return false;
656
+ }
657
+ return value.constructor === Object && Object.getPrototypeOf(value) === Object.prototype;
658
+ }
659
+ function mergeDeep(target, source) {
660
+ const output = { ...target };
661
+ if (isPlainObject(target) && isPlainObject(source)) {
662
+ Object.keys(source).forEach((key) => {
663
+ if (isPlainObject(source[key]) && isPlainObject(target[key])) {
664
+ output[key] = mergeDeep(target[key], source[key]);
665
+ } else {
666
+ output[key] = source[key];
667
+ }
668
+ });
669
+ }
670
+ return output;
671
+ }
672
+ var Mark = class _Mark {
673
+ constructor(config = {}) {
674
+ this.type = "mark";
675
+ this.name = "mark";
676
+ this.parent = null;
677
+ this.child = null;
678
+ this.config = {
679
+ name: this.name,
680
+ defaultOptions: {}
681
+ };
682
+ this.config = {
683
+ ...this.config,
684
+ ...config
685
+ };
686
+ this.name = this.config.name;
687
+ if (config.defaultOptions && Object.keys(config.defaultOptions).length > 0) {
688
+ console.warn(`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${this.name}".`);
689
+ }
690
+ this.options = this.config.defaultOptions;
691
+ if (this.config.addOptions) {
692
+ this.options = callOrReturn(getExtensionField(this, "addOptions", {
693
+ name: this.name
694
+ }));
695
+ }
696
+ this.storage = callOrReturn(getExtensionField(this, "addStorage", {
697
+ name: this.name,
698
+ options: this.options
699
+ })) || {};
700
+ }
701
+ static create(config = {}) {
702
+ return new _Mark(config);
703
+ }
704
+ configure(options = {}) {
705
+ const extension = this.extend({
706
+ ...this.config,
707
+ addOptions: () => {
708
+ return mergeDeep(this.options, options);
709
+ }
710
+ });
711
+ extension.name = this.name;
712
+ extension.parent = this.parent;
713
+ return extension;
714
+ }
715
+ extend(extendedConfig = {}) {
716
+ const extension = new _Mark(extendedConfig);
717
+ extension.parent = this;
718
+ this.child = extension;
719
+ extension.name = extendedConfig.name ? extendedConfig.name : extension.parent.name;
720
+ if (extendedConfig.defaultOptions && Object.keys(extendedConfig.defaultOptions).length > 0) {
721
+ console.warn(`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`);
722
+ }
723
+ extension.options = callOrReturn(getExtensionField(extension, "addOptions", {
724
+ name: extension.name
725
+ }));
726
+ extension.storage = callOrReturn(getExtensionField(extension, "addStorage", {
727
+ name: extension.name,
728
+ options: extension.options
729
+ }));
730
+ return extension;
731
+ }
732
+ static handleExit({ editor, mark }) {
733
+ const { tr } = editor.state;
734
+ const currentPos = editor.state.selection.$from;
735
+ const isAtEnd = currentPos.pos === currentPos.end();
736
+ if (isAtEnd) {
737
+ const currentMarks = currentPos.marks();
738
+ const isInMark = !!currentMarks.find((m) => (m === null || m === void 0 ? void 0 : m.type.name) === mark.name);
739
+ if (!isInMark) {
740
+ return false;
741
+ }
742
+ const removeMark = currentMarks.find((m) => (m === null || m === void 0 ? void 0 : m.type.name) === mark.name);
743
+ if (removeMark) {
744
+ tr.removeStoredMark(removeMark);
745
+ }
746
+ tr.insertText(" ", currentPos.pos);
747
+ editor.view.dispatch(tr);
748
+ return true;
749
+ }
750
+ return false;
751
+ }
752
+ };
753
+ function isNumber(value) {
754
+ return typeof value === "number";
755
+ }
756
+ var pasteRuleMatcherHandler = (text, find, event) => {
757
+ if (isRegExp(find)) {
758
+ return [...text.matchAll(find)];
759
+ }
760
+ const matches = find(text, event);
761
+ if (!matches) {
762
+ return [];
763
+ }
764
+ return matches.map((pasteRuleMatch) => {
765
+ const result = [pasteRuleMatch.text];
766
+ result.index = pasteRuleMatch.index;
767
+ result.input = text;
768
+ result.data = pasteRuleMatch.data;
769
+ if (pasteRuleMatch.replaceWith) {
770
+ if (!pasteRuleMatch.text.includes(pasteRuleMatch.replaceWith)) {
771
+ console.warn('[tiptap warn]: "pasteRuleMatch.replaceWith" must be part of "pasteRuleMatch.text".');
772
+ }
773
+ result.push(pasteRuleMatch.replaceWith);
774
+ }
775
+ return result;
776
+ });
777
+ };
778
+ function run(config) {
779
+ const { editor, state, from, to, rule, pasteEvent, dropEvent } = config;
780
+ const { commands: commands2, chain, can } = new CommandManager({
781
+ editor,
782
+ state
783
+ });
784
+ const handlers = [];
785
+ state.doc.nodesBetween(from, to, (node, pos) => {
786
+ if (!node.isTextblock || node.type.spec.code) {
787
+ return;
788
+ }
789
+ const resolvedFrom = Math.max(from, pos);
790
+ const resolvedTo = Math.min(to, pos + node.content.size);
791
+ const textToMatch = node.textBetween(resolvedFrom - pos, resolvedTo - pos, void 0, "\uFFFC");
792
+ const matches = pasteRuleMatcherHandler(textToMatch, rule.find, pasteEvent);
793
+ matches.forEach((match) => {
794
+ if (match.index === void 0) {
795
+ return;
796
+ }
797
+ const start = resolvedFrom + match.index + 1;
798
+ const end = start + match[0].length;
799
+ const range = {
800
+ from: state.tr.mapping.map(start),
801
+ to: state.tr.mapping.map(end)
802
+ };
803
+ const handler = rule.handler({
804
+ state,
805
+ range,
806
+ match,
807
+ commands: commands2,
808
+ chain,
809
+ can,
810
+ pasteEvent,
811
+ dropEvent
812
+ });
813
+ handlers.push(handler);
814
+ });
815
+ });
816
+ const success = handlers.every((handler) => handler !== null);
817
+ return success;
818
+ }
819
+ var createClipboardPasteEvent = (text) => {
820
+ var _a;
821
+ const event = new ClipboardEvent("paste", {
822
+ clipboardData: new DataTransfer()
823
+ });
824
+ (_a = event.clipboardData) === null || _a === void 0 ? void 0 : _a.setData("text/html", text);
825
+ return event;
826
+ };
827
+ function pasteRulesPlugin(props) {
828
+ const { editor, rules } = props;
829
+ let dragSourceElement = null;
830
+ let isPastedFromProseMirror = false;
831
+ let isDroppedFromProseMirror = false;
832
+ let pasteEvent = typeof ClipboardEvent !== "undefined" ? new ClipboardEvent("paste") : null;
833
+ let dropEvent = typeof DragEvent !== "undefined" ? new DragEvent("drop") : null;
834
+ const processEvent = ({ state, from, to, rule, pasteEvt }) => {
835
+ const tr = state.tr;
836
+ const chainableState = createChainableState({
837
+ state,
838
+ transaction: tr
839
+ });
840
+ const handler = run({
841
+ editor,
842
+ state: chainableState,
843
+ from: Math.max(from - 1, 0),
844
+ to: to.b - 1,
845
+ rule,
846
+ pasteEvent: pasteEvt,
847
+ dropEvent
848
+ });
849
+ if (!handler || !tr.steps.length) {
850
+ return;
851
+ }
852
+ dropEvent = typeof DragEvent !== "undefined" ? new DragEvent("drop") : null;
853
+ pasteEvent = typeof ClipboardEvent !== "undefined" ? new ClipboardEvent("paste") : null;
854
+ return tr;
855
+ };
856
+ const plugins = rules.map((rule) => {
857
+ return new (0, _state.Plugin)({
858
+ // we register a global drag handler to track the current drag source element
859
+ view(view) {
860
+ const handleDragstart = (event) => {
861
+ var _a;
862
+ dragSourceElement = ((_a = view.dom.parentElement) === null || _a === void 0 ? void 0 : _a.contains(event.target)) ? view.dom.parentElement : null;
863
+ };
864
+ window.addEventListener("dragstart", handleDragstart);
865
+ return {
866
+ destroy() {
867
+ window.removeEventListener("dragstart", handleDragstart);
868
+ }
869
+ };
870
+ },
871
+ props: {
872
+ handleDOMEvents: {
873
+ drop: (view, event) => {
874
+ isDroppedFromProseMirror = dragSourceElement === view.dom.parentElement;
875
+ dropEvent = event;
876
+ return false;
877
+ },
878
+ paste: (_view, event) => {
879
+ var _a;
880
+ const html = (_a = event.clipboardData) === null || _a === void 0 ? void 0 : _a.getData("text/html");
881
+ pasteEvent = event;
882
+ isPastedFromProseMirror = !!(html === null || html === void 0 ? void 0 : html.includes("data-pm-slice"));
883
+ return false;
884
+ }
885
+ }
886
+ },
887
+ appendTransaction: (transactions, oldState, state) => {
888
+ const transaction = transactions[0];
889
+ const isPaste = transaction.getMeta("uiEvent") === "paste" && !isPastedFromProseMirror;
890
+ const isDrop = transaction.getMeta("uiEvent") === "drop" && !isDroppedFromProseMirror;
891
+ const simulatedPasteMeta = transaction.getMeta("applyPasteRules");
892
+ const isSimulatedPaste = !!simulatedPasteMeta;
893
+ if (!isPaste && !isDrop && !isSimulatedPaste) {
894
+ return;
895
+ }
896
+ if (isSimulatedPaste) {
897
+ const { from: from2, text } = simulatedPasteMeta;
898
+ const to2 = from2 + text.length;
899
+ const pasteEvt = createClipboardPasteEvent(text);
900
+ return processEvent({
901
+ rule,
902
+ state,
903
+ from: from2,
904
+ to: { b: to2 },
905
+ pasteEvt
906
+ });
907
+ }
908
+ const from = oldState.doc.content.findDiffStart(state.doc.content);
909
+ const to = oldState.doc.content.findDiffEnd(state.doc.content);
910
+ if (!isNumber(from) || !to || from === to.b) {
911
+ return;
912
+ }
913
+ return processEvent({
914
+ rule,
915
+ state,
916
+ from,
917
+ to,
918
+ pasteEvt: pasteEvent
919
+ });
920
+ }
921
+ });
922
+ });
923
+ return plugins;
924
+ }
925
+ function findDuplicates(items) {
926
+ const filtered = items.filter((el, index) => items.indexOf(el) !== index);
927
+ return Array.from(new Set(filtered));
928
+ }
929
+ var ExtensionManager = class _ExtensionManager {
930
+ constructor(extensions, editor) {
931
+ this.splittableMarks = [];
932
+ this.editor = editor;
933
+ this.extensions = _ExtensionManager.resolve(extensions);
934
+ this.schema = getSchemaByResolvedExtensions(this.extensions, editor);
935
+ this.setupExtensions();
936
+ }
937
+ /**
938
+ * Returns a flattened and sorted extension list while
939
+ * also checking for duplicated extensions and warns the user.
940
+ * @param extensions An array of Tiptap extensions
941
+ * @returns An flattened and sorted array of Tiptap extensions
942
+ */
943
+ static resolve(extensions) {
944
+ const resolvedExtensions = _ExtensionManager.sort(_ExtensionManager.flatten(extensions));
945
+ const duplicatedNames = findDuplicates(resolvedExtensions.map((extension) => extension.name));
946
+ if (duplicatedNames.length) {
947
+ console.warn(`[tiptap warn]: Duplicate extension names found: [${duplicatedNames.map((item) => `'${item}'`).join(", ")}]. This can lead to issues.`);
948
+ }
949
+ return resolvedExtensions;
950
+ }
951
+ /**
952
+ * Create a flattened array of extensions by traversing the `addExtensions` field.
953
+ * @param extensions An array of Tiptap extensions
954
+ * @returns A flattened array of Tiptap extensions
955
+ */
956
+ static flatten(extensions) {
957
+ return extensions.map((extension) => {
958
+ const context = {
959
+ name: extension.name,
960
+ options: extension.options,
961
+ storage: extension.storage
962
+ };
963
+ const addExtensions = getExtensionField(extension, "addExtensions", context);
964
+ if (addExtensions) {
965
+ return [extension, ...this.flatten(addExtensions())];
966
+ }
967
+ return extension;
968
+ }).flat(10);
969
+ }
970
+ /**
971
+ * Sort extensions by priority.
972
+ * @param extensions An array of Tiptap extensions
973
+ * @returns A sorted array of Tiptap extensions by priority
974
+ */
975
+ static sort(extensions) {
976
+ const defaultPriority = 100;
977
+ return extensions.sort((a, b) => {
978
+ const priorityA = getExtensionField(a, "priority") || defaultPriority;
979
+ const priorityB = getExtensionField(b, "priority") || defaultPriority;
980
+ if (priorityA > priorityB) {
981
+ return -1;
982
+ }
983
+ if (priorityA < priorityB) {
984
+ return 1;
985
+ }
986
+ return 0;
987
+ });
988
+ }
989
+ /**
990
+ * Get all commands from the extensions.
991
+ * @returns An object with all commands where the key is the command name and the value is the command function
992
+ */
993
+ get commands() {
994
+ return this.extensions.reduce((commands2, extension) => {
995
+ const context = {
996
+ name: extension.name,
997
+ options: extension.options,
998
+ storage: extension.storage,
999
+ editor: this.editor,
1000
+ type: getSchemaTypeByName(extension.name, this.schema)
1001
+ };
1002
+ const addCommands = getExtensionField(extension, "addCommands", context);
1003
+ if (!addCommands) {
1004
+ return commands2;
1005
+ }
1006
+ return {
1007
+ ...commands2,
1008
+ ...addCommands()
1009
+ };
1010
+ }, {});
1011
+ }
1012
+ /**
1013
+ * Get all registered Prosemirror plugins from the extensions.
1014
+ * @returns An array of Prosemirror plugins
1015
+ */
1016
+ get plugins() {
1017
+ const { editor } = this;
1018
+ const extensions = _ExtensionManager.sort([...this.extensions].reverse());
1019
+ const inputRules = [];
1020
+ const pasteRules = [];
1021
+ const allPlugins = extensions.map((extension) => {
1022
+ const context = {
1023
+ name: extension.name,
1024
+ options: extension.options,
1025
+ storage: extension.storage,
1026
+ editor,
1027
+ type: getSchemaTypeByName(extension.name, this.schema)
1028
+ };
1029
+ const plugins = [];
1030
+ const addKeyboardShortcuts = getExtensionField(extension, "addKeyboardShortcuts", context);
1031
+ let defaultBindings = {};
1032
+ if (extension.type === "mark" && getExtensionField(extension, "exitable", context)) {
1033
+ defaultBindings.ArrowRight = () => Mark.handleExit({ editor, mark: extension });
1034
+ }
1035
+ if (addKeyboardShortcuts) {
1036
+ const bindings = Object.fromEntries(Object.entries(addKeyboardShortcuts()).map(([shortcut, method]) => {
1037
+ return [shortcut, () => method({ editor })];
1038
+ }));
1039
+ defaultBindings = { ...defaultBindings, ...bindings };
1040
+ }
1041
+ const keyMapPlugin = _keymap.keymap.call(void 0, defaultBindings);
1042
+ plugins.push(keyMapPlugin);
1043
+ const addInputRules = getExtensionField(extension, "addInputRules", context);
1044
+ if (isExtensionRulesEnabled(extension, editor.options.enableInputRules) && addInputRules) {
1045
+ inputRules.push(...addInputRules());
1046
+ }
1047
+ const addPasteRules = getExtensionField(extension, "addPasteRules", context);
1048
+ if (isExtensionRulesEnabled(extension, editor.options.enablePasteRules) && addPasteRules) {
1049
+ pasteRules.push(...addPasteRules());
1050
+ }
1051
+ const addProseMirrorPlugins = getExtensionField(extension, "addProseMirrorPlugins", context);
1052
+ if (addProseMirrorPlugins) {
1053
+ const proseMirrorPlugins = addProseMirrorPlugins();
1054
+ plugins.push(...proseMirrorPlugins);
1055
+ }
1056
+ return plugins;
1057
+ }).flat();
1058
+ return [
1059
+ inputRulesPlugin({
1060
+ editor,
1061
+ rules: inputRules
1062
+ }),
1063
+ ...pasteRulesPlugin({
1064
+ editor,
1065
+ rules: pasteRules
1066
+ }),
1067
+ ...allPlugins
1068
+ ];
1069
+ }
1070
+ /**
1071
+ * Get all attributes from the extensions.
1072
+ * @returns An array of attributes
1073
+ */
1074
+ get attributes() {
1075
+ return getAttributesFromExtensions(this.extensions);
1076
+ }
1077
+ /**
1078
+ * Get all node views from the extensions.
1079
+ * @returns An object with all node views where the key is the node name and the value is the node view function
1080
+ */
1081
+ get nodeViews() {
1082
+ const { editor } = this;
1083
+ const { nodeExtensions } = splitExtensions(this.extensions);
1084
+ return Object.fromEntries(nodeExtensions.filter((extension) => !!getExtensionField(extension, "addNodeView")).map((extension) => {
1085
+ const extensionAttributes = this.attributes.filter((attribute) => attribute.type === extension.name);
1086
+ const context = {
1087
+ name: extension.name,
1088
+ options: extension.options,
1089
+ storage: extension.storage,
1090
+ editor,
1091
+ type: getNodeType(extension.name, this.schema)
1092
+ };
1093
+ const addNodeView = getExtensionField(extension, "addNodeView", context);
1094
+ if (!addNodeView) {
1095
+ return [];
1096
+ }
1097
+ const nodeview = (node, view, getPos, decorations, innerDecorations) => {
1098
+ const HTMLAttributes = getRenderedAttributes(node, extensionAttributes);
1099
+ return addNodeView()({
1100
+ // pass-through
1101
+ node,
1102
+ view,
1103
+ getPos,
1104
+ decorations,
1105
+ innerDecorations,
1106
+ // tiptap-specific
1107
+ editor,
1108
+ extension,
1109
+ HTMLAttributes
1110
+ });
1111
+ };
1112
+ return [extension.name, nodeview];
1113
+ }));
1114
+ }
1115
+ /**
1116
+ * Go through all extensions, create extension storages & setup marks
1117
+ * & bind editor event listener.
1118
+ */
1119
+ setupExtensions() {
1120
+ this.extensions.forEach((extension) => {
1121
+ var _a;
1122
+ this.editor.extensionStorage[extension.name] = extension.storage;
1123
+ const context = {
1124
+ name: extension.name,
1125
+ options: extension.options,
1126
+ storage: extension.storage,
1127
+ editor: this.editor,
1128
+ type: getSchemaTypeByName(extension.name, this.schema)
1129
+ };
1130
+ if (extension.type === "mark") {
1131
+ const keepOnSplit = (_a = callOrReturn(getExtensionField(extension, "keepOnSplit", context))) !== null && _a !== void 0 ? _a : true;
1132
+ if (keepOnSplit) {
1133
+ this.splittableMarks.push(extension.name);
1134
+ }
1135
+ }
1136
+ const onBeforeCreate = getExtensionField(extension, "onBeforeCreate", context);
1137
+ const onCreate = getExtensionField(extension, "onCreate", context);
1138
+ const onUpdate = getExtensionField(extension, "onUpdate", context);
1139
+ const onSelectionUpdate = getExtensionField(extension, "onSelectionUpdate", context);
1140
+ const onTransaction = getExtensionField(extension, "onTransaction", context);
1141
+ const onFocus = getExtensionField(extension, "onFocus", context);
1142
+ const onBlur = getExtensionField(extension, "onBlur", context);
1143
+ const onDestroy = getExtensionField(extension, "onDestroy", context);
1144
+ if (onBeforeCreate) {
1145
+ this.editor.on("beforeCreate", onBeforeCreate);
1146
+ }
1147
+ if (onCreate) {
1148
+ this.editor.on("create", onCreate);
1149
+ }
1150
+ if (onUpdate) {
1151
+ this.editor.on("update", onUpdate);
1152
+ }
1153
+ if (onSelectionUpdate) {
1154
+ this.editor.on("selectionUpdate", onSelectionUpdate);
1155
+ }
1156
+ if (onTransaction) {
1157
+ this.editor.on("transaction", onTransaction);
1158
+ }
1159
+ if (onFocus) {
1160
+ this.editor.on("focus", onFocus);
1161
+ }
1162
+ if (onBlur) {
1163
+ this.editor.on("blur", onBlur);
1164
+ }
1165
+ if (onDestroy) {
1166
+ this.editor.on("destroy", onDestroy);
1167
+ }
1168
+ });
1169
+ }
1170
+ };
1171
+ var Extension = class _Extension {
1172
+ constructor(config = {}) {
1173
+ this.type = "extension";
1174
+ this.name = "extension";
1175
+ this.parent = null;
1176
+ this.child = null;
1177
+ this.config = {
1178
+ name: this.name,
1179
+ defaultOptions: {}
1180
+ };
1181
+ this.config = {
1182
+ ...this.config,
1183
+ ...config
1184
+ };
1185
+ this.name = this.config.name;
1186
+ if (config.defaultOptions && Object.keys(config.defaultOptions).length > 0) {
1187
+ console.warn(`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${this.name}".`);
1188
+ }
1189
+ this.options = this.config.defaultOptions;
1190
+ if (this.config.addOptions) {
1191
+ this.options = callOrReturn(getExtensionField(this, "addOptions", {
1192
+ name: this.name
1193
+ }));
1194
+ }
1195
+ this.storage = callOrReturn(getExtensionField(this, "addStorage", {
1196
+ name: this.name,
1197
+ options: this.options
1198
+ })) || {};
1199
+ }
1200
+ static create(config = {}) {
1201
+ return new _Extension(config);
1202
+ }
1203
+ configure(options = {}) {
1204
+ const extension = this.extend({
1205
+ ...this.config,
1206
+ addOptions: () => {
1207
+ return mergeDeep(this.options, options);
1208
+ }
1209
+ });
1210
+ extension.name = this.name;
1211
+ extension.parent = this.parent;
1212
+ return extension;
1213
+ }
1214
+ extend(extendedConfig = {}) {
1215
+ const extension = new _Extension({ ...this.config, ...extendedConfig });
1216
+ extension.parent = this;
1217
+ this.child = extension;
1218
+ extension.name = extendedConfig.name ? extendedConfig.name : extension.parent.name;
1219
+ if (extendedConfig.defaultOptions && Object.keys(extendedConfig.defaultOptions).length > 0) {
1220
+ console.warn(`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`);
1221
+ }
1222
+ extension.options = callOrReturn(getExtensionField(extension, "addOptions", {
1223
+ name: extension.name
1224
+ }));
1225
+ extension.storage = callOrReturn(getExtensionField(extension, "addStorage", {
1226
+ name: extension.name,
1227
+ options: extension.options
1228
+ }));
1229
+ return extension;
1230
+ }
1231
+ };
1232
+ function getTextBetween(startNode, range, options) {
1233
+ const { from, to } = range;
1234
+ const { blockSeparator = "\n\n", textSerializers = {} } = options || {};
1235
+ let text = "";
1236
+ startNode.nodesBetween(from, to, (node, pos, parent, index) => {
1237
+ var _a;
1238
+ if (node.isBlock && pos > from) {
1239
+ text += blockSeparator;
1240
+ }
1241
+ const textSerializer = textSerializers === null || textSerializers === void 0 ? void 0 : textSerializers[node.type.name];
1242
+ if (textSerializer) {
1243
+ if (parent) {
1244
+ text += textSerializer({
1245
+ node,
1246
+ pos,
1247
+ parent,
1248
+ index,
1249
+ range
1250
+ });
1251
+ }
1252
+ return false;
1253
+ }
1254
+ if (node.isText) {
1255
+ text += (_a = node === null || node === void 0 ? void 0 : node.text) === null || _a === void 0 ? void 0 : _a.slice(Math.max(from, pos) - pos, to - pos);
1256
+ }
1257
+ });
1258
+ return text;
1259
+ }
1260
+ function getTextSerializersFromSchema(schema) {
1261
+ return Object.fromEntries(Object.entries(schema.nodes).filter(([, node]) => node.spec.toText).map(([name, node]) => [name, node.spec.toText]));
1262
+ }
1263
+ var ClipboardTextSerializer = Extension.create({
1264
+ name: "clipboardTextSerializer",
1265
+ addOptions() {
1266
+ return {
1267
+ blockSeparator: void 0
1268
+ };
1269
+ },
1270
+ addProseMirrorPlugins() {
1271
+ return [
1272
+ new (0, _state.Plugin)({
1273
+ key: new (0, _state.PluginKey)("clipboardTextSerializer"),
1274
+ props: {
1275
+ clipboardTextSerializer: () => {
1276
+ const { editor } = this;
1277
+ const { state, schema } = editor;
1278
+ const { doc, selection } = state;
1279
+ const { ranges } = selection;
1280
+ const from = Math.min(...ranges.map((range2) => range2.$from.pos));
1281
+ const to = Math.max(...ranges.map((range2) => range2.$to.pos));
1282
+ const textSerializers = getTextSerializersFromSchema(schema);
1283
+ const range = { from, to };
1284
+ return getTextBetween(doc, range, {
1285
+ ...this.options.blockSeparator !== void 0 ? { blockSeparator: this.options.blockSeparator } : {},
1286
+ textSerializers
1287
+ });
1288
+ }
1289
+ }
1290
+ })
1291
+ ];
1292
+ }
1293
+ });
1294
+ var blur = () => ({ editor, view }) => {
1295
+ requestAnimationFrame(() => {
1296
+ var _a;
1297
+ if (!editor.isDestroyed) {
1298
+ view.dom.blur();
1299
+ (_a = window === null || window === void 0 ? void 0 : window.getSelection()) === null || _a === void 0 ? void 0 : _a.removeAllRanges();
1300
+ }
1301
+ });
1302
+ return true;
1303
+ };
1304
+ var clearContent = (emitUpdate = false) => ({ commands: commands2 }) => {
1305
+ return commands2.setContent("", emitUpdate);
1306
+ };
1307
+ var clearNodes = () => ({ state, tr, dispatch }) => {
1308
+ const { selection } = tr;
1309
+ const { ranges } = selection;
1310
+ if (!dispatch) {
1311
+ return true;
1312
+ }
1313
+ ranges.forEach(({ $from, $to }) => {
1314
+ state.doc.nodesBetween($from.pos, $to.pos, (node, pos) => {
1315
+ if (node.type.isText) {
1316
+ return;
1317
+ }
1318
+ const { doc, mapping } = tr;
1319
+ const $mappedFrom = doc.resolve(mapping.map(pos));
1320
+ const $mappedTo = doc.resolve(mapping.map(pos + node.nodeSize));
1321
+ const nodeRange = $mappedFrom.blockRange($mappedTo);
1322
+ if (!nodeRange) {
1323
+ return;
1324
+ }
1325
+ const targetLiftDepth = _transform.liftTarget.call(void 0, nodeRange);
1326
+ if (node.type.isTextblock) {
1327
+ const { defaultType } = $mappedFrom.parent.contentMatchAt($mappedFrom.index());
1328
+ tr.setNodeMarkup(nodeRange.start, defaultType);
1329
+ }
1330
+ if (targetLiftDepth || targetLiftDepth === 0) {
1331
+ tr.lift(nodeRange, targetLiftDepth);
1332
+ }
1333
+ });
1334
+ });
1335
+ return true;
1336
+ };
1337
+ var command = (fn) => (props) => {
1338
+ return fn(props);
1339
+ };
1340
+ var createParagraphNear = () => ({ state, dispatch }) => {
1341
+ return _commands.createParagraphNear.call(void 0, state, dispatch);
1342
+ };
1343
+ var cut = (originRange, targetPos) => ({ editor, tr }) => {
1344
+ const { state } = editor;
1345
+ const contentSlice = state.doc.slice(originRange.from, originRange.to);
1346
+ tr.deleteRange(originRange.from, originRange.to);
1347
+ const newPos = tr.mapping.map(targetPos);
1348
+ tr.insert(newPos, contentSlice.content);
1349
+ tr.setSelection(new (0, _state.TextSelection)(tr.doc.resolve(newPos - 1)));
1350
+ return true;
1351
+ };
1352
+ var deleteCurrentNode = () => ({ tr, dispatch }) => {
1353
+ const { selection } = tr;
1354
+ const currentNode = selection.$anchor.node();
1355
+ if (currentNode.content.size > 0) {
1356
+ return false;
1357
+ }
1358
+ const $pos = tr.selection.$anchor;
1359
+ for (let depth = $pos.depth; depth > 0; depth -= 1) {
1360
+ const node = $pos.node(depth);
1361
+ if (node.type === currentNode.type) {
1362
+ if (dispatch) {
1363
+ const from = $pos.before(depth);
1364
+ const to = $pos.after(depth);
1365
+ tr.delete(from, to).scrollIntoView();
1366
+ }
1367
+ return true;
1368
+ }
1369
+ }
1370
+ return false;
1371
+ };
1372
+ var deleteNode = (typeOrName) => ({ tr, state, dispatch }) => {
1373
+ const type = getNodeType(typeOrName, state.schema);
1374
+ const $pos = tr.selection.$anchor;
1375
+ for (let depth = $pos.depth; depth > 0; depth -= 1) {
1376
+ const node = $pos.node(depth);
1377
+ if (node.type === type) {
1378
+ if (dispatch) {
1379
+ const from = $pos.before(depth);
1380
+ const to = $pos.after(depth);
1381
+ tr.delete(from, to).scrollIntoView();
1382
+ }
1383
+ return true;
1384
+ }
1385
+ }
1386
+ return false;
1387
+ };
1388
+ var deleteRange = (range) => ({ tr, dispatch }) => {
1389
+ const { from, to } = range;
1390
+ if (dispatch) {
1391
+ tr.delete(from, to);
1392
+ }
1393
+ return true;
1394
+ };
1395
+ var deleteSelection = () => ({ state, dispatch }) => {
1396
+ return _commands.deleteSelection.call(void 0, state, dispatch);
1397
+ };
1398
+ var enter = () => ({ commands: commands2 }) => {
1399
+ return commands2.keyboardShortcut("Enter");
1400
+ };
1401
+ var exitCode = () => ({ state, dispatch }) => {
1402
+ return _commands.exitCode.call(void 0, state, dispatch);
1403
+ };
1404
+ function objectIncludes(object1, object2, options = { strict: true }) {
1405
+ const keys = Object.keys(object2);
1406
+ if (!keys.length) {
1407
+ return true;
1408
+ }
1409
+ return keys.every((key) => {
1410
+ if (options.strict) {
1411
+ return object2[key] === object1[key];
1412
+ }
1413
+ if (isRegExp(object2[key])) {
1414
+ return object2[key].test(object1[key]);
1415
+ }
1416
+ return object2[key] === object1[key];
1417
+ });
1418
+ }
1419
+ function findMarkInSet(marks, type, attributes = {}) {
1420
+ return marks.find((item) => {
1421
+ return item.type === type && objectIncludes(item.attrs, attributes);
1422
+ });
1423
+ }
1424
+ function isMarkInSet(marks, type, attributes = {}) {
1425
+ return !!findMarkInSet(marks, type, attributes);
1426
+ }
1427
+ function getMarkRange($pos, type, attributes = {}) {
1428
+ if (!$pos || !type) {
1429
+ return;
1430
+ }
1431
+ let start = $pos.parent.childAfter($pos.parentOffset);
1432
+ if (!start.node || !start.node.marks.some((mark2) => mark2.type === type)) {
1433
+ start = $pos.parent.childBefore($pos.parentOffset);
1434
+ }
1435
+ if (!start.node || !start.node.marks.some((mark2) => mark2.type === type)) {
1436
+ return;
1437
+ }
1438
+ const mark = findMarkInSet([...start.node.marks], type, attributes);
1439
+ if (!mark) {
1440
+ return;
1441
+ }
1442
+ let startIndex = start.index;
1443
+ let startPos = $pos.start() + start.offset;
1444
+ let endIndex = startIndex + 1;
1445
+ let endPos = startPos + start.node.nodeSize;
1446
+ findMarkInSet([...start.node.marks], type, attributes);
1447
+ while (startIndex > 0 && mark.isInSet($pos.parent.child(startIndex - 1).marks)) {
1448
+ startIndex -= 1;
1449
+ startPos -= $pos.parent.child(startIndex).nodeSize;
1450
+ }
1451
+ while (endIndex < $pos.parent.childCount && isMarkInSet([...$pos.parent.child(endIndex).marks], type, attributes)) {
1452
+ endPos += $pos.parent.child(endIndex).nodeSize;
1453
+ endIndex += 1;
1454
+ }
1455
+ return {
1456
+ from: startPos,
1457
+ to: endPos
1458
+ };
1459
+ }
1460
+ function getMarkType(nameOrType, schema) {
1461
+ if (typeof nameOrType === "string") {
1462
+ if (!schema.marks[nameOrType]) {
1463
+ throw Error(`There is no mark type named '${nameOrType}'. Maybe you forgot to add the extension?`);
1464
+ }
1465
+ return schema.marks[nameOrType];
1466
+ }
1467
+ return nameOrType;
1468
+ }
1469
+ var extendMarkRange = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {
1470
+ const type = getMarkType(typeOrName, state.schema);
1471
+ const { doc, selection } = tr;
1472
+ const { $from, from, to } = selection;
1473
+ if (dispatch) {
1474
+ const range = getMarkRange($from, type, attributes);
1475
+ if (range && range.from <= from && range.to >= to) {
1476
+ const newSelection = _state.TextSelection.create(doc, range.from, range.to);
1477
+ tr.setSelection(newSelection);
1478
+ }
1479
+ }
1480
+ return true;
1481
+ };
1482
+ var first = (commands2) => (props) => {
1483
+ const items = typeof commands2 === "function" ? commands2(props) : commands2;
1484
+ for (let i = 0; i < items.length; i += 1) {
1485
+ if (items[i](props)) {
1486
+ return true;
1487
+ }
1488
+ }
1489
+ return false;
1490
+ };
1491
+ function isTextSelection(value) {
1492
+ return value instanceof _state.TextSelection;
1493
+ }
1494
+ function minMax(value = 0, min = 0, max = 0) {
1495
+ return Math.min(Math.max(value, min), max);
1496
+ }
1497
+ function resolveFocusPosition(doc, position = null) {
1498
+ if (!position) {
1499
+ return null;
1500
+ }
1501
+ const selectionAtStart = _state.Selection.atStart(doc);
1502
+ const selectionAtEnd = _state.Selection.atEnd(doc);
1503
+ if (position === "start" || position === true) {
1504
+ return selectionAtStart;
1505
+ }
1506
+ if (position === "end") {
1507
+ return selectionAtEnd;
1508
+ }
1509
+ const minPos = selectionAtStart.from;
1510
+ const maxPos = selectionAtEnd.to;
1511
+ if (position === "all") {
1512
+ return _state.TextSelection.create(doc, minMax(0, minPos, maxPos), minMax(doc.content.size, minPos, maxPos));
1513
+ }
1514
+ return _state.TextSelection.create(doc, minMax(position, minPos, maxPos), minMax(position, minPos, maxPos));
1515
+ }
1516
+ function isiOS() {
1517
+ return [
1518
+ "iPad Simulator",
1519
+ "iPhone Simulator",
1520
+ "iPod Simulator",
1521
+ "iPad",
1522
+ "iPhone",
1523
+ "iPod"
1524
+ ].includes(navigator.platform) || navigator.userAgent.includes("Mac") && "ontouchend" in document;
1525
+ }
1526
+ var focus = (position = null, options = {}) => ({ editor, view, tr, dispatch }) => {
1527
+ options = {
1528
+ scrollIntoView: true,
1529
+ ...options
1530
+ };
1531
+ const delayedFocus = () => {
1532
+ if (isiOS()) {
1533
+ view.dom.focus();
1534
+ }
1535
+ requestAnimationFrame(() => {
1536
+ if (!editor.isDestroyed) {
1537
+ view.focus();
1538
+ if (options === null || options === void 0 ? void 0 : options.scrollIntoView) {
1539
+ editor.commands.scrollIntoView();
1540
+ }
1541
+ }
1542
+ });
1543
+ };
1544
+ if (view.hasFocus() && position === null || position === false) {
1545
+ return true;
1546
+ }
1547
+ if (dispatch && position === null && !isTextSelection(editor.state.selection)) {
1548
+ delayedFocus();
1549
+ return true;
1550
+ }
1551
+ const selection = resolveFocusPosition(tr.doc, position) || editor.state.selection;
1552
+ const isSameSelection = editor.state.selection.eq(selection);
1553
+ if (dispatch) {
1554
+ if (!isSameSelection) {
1555
+ tr.setSelection(selection);
1556
+ }
1557
+ if (isSameSelection && tr.storedMarks) {
1558
+ tr.setStoredMarks(tr.storedMarks);
1559
+ }
1560
+ delayedFocus();
1561
+ }
1562
+ return true;
1563
+ };
1564
+ var forEach = (items, fn) => (props) => {
1565
+ return items.every((item, index) => fn(item, { ...props, index }));
1566
+ };
1567
+ var insertContent = (value, options) => ({ tr, commands: commands2 }) => {
1568
+ return commands2.insertContentAt({ from: tr.selection.from, to: tr.selection.to }, value, options);
1569
+ };
1570
+ var removeWhitespaces = (node) => {
1571
+ const children = node.childNodes;
1572
+ for (let i = children.length - 1; i >= 0; i -= 1) {
1573
+ const child = children[i];
1574
+ if (child.nodeType === 3 && child.nodeValue && /^(\n\s\s|\n)$/.test(child.nodeValue)) {
1575
+ node.removeChild(child);
1576
+ } else if (child.nodeType === 1) {
1577
+ removeWhitespaces(child);
1578
+ }
1579
+ }
1580
+ return node;
1581
+ };
1582
+ function elementFromString(value) {
1583
+ const wrappedValue = `<body>${value}</body>`;
1584
+ const html = new window.DOMParser().parseFromString(wrappedValue, "text/html").body;
1585
+ return removeWhitespaces(html);
1586
+ }
1587
+ function createNodeFromContent(content, schema, options) {
1588
+ options = {
1589
+ slice: true,
1590
+ parseOptions: {},
1591
+ ...options
1592
+ };
1593
+ const isJSONContent = typeof content === "object" && content !== null;
1594
+ const isTextContent = typeof content === "string";
1595
+ if (isJSONContent) {
1596
+ try {
1597
+ const isArrayContent = Array.isArray(content) && content.length > 0;
1598
+ if (isArrayContent) {
1599
+ return _model.Fragment.fromArray(content.map((item) => schema.nodeFromJSON(item)));
1600
+ }
1601
+ const node = schema.nodeFromJSON(content);
1602
+ if (options.errorOnInvalidContent) {
1603
+ node.check();
1604
+ }
1605
+ return node;
1606
+ } catch (error) {
1607
+ if (options.errorOnInvalidContent) {
1608
+ throw new Error("[tiptap error]: Invalid JSON content", { cause: error });
1609
+ }
1610
+ console.warn("[tiptap warn]: Invalid content.", "Passed value:", content, "Error:", error);
1611
+ return createNodeFromContent("", schema, options);
1612
+ }
1613
+ }
1614
+ if (isTextContent) {
1615
+ if (options.errorOnInvalidContent) {
1616
+ let hasInvalidContent = false;
1617
+ let invalidContent = "";
1618
+ const contentCheckSchema = new (0, _model.Schema)({
1619
+ topNode: schema.spec.topNode,
1620
+ marks: schema.spec.marks,
1621
+ // Prosemirror's schemas are executed such that: the last to execute, matches last
1622
+ // This means that we can add a catch-all node at the end of the schema to catch any content that we don't know how to handle
1623
+ nodes: schema.spec.nodes.append({
1624
+ __tiptap__private__unknown__catch__all__node: {
1625
+ content: "inline*",
1626
+ group: "block",
1627
+ parseDOM: [
1628
+ {
1629
+ tag: "*",
1630
+ getAttrs: (e) => {
1631
+ hasInvalidContent = true;
1632
+ invalidContent = typeof e === "string" ? e : e.outerHTML;
1633
+ return null;
1634
+ }
1635
+ }
1636
+ ]
1637
+ }
1638
+ })
1639
+ });
1640
+ if (options.slice) {
1641
+ _model.DOMParser.fromSchema(contentCheckSchema).parseSlice(elementFromString(content), options.parseOptions);
1642
+ } else {
1643
+ _model.DOMParser.fromSchema(contentCheckSchema).parse(elementFromString(content), options.parseOptions);
1644
+ }
1645
+ if (options.errorOnInvalidContent && hasInvalidContent) {
1646
+ throw new Error("[tiptap error]: Invalid HTML content", { cause: new Error(`Invalid element found: ${invalidContent}`) });
1647
+ }
1648
+ }
1649
+ const parser = _model.DOMParser.fromSchema(schema);
1650
+ if (options.slice) {
1651
+ return parser.parseSlice(elementFromString(content), options.parseOptions).content;
1652
+ }
1653
+ return parser.parse(elementFromString(content), options.parseOptions);
1654
+ }
1655
+ return createNodeFromContent("", schema, options);
1656
+ }
1657
+ function selectionToInsertionEnd(tr, startLen, bias) {
1658
+ const last = tr.steps.length - 1;
1659
+ if (last < startLen) {
1660
+ return;
1661
+ }
1662
+ const step = tr.steps[last];
1663
+ if (!(step instanceof _transform.ReplaceStep || step instanceof _transform.ReplaceAroundStep)) {
1664
+ return;
1665
+ }
1666
+ const map = tr.mapping.maps[last];
1667
+ let end = 0;
1668
+ map.forEach((_from, _to, _newFrom, newTo) => {
1669
+ if (end === 0) {
1670
+ end = newTo;
1671
+ }
1672
+ });
1673
+ tr.setSelection(_state.Selection.near(tr.doc.resolve(end), bias));
1674
+ }
1675
+ var isFragment = (nodeOrFragment) => {
1676
+ return !("type" in nodeOrFragment);
1677
+ };
1678
+ var insertContentAt = (position, value, options) => ({ tr, dispatch, editor }) => {
1679
+ var _a;
1680
+ if (dispatch) {
1681
+ options = {
1682
+ parseOptions: editor.options.parseOptions,
1683
+ updateSelection: true,
1684
+ applyInputRules: false,
1685
+ applyPasteRules: false,
1686
+ ...options
1687
+ };
1688
+ let content;
1689
+ try {
1690
+ content = createNodeFromContent(value, editor.schema, {
1691
+ parseOptions: {
1692
+ preserveWhitespace: "full",
1693
+ ...options.parseOptions
1694
+ },
1695
+ errorOnInvalidContent: (_a = options.errorOnInvalidContent) !== null && _a !== void 0 ? _a : editor.options.enableContentCheck
1696
+ });
1697
+ } catch (e) {
1698
+ editor.emit("contentError", {
1699
+ editor,
1700
+ error: e,
1701
+ disableCollaboration: () => {
1702
+ if (editor.storage.collaboration) {
1703
+ editor.storage.collaboration.isDisabled = true;
1704
+ }
1705
+ }
1706
+ });
1707
+ return false;
1708
+ }
1709
+ let { from, to } = typeof position === "number" ? { from: position, to: position } : { from: position.from, to: position.to };
1710
+ let isOnlyTextContent = true;
1711
+ let isOnlyBlockContent = true;
1712
+ const nodes = isFragment(content) ? content : [content];
1713
+ nodes.forEach((node) => {
1714
+ node.check();
1715
+ isOnlyTextContent = isOnlyTextContent ? node.isText && node.marks.length === 0 : false;
1716
+ isOnlyBlockContent = isOnlyBlockContent ? node.isBlock : false;
1717
+ });
1718
+ if (from === to && isOnlyBlockContent) {
1719
+ const { parent } = tr.doc.resolve(from);
1720
+ const isEmptyTextBlock = parent.isTextblock && !parent.type.spec.code && !parent.childCount;
1721
+ if (isEmptyTextBlock) {
1722
+ from -= 1;
1723
+ to += 1;
1724
+ }
1725
+ }
1726
+ let newContent;
1727
+ if (isOnlyTextContent) {
1728
+ if (Array.isArray(value)) {
1729
+ newContent = value.map((v) => v.text || "").join("");
1730
+ } else if (typeof value === "object" && !!value && !!value.text) {
1731
+ newContent = value.text;
1732
+ } else {
1733
+ newContent = value;
1734
+ }
1735
+ tr.insertText(newContent, from, to);
1736
+ } else {
1737
+ newContent = content;
1738
+ tr.replaceWith(from, to, newContent);
1739
+ }
1740
+ if (options.updateSelection) {
1741
+ selectionToInsertionEnd(tr, tr.steps.length - 1, -1);
1742
+ }
1743
+ if (options.applyInputRules) {
1744
+ tr.setMeta("applyInputRules", { from, text: newContent });
1745
+ }
1746
+ if (options.applyPasteRules) {
1747
+ tr.setMeta("applyPasteRules", { from, text: newContent });
1748
+ }
1749
+ }
1750
+ return true;
1751
+ };
1752
+ var joinUp = () => ({ state, dispatch }) => {
1753
+ return _commands.joinUp.call(void 0, state, dispatch);
1754
+ };
1755
+ var joinDown = () => ({ state, dispatch }) => {
1756
+ return _commands.joinDown.call(void 0, state, dispatch);
1757
+ };
1758
+ var joinBackward = () => ({ state, dispatch }) => {
1759
+ return _commands.joinBackward.call(void 0, state, dispatch);
1760
+ };
1761
+ var joinForward = () => ({ state, dispatch }) => {
1762
+ return _commands.joinForward.call(void 0, state, dispatch);
1763
+ };
1764
+ var joinItemBackward = () => ({ state, dispatch, tr }) => {
1765
+ try {
1766
+ const point = _transform.joinPoint.call(void 0, state.doc, state.selection.$from.pos, -1);
1767
+ if (point === null || point === void 0) {
1768
+ return false;
1769
+ }
1770
+ tr.join(point, 2);
1771
+ if (dispatch) {
1772
+ dispatch(tr);
1773
+ }
1774
+ return true;
1775
+ } catch (e) {
1776
+ return false;
1777
+ }
1778
+ };
1779
+ var joinItemForward = () => ({ state, dispatch, tr }) => {
1780
+ try {
1781
+ const point = _transform.joinPoint.call(void 0, state.doc, state.selection.$from.pos, 1);
1782
+ if (point === null || point === void 0) {
1783
+ return false;
1784
+ }
1785
+ tr.join(point, 2);
1786
+ if (dispatch) {
1787
+ dispatch(tr);
1788
+ }
1789
+ return true;
1790
+ } catch (e) {
1791
+ return false;
1792
+ }
1793
+ };
1794
+ var joinTextblockBackward = () => ({ state, dispatch }) => {
1795
+ return _commands.joinTextblockBackward.call(void 0, state, dispatch);
1796
+ };
1797
+ var joinTextblockForward = () => ({ state, dispatch }) => {
1798
+ return _commands.joinTextblockForward.call(void 0, state, dispatch);
1799
+ };
1800
+ function isMacOS() {
1801
+ return typeof navigator !== "undefined" ? /Mac/.test(navigator.platform) : false;
1802
+ }
1803
+ function normalizeKeyName(name) {
1804
+ const parts = name.split(/-(?!$)/);
1805
+ let result = parts[parts.length - 1];
1806
+ if (result === "Space") {
1807
+ result = " ";
1808
+ }
1809
+ let alt;
1810
+ let ctrl;
1811
+ let shift;
1812
+ let meta;
1813
+ for (let i = 0; i < parts.length - 1; i += 1) {
1814
+ const mod = parts[i];
1815
+ if (/^(cmd|meta|m)$/i.test(mod)) {
1816
+ meta = true;
1817
+ } else if (/^a(lt)?$/i.test(mod)) {
1818
+ alt = true;
1819
+ } else if (/^(c|ctrl|control)$/i.test(mod)) {
1820
+ ctrl = true;
1821
+ } else if (/^s(hift)?$/i.test(mod)) {
1822
+ shift = true;
1823
+ } else if (/^mod$/i.test(mod)) {
1824
+ if (isiOS() || isMacOS()) {
1825
+ meta = true;
1826
+ } else {
1827
+ ctrl = true;
1828
+ }
1829
+ } else {
1830
+ throw new Error(`Unrecognized modifier name: ${mod}`);
1831
+ }
1832
+ }
1833
+ if (alt) {
1834
+ result = `Alt-${result}`;
1835
+ }
1836
+ if (ctrl) {
1837
+ result = `Ctrl-${result}`;
1838
+ }
1839
+ if (meta) {
1840
+ result = `Meta-${result}`;
1841
+ }
1842
+ if (shift) {
1843
+ result = `Shift-${result}`;
1844
+ }
1845
+ return result;
1846
+ }
1847
+ var keyboardShortcut = (name) => ({ editor, view, tr, dispatch }) => {
1848
+ const keys = normalizeKeyName(name).split(/-(?!$)/);
1849
+ const key = keys.find((item) => !["Alt", "Ctrl", "Meta", "Shift"].includes(item));
1850
+ const event = new KeyboardEvent("keydown", {
1851
+ key: key === "Space" ? " " : key,
1852
+ altKey: keys.includes("Alt"),
1853
+ ctrlKey: keys.includes("Ctrl"),
1854
+ metaKey: keys.includes("Meta"),
1855
+ shiftKey: keys.includes("Shift"),
1856
+ bubbles: true,
1857
+ cancelable: true
1858
+ });
1859
+ const capturedTransaction = editor.captureTransaction(() => {
1860
+ view.someProp("handleKeyDown", (f) => f(view, event));
1861
+ });
1862
+ capturedTransaction === null || capturedTransaction === void 0 ? void 0 : capturedTransaction.steps.forEach((step) => {
1863
+ const newStep = step.map(tr.mapping);
1864
+ if (newStep && dispatch) {
1865
+ tr.maybeStep(newStep);
1866
+ }
1867
+ });
1868
+ return true;
1869
+ };
1870
+ function isNodeActive(state, typeOrName, attributes = {}) {
1871
+ const { from, to, empty } = state.selection;
1872
+ const type = typeOrName ? getNodeType(typeOrName, state.schema) : null;
1873
+ const nodeRanges = [];
1874
+ state.doc.nodesBetween(from, to, (node, pos) => {
1875
+ if (node.isText) {
1876
+ return;
1877
+ }
1878
+ const relativeFrom = Math.max(from, pos);
1879
+ const relativeTo = Math.min(to, pos + node.nodeSize);
1880
+ nodeRanges.push({
1881
+ node,
1882
+ from: relativeFrom,
1883
+ to: relativeTo
1884
+ });
1885
+ });
1886
+ const selectionRange = to - from;
1887
+ const matchedNodeRanges = nodeRanges.filter((nodeRange) => {
1888
+ if (!type) {
1889
+ return true;
1890
+ }
1891
+ return type.name === nodeRange.node.type.name;
1892
+ }).filter((nodeRange) => objectIncludes(nodeRange.node.attrs, attributes, { strict: false }));
1893
+ if (empty) {
1894
+ return !!matchedNodeRanges.length;
1895
+ }
1896
+ const range = matchedNodeRanges.reduce((sum, nodeRange) => sum + nodeRange.to - nodeRange.from, 0);
1897
+ return range >= selectionRange;
1898
+ }
1899
+ var lift = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
1900
+ const type = getNodeType(typeOrName, state.schema);
1901
+ const isActive = isNodeActive(state, type, attributes);
1902
+ if (!isActive) {
1903
+ return false;
1904
+ }
1905
+ return _commands.lift.call(void 0, state, dispatch);
1906
+ };
1907
+ var liftEmptyBlock = () => ({ state, dispatch }) => {
1908
+ return _commands.liftEmptyBlock.call(void 0, state, dispatch);
1909
+ };
1910
+ var liftListItem = (typeOrName) => ({ state, dispatch }) => {
1911
+ const type = getNodeType(typeOrName, state.schema);
1912
+ return _schemalist.liftListItem.call(void 0, type)(state, dispatch);
1913
+ };
1914
+ var newlineInCode = () => ({ state, dispatch }) => {
1915
+ return _commands.newlineInCode.call(void 0, state, dispatch);
1916
+ };
1917
+ function getSchemaTypeNameByName(name, schema) {
1918
+ if (schema.nodes[name]) {
1919
+ return "node";
1920
+ }
1921
+ if (schema.marks[name]) {
1922
+ return "mark";
1923
+ }
1924
+ return null;
1925
+ }
1926
+ function deleteProps(obj, propOrProps) {
1927
+ const props = typeof propOrProps === "string" ? [propOrProps] : propOrProps;
1928
+ return Object.keys(obj).reduce((newObj, prop) => {
1929
+ if (!props.includes(prop)) {
1930
+ newObj[prop] = obj[prop];
1931
+ }
1932
+ return newObj;
1933
+ }, {});
1934
+ }
1935
+ var resetAttributes = (typeOrName, attributes) => ({ tr, state, dispatch }) => {
1936
+ let nodeType = null;
1937
+ let markType = null;
1938
+ const schemaType = getSchemaTypeNameByName(typeof typeOrName === "string" ? typeOrName : typeOrName.name, state.schema);
1939
+ if (!schemaType) {
1940
+ return false;
1941
+ }
1942
+ if (schemaType === "node") {
1943
+ nodeType = getNodeType(typeOrName, state.schema);
1944
+ }
1945
+ if (schemaType === "mark") {
1946
+ markType = getMarkType(typeOrName, state.schema);
1947
+ }
1948
+ if (dispatch) {
1949
+ tr.selection.ranges.forEach((range) => {
1950
+ state.doc.nodesBetween(range.$from.pos, range.$to.pos, (node, pos) => {
1951
+ if (nodeType && nodeType === node.type) {
1952
+ tr.setNodeMarkup(pos, void 0, deleteProps(node.attrs, attributes));
1953
+ }
1954
+ if (markType && node.marks.length) {
1955
+ node.marks.forEach((mark) => {
1956
+ if (markType === mark.type) {
1957
+ tr.addMark(pos, pos + node.nodeSize, markType.create(deleteProps(mark.attrs, attributes)));
1958
+ }
1959
+ });
1960
+ }
1961
+ });
1962
+ });
1963
+ }
1964
+ return true;
1965
+ };
1966
+ var scrollIntoView = () => ({ tr, dispatch }) => {
1967
+ if (dispatch) {
1968
+ tr.scrollIntoView();
1969
+ }
1970
+ return true;
1971
+ };
1972
+ var selectAll = () => ({ tr, commands: commands2 }) => {
1973
+ return commands2.setTextSelection({
1974
+ from: 0,
1975
+ to: tr.doc.content.size
1976
+ });
1977
+ };
1978
+ var selectNodeBackward = () => ({ state, dispatch }) => {
1979
+ return _commands.selectNodeBackward.call(void 0, state, dispatch);
1980
+ };
1981
+ var selectNodeForward = () => ({ state, dispatch }) => {
1982
+ return _commands.selectNodeForward.call(void 0, state, dispatch);
1983
+ };
1984
+ var selectParentNode = () => ({ state, dispatch }) => {
1985
+ return _commands.selectParentNode.call(void 0, state, dispatch);
1986
+ };
1987
+ var selectTextblockEnd = () => ({ state, dispatch }) => {
1988
+ return _commands.selectTextblockEnd.call(void 0, state, dispatch);
1989
+ };
1990
+ var selectTextblockStart = () => ({ state, dispatch }) => {
1991
+ return _commands.selectTextblockStart.call(void 0, state, dispatch);
1992
+ };
1993
+ function createDocument(content, schema, parseOptions = {}, options = {}) {
1994
+ return createNodeFromContent(content, schema, {
1995
+ slice: false,
1996
+ parseOptions,
1997
+ errorOnInvalidContent: options.errorOnInvalidContent
1998
+ });
1999
+ }
2000
+ var setContent = (content, emitUpdate = false, parseOptions = {}, options = {}) => ({ editor, tr, dispatch, commands: commands2 }) => {
2001
+ var _a, _b;
2002
+ const { doc } = tr;
2003
+ if (parseOptions.preserveWhitespace !== "full") {
2004
+ const document2 = createDocument(content, editor.schema, parseOptions, {
2005
+ errorOnInvalidContent: (_a = options.errorOnInvalidContent) !== null && _a !== void 0 ? _a : editor.options.enableContentCheck
2006
+ });
2007
+ if (dispatch) {
2008
+ tr.replaceWith(0, doc.content.size, document2).setMeta("preventUpdate", !emitUpdate);
2009
+ }
2010
+ return true;
2011
+ }
2012
+ if (dispatch) {
2013
+ tr.setMeta("preventUpdate", !emitUpdate);
2014
+ }
2015
+ return commands2.insertContentAt({ from: 0, to: doc.content.size }, content, {
2016
+ parseOptions,
2017
+ errorOnInvalidContent: (_b = options.errorOnInvalidContent) !== null && _b !== void 0 ? _b : editor.options.enableContentCheck
2018
+ });
2019
+ };
2020
+ function getMarkAttributes(state, typeOrName) {
2021
+ const type = getMarkType(typeOrName, state.schema);
2022
+ const { from, to, empty } = state.selection;
2023
+ const marks = [];
2024
+ if (empty) {
2025
+ if (state.storedMarks) {
2026
+ marks.push(...state.storedMarks);
2027
+ }
2028
+ marks.push(...state.selection.$head.marks());
2029
+ } else {
2030
+ state.doc.nodesBetween(from, to, (node) => {
2031
+ marks.push(...node.marks);
2032
+ });
2033
+ }
2034
+ const mark = marks.find((markItem) => markItem.type.name === type.name);
2035
+ if (!mark) {
2036
+ return {};
2037
+ }
2038
+ return { ...mark.attrs };
2039
+ }
2040
+ function defaultBlockAt(match) {
2041
+ for (let i = 0; i < match.edgeCount; i += 1) {
2042
+ const { type } = match.edge(i);
2043
+ if (type.isTextblock && !type.hasRequiredAttrs()) {
2044
+ return type;
2045
+ }
2046
+ }
2047
+ return null;
2048
+ }
2049
+ function findParentNodeClosestToPos($pos, predicate) {
2050
+ for (let i = $pos.depth; i > 0; i -= 1) {
2051
+ const node = $pos.node(i);
2052
+ if (predicate(node)) {
2053
+ return {
2054
+ pos: i > 0 ? $pos.before(i) : 0,
2055
+ start: $pos.start(i),
2056
+ depth: i,
2057
+ node
2058
+ };
2059
+ }
2060
+ }
2061
+ }
2062
+ function findParentNode(predicate) {
2063
+ return (selection) => findParentNodeClosestToPos(selection.$from, predicate);
2064
+ }
2065
+ function getSchema(extensions, editor) {
2066
+ const resolvedExtensions = ExtensionManager.resolve(extensions);
2067
+ return getSchemaByResolvedExtensions(resolvedExtensions, editor);
2068
+ }
2069
+ function getText(node, options) {
2070
+ const range = {
2071
+ from: 0,
2072
+ to: node.content.size
2073
+ };
2074
+ return getTextBetween(node, range, options);
2075
+ }
2076
+ function getSplittedAttributes(extensionAttributes, typeName, attributes) {
2077
+ return Object.fromEntries(Object.entries(attributes).filter(([name]) => {
2078
+ const extensionAttribute = extensionAttributes.find((item) => {
2079
+ return item.type === typeName && item.name === name;
2080
+ });
2081
+ if (!extensionAttribute) {
2082
+ return false;
2083
+ }
2084
+ return extensionAttribute.attribute.keepOnSplit;
2085
+ }));
2086
+ }
2087
+ function isMarkActive(state, typeOrName, attributes = {}) {
2088
+ const { empty, ranges } = state.selection;
2089
+ const type = typeOrName ? getMarkType(typeOrName, state.schema) : null;
2090
+ if (empty) {
2091
+ return !!(state.storedMarks || state.selection.$from.marks()).filter((mark) => {
2092
+ if (!type) {
2093
+ return true;
2094
+ }
2095
+ return type.name === mark.type.name;
2096
+ }).find((mark) => objectIncludes(mark.attrs, attributes, { strict: false }));
2097
+ }
2098
+ let selectionRange = 0;
2099
+ const markRanges = [];
2100
+ ranges.forEach(({ $from, $to }) => {
2101
+ const from = $from.pos;
2102
+ const to = $to.pos;
2103
+ state.doc.nodesBetween(from, to, (node, pos) => {
2104
+ if (!node.isText && !node.marks.length) {
2105
+ return;
2106
+ }
2107
+ const relativeFrom = Math.max(from, pos);
2108
+ const relativeTo = Math.min(to, pos + node.nodeSize);
2109
+ const range2 = relativeTo - relativeFrom;
2110
+ selectionRange += range2;
2111
+ markRanges.push(...node.marks.map((mark) => ({
2112
+ mark,
2113
+ from: relativeFrom,
2114
+ to: relativeTo
2115
+ })));
2116
+ });
2117
+ });
2118
+ if (selectionRange === 0) {
2119
+ return false;
2120
+ }
2121
+ const matchedRange = markRanges.filter((markRange) => {
2122
+ if (!type) {
2123
+ return true;
2124
+ }
2125
+ return type.name === markRange.mark.type.name;
2126
+ }).filter((markRange) => objectIncludes(markRange.mark.attrs, attributes, { strict: false })).reduce((sum, markRange) => sum + markRange.to - markRange.from, 0);
2127
+ const excludedRange = markRanges.filter((markRange) => {
2128
+ if (!type) {
2129
+ return true;
2130
+ }
2131
+ return markRange.mark.type !== type && markRange.mark.type.excludes(type);
2132
+ }).reduce((sum, markRange) => sum + markRange.to - markRange.from, 0);
2133
+ const range = matchedRange > 0 ? matchedRange + excludedRange : matchedRange;
2134
+ return range >= selectionRange;
2135
+ }
2136
+ function isList(name, extensions) {
2137
+ const { nodeExtensions } = splitExtensions(extensions);
2138
+ const extension = nodeExtensions.find((item) => item.name === name);
2139
+ if (!extension) {
2140
+ return false;
2141
+ }
2142
+ const context = {
2143
+ name: extension.name,
2144
+ options: extension.options,
2145
+ storage: extension.storage
2146
+ };
2147
+ const group = callOrReturn(getExtensionField(extension, "group", context));
2148
+ if (typeof group !== "string") {
2149
+ return false;
2150
+ }
2151
+ return group.split(" ").includes("list");
2152
+ }
2153
+ function isNodeEmpty(node, { checkChildren = true, ignoreWhitespace = false } = {}) {
2154
+ var _a;
2155
+ if (ignoreWhitespace) {
2156
+ if (node.type.name === "hardBreak") {
2157
+ return true;
2158
+ }
2159
+ if (node.isText) {
2160
+ return /^\s*$/m.test((_a = node.text) !== null && _a !== void 0 ? _a : "");
2161
+ }
2162
+ }
2163
+ if (node.isText) {
2164
+ return !node.text;
2165
+ }
2166
+ if (node.isAtom || node.isLeaf) {
2167
+ return false;
2168
+ }
2169
+ if (node.content.childCount === 0) {
2170
+ return true;
2171
+ }
2172
+ if (checkChildren) {
2173
+ let isContentEmpty = true;
2174
+ node.content.forEach((childNode) => {
2175
+ if (isContentEmpty === false) {
2176
+ return;
2177
+ }
2178
+ if (!isNodeEmpty(childNode, { ignoreWhitespace, checkChildren })) {
2179
+ isContentEmpty = false;
2180
+ }
2181
+ });
2182
+ return isContentEmpty;
2183
+ }
2184
+ return false;
2185
+ }
2186
+ function canSetMark(state, tr, newMarkType) {
2187
+ var _a;
2188
+ const { selection } = tr;
2189
+ let cursor = null;
2190
+ if (isTextSelection(selection)) {
2191
+ cursor = selection.$cursor;
2192
+ }
2193
+ if (cursor) {
2194
+ const currentMarks = (_a = state.storedMarks) !== null && _a !== void 0 ? _a : cursor.marks();
2195
+ return !!newMarkType.isInSet(currentMarks) || !currentMarks.some((mark) => mark.type.excludes(newMarkType));
2196
+ }
2197
+ const { ranges } = selection;
2198
+ return ranges.some(({ $from, $to }) => {
2199
+ let someNodeSupportsMark = $from.depth === 0 ? state.doc.inlineContent && state.doc.type.allowsMarkType(newMarkType) : false;
2200
+ state.doc.nodesBetween($from.pos, $to.pos, (node, _pos, parent) => {
2201
+ if (someNodeSupportsMark) {
2202
+ return false;
2203
+ }
2204
+ if (node.isInline) {
2205
+ const parentAllowsMarkType = !parent || parent.type.allowsMarkType(newMarkType);
2206
+ const currentMarksAllowMarkType = !!newMarkType.isInSet(node.marks) || !node.marks.some((otherMark) => otherMark.type.excludes(newMarkType));
2207
+ someNodeSupportsMark = parentAllowsMarkType && currentMarksAllowMarkType;
2208
+ }
2209
+ return !someNodeSupportsMark;
2210
+ });
2211
+ return someNodeSupportsMark;
2212
+ });
2213
+ }
2214
+ var setMark = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {
2215
+ const { selection } = tr;
2216
+ const { empty, ranges } = selection;
2217
+ const type = getMarkType(typeOrName, state.schema);
2218
+ if (dispatch) {
2219
+ if (empty) {
2220
+ const oldAttributes = getMarkAttributes(state, type);
2221
+ tr.addStoredMark(type.create({
2222
+ ...oldAttributes,
2223
+ ...attributes
2224
+ }));
2225
+ } else {
2226
+ ranges.forEach((range) => {
2227
+ const from = range.$from.pos;
2228
+ const to = range.$to.pos;
2229
+ state.doc.nodesBetween(from, to, (node, pos) => {
2230
+ const trimmedFrom = Math.max(pos, from);
2231
+ const trimmedTo = Math.min(pos + node.nodeSize, to);
2232
+ const someHasMark = node.marks.find((mark) => mark.type === type);
2233
+ if (someHasMark) {
2234
+ node.marks.forEach((mark) => {
2235
+ if (type === mark.type) {
2236
+ tr.addMark(trimmedFrom, trimmedTo, type.create({
2237
+ ...mark.attrs,
2238
+ ...attributes
2239
+ }));
2240
+ }
2241
+ });
2242
+ } else {
2243
+ tr.addMark(trimmedFrom, trimmedTo, type.create(attributes));
2244
+ }
2245
+ });
2246
+ });
2247
+ }
2248
+ }
2249
+ return canSetMark(state, tr, type);
2250
+ };
2251
+ var setMeta = (key, value) => ({ tr }) => {
2252
+ tr.setMeta(key, value);
2253
+ return true;
2254
+ };
2255
+ var setNode = (typeOrName, attributes = {}) => ({ state, dispatch, chain }) => {
2256
+ const type = getNodeType(typeOrName, state.schema);
2257
+ if (!type.isTextblock) {
2258
+ console.warn('[tiptap warn]: Currently "setNode()" only supports text block nodes.');
2259
+ return false;
2260
+ }
2261
+ return chain().command(({ commands: commands2 }) => {
2262
+ const canSetBlock = _commands.setBlockType.call(void 0, type, attributes)(state);
2263
+ if (canSetBlock) {
2264
+ return true;
2265
+ }
2266
+ return commands2.clearNodes();
2267
+ }).command(({ state: updatedState }) => {
2268
+ return _commands.setBlockType.call(void 0, type, attributes)(updatedState, dispatch);
2269
+ }).run();
2270
+ };
2271
+ var setNodeSelection = (position) => ({ tr, dispatch }) => {
2272
+ if (dispatch) {
2273
+ const { doc } = tr;
2274
+ const from = minMax(position, 0, doc.content.size);
2275
+ const selection = _state.NodeSelection.create(doc, from);
2276
+ tr.setSelection(selection);
2277
+ }
2278
+ return true;
2279
+ };
2280
+ var setTextSelection = (position) => ({ tr, dispatch }) => {
2281
+ if (dispatch) {
2282
+ const { doc } = tr;
2283
+ const { from, to } = typeof position === "number" ? { from: position, to: position } : position;
2284
+ const minPos = _state.TextSelection.atStart(doc).from;
2285
+ const maxPos = _state.TextSelection.atEnd(doc).to;
2286
+ const resolvedFrom = minMax(from, minPos, maxPos);
2287
+ const resolvedEnd = minMax(to, minPos, maxPos);
2288
+ const selection = _state.TextSelection.create(doc, resolvedFrom, resolvedEnd);
2289
+ tr.setSelection(selection);
2290
+ }
2291
+ return true;
2292
+ };
2293
+ var sinkListItem = (typeOrName) => ({ state, dispatch }) => {
2294
+ const type = getNodeType(typeOrName, state.schema);
2295
+ return _schemalist.sinkListItem.call(void 0, type)(state, dispatch);
2296
+ };
2297
+ function ensureMarks(state, splittableMarks) {
2298
+ const marks = state.storedMarks || state.selection.$to.parentOffset && state.selection.$from.marks();
2299
+ if (marks) {
2300
+ const filteredMarks = marks.filter((mark) => splittableMarks === null || splittableMarks === void 0 ? void 0 : splittableMarks.includes(mark.type.name));
2301
+ state.tr.ensureMarks(filteredMarks);
2302
+ }
2303
+ }
2304
+ var splitBlock = ({ keepMarks = true } = {}) => ({ tr, state, dispatch, editor }) => {
2305
+ const { selection, doc } = tr;
2306
+ const { $from, $to } = selection;
2307
+ const extensionAttributes = editor.extensionManager.attributes;
2308
+ const newAttributes = getSplittedAttributes(extensionAttributes, $from.node().type.name, $from.node().attrs);
2309
+ if (selection instanceof _state.NodeSelection && selection.node.isBlock) {
2310
+ if (!$from.parentOffset || !_transform.canSplit.call(void 0, doc, $from.pos)) {
2311
+ return false;
2312
+ }
2313
+ if (dispatch) {
2314
+ if (keepMarks) {
2315
+ ensureMarks(state, editor.extensionManager.splittableMarks);
2316
+ }
2317
+ tr.split($from.pos).scrollIntoView();
2318
+ }
2319
+ return true;
2320
+ }
2321
+ if (!$from.parent.isBlock) {
2322
+ return false;
2323
+ }
2324
+ const atEnd = $to.parentOffset === $to.parent.content.size;
2325
+ const deflt = $from.depth === 0 ? void 0 : defaultBlockAt($from.node(-1).contentMatchAt($from.indexAfter(-1)));
2326
+ let types = atEnd && deflt ? [
2327
+ {
2328
+ type: deflt,
2329
+ attrs: newAttributes
2330
+ }
2331
+ ] : void 0;
2332
+ let can = _transform.canSplit.call(void 0, tr.doc, tr.mapping.map($from.pos), 1, types);
2333
+ if (!types && !can && _transform.canSplit.call(void 0, tr.doc, tr.mapping.map($from.pos), 1, deflt ? [{ type: deflt }] : void 0)) {
2334
+ can = true;
2335
+ types = deflt ? [
2336
+ {
2337
+ type: deflt,
2338
+ attrs: newAttributes
2339
+ }
2340
+ ] : void 0;
2341
+ }
2342
+ if (dispatch) {
2343
+ if (can) {
2344
+ if (selection instanceof _state.TextSelection) {
2345
+ tr.deleteSelection();
2346
+ }
2347
+ tr.split(tr.mapping.map($from.pos), 1, types);
2348
+ if (deflt && !atEnd && !$from.parentOffset && $from.parent.type !== deflt) {
2349
+ const first2 = tr.mapping.map($from.before());
2350
+ const $first = tr.doc.resolve(first2);
2351
+ if ($from.node(-1).canReplaceWith($first.index(), $first.index() + 1, deflt)) {
2352
+ tr.setNodeMarkup(tr.mapping.map($from.before()), deflt);
2353
+ }
2354
+ }
2355
+ }
2356
+ if (keepMarks) {
2357
+ ensureMarks(state, editor.extensionManager.splittableMarks);
2358
+ }
2359
+ tr.scrollIntoView();
2360
+ }
2361
+ return can;
2362
+ };
2363
+ var splitListItem = (typeOrName, overrideAttrs = {}) => ({ tr, state, dispatch, editor }) => {
2364
+ var _a;
2365
+ const type = getNodeType(typeOrName, state.schema);
2366
+ const { $from, $to } = state.selection;
2367
+ const node = state.selection.node;
2368
+ if (node && node.isBlock || $from.depth < 2 || !$from.sameParent($to)) {
2369
+ return false;
2370
+ }
2371
+ const grandParent = $from.node(-1);
2372
+ if (grandParent.type !== type) {
2373
+ return false;
2374
+ }
2375
+ const extensionAttributes = editor.extensionManager.attributes;
2376
+ if ($from.parent.content.size === 0 && $from.node(-1).childCount === $from.indexAfter(-1)) {
2377
+ if ($from.depth === 2 || $from.node(-3).type !== type || $from.index(-2) !== $from.node(-2).childCount - 1) {
2378
+ return false;
2379
+ }
2380
+ if (dispatch) {
2381
+ let wrap = _model.Fragment.empty;
2382
+ const depthBefore = $from.index(-1) ? 1 : $from.index(-2) ? 2 : 3;
2383
+ for (let d = $from.depth - depthBefore; d >= $from.depth - 3; d -= 1) {
2384
+ wrap = _model.Fragment.from($from.node(d).copy(wrap));
2385
+ }
2386
+ const depthAfter = $from.indexAfter(-1) < $from.node(-2).childCount ? 1 : $from.indexAfter(-2) < $from.node(-3).childCount ? 2 : 3;
2387
+ const newNextTypeAttributes2 = {
2388
+ ...getSplittedAttributes(extensionAttributes, $from.node().type.name, $from.node().attrs),
2389
+ ...overrideAttrs
2390
+ };
2391
+ const nextType2 = ((_a = type.contentMatch.defaultType) === null || _a === void 0 ? void 0 : _a.createAndFill(newNextTypeAttributes2)) || void 0;
2392
+ wrap = wrap.append(_model.Fragment.from(type.createAndFill(null, nextType2) || void 0));
2393
+ const start = $from.before($from.depth - (depthBefore - 1));
2394
+ tr.replace(start, $from.after(-depthAfter), new (0, _model.Slice)(wrap, 4 - depthBefore, 0));
2395
+ let sel = -1;
2396
+ tr.doc.nodesBetween(start, tr.doc.content.size, (n, pos) => {
2397
+ if (sel > -1) {
2398
+ return false;
2399
+ }
2400
+ if (n.isTextblock && n.content.size === 0) {
2401
+ sel = pos + 1;
2402
+ }
2403
+ });
2404
+ if (sel > -1) {
2405
+ tr.setSelection(_state.TextSelection.near(tr.doc.resolve(sel)));
2406
+ }
2407
+ tr.scrollIntoView();
2408
+ }
2409
+ return true;
2410
+ }
2411
+ const nextType = $to.pos === $from.end() ? grandParent.contentMatchAt(0).defaultType : null;
2412
+ const newTypeAttributes = {
2413
+ ...getSplittedAttributes(extensionAttributes, grandParent.type.name, grandParent.attrs),
2414
+ ...overrideAttrs
2415
+ };
2416
+ const newNextTypeAttributes = {
2417
+ ...getSplittedAttributes(extensionAttributes, $from.node().type.name, $from.node().attrs),
2418
+ ...overrideAttrs
2419
+ };
2420
+ tr.delete($from.pos, $to.pos);
2421
+ const types = nextType ? [
2422
+ { type, attrs: newTypeAttributes },
2423
+ { type: nextType, attrs: newNextTypeAttributes }
2424
+ ] : [{ type, attrs: newTypeAttributes }];
2425
+ if (!_transform.canSplit.call(void 0, tr.doc, $from.pos, 2)) {
2426
+ return false;
2427
+ }
2428
+ if (dispatch) {
2429
+ const { selection, storedMarks } = state;
2430
+ const { splittableMarks } = editor.extensionManager;
2431
+ const marks = storedMarks || selection.$to.parentOffset && selection.$from.marks();
2432
+ tr.split($from.pos, 2, types).scrollIntoView();
2433
+ if (!marks || !dispatch) {
2434
+ return true;
2435
+ }
2436
+ const filteredMarks = marks.filter((mark) => splittableMarks.includes(mark.type.name));
2437
+ tr.ensureMarks(filteredMarks);
2438
+ }
2439
+ return true;
2440
+ };
2441
+ var joinListBackwards = (tr, listType) => {
2442
+ const list = findParentNode((node) => node.type === listType)(tr.selection);
2443
+ if (!list) {
2444
+ return true;
2445
+ }
2446
+ const before = tr.doc.resolve(Math.max(0, list.pos - 1)).before(list.depth);
2447
+ if (before === void 0) {
2448
+ return true;
2449
+ }
2450
+ const nodeBefore = tr.doc.nodeAt(before);
2451
+ const canJoinBackwards = list.node.type === (nodeBefore === null || nodeBefore === void 0 ? void 0 : nodeBefore.type) && _transform.canJoin.call(void 0, tr.doc, list.pos);
2452
+ if (!canJoinBackwards) {
2453
+ return true;
2454
+ }
2455
+ tr.join(list.pos);
2456
+ return true;
2457
+ };
2458
+ var joinListForwards = (tr, listType) => {
2459
+ const list = findParentNode((node) => node.type === listType)(tr.selection);
2460
+ if (!list) {
2461
+ return true;
2462
+ }
2463
+ const after = tr.doc.resolve(list.start).after(list.depth);
2464
+ if (after === void 0) {
2465
+ return true;
2466
+ }
2467
+ const nodeAfter = tr.doc.nodeAt(after);
2468
+ const canJoinForwards = list.node.type === (nodeAfter === null || nodeAfter === void 0 ? void 0 : nodeAfter.type) && _transform.canJoin.call(void 0, tr.doc, after);
2469
+ if (!canJoinForwards) {
2470
+ return true;
2471
+ }
2472
+ tr.join(after);
2473
+ return true;
2474
+ };
2475
+ var toggleList = (listTypeOrName, itemTypeOrName, keepMarks, attributes = {}) => ({ editor, tr, state, dispatch, chain, commands: commands2, can }) => {
2476
+ const { extensions, splittableMarks } = editor.extensionManager;
2477
+ const listType = getNodeType(listTypeOrName, state.schema);
2478
+ const itemType = getNodeType(itemTypeOrName, state.schema);
2479
+ const { selection, storedMarks } = state;
2480
+ const { $from, $to } = selection;
2481
+ const range = $from.blockRange($to);
2482
+ const marks = storedMarks || selection.$to.parentOffset && selection.$from.marks();
2483
+ if (!range) {
2484
+ return false;
2485
+ }
2486
+ const parentList = findParentNode((node) => isList(node.type.name, extensions))(selection);
2487
+ if (range.depth >= 1 && parentList && range.depth - parentList.depth <= 1) {
2488
+ if (parentList.node.type === listType) {
2489
+ return commands2.liftListItem(itemType);
2490
+ }
2491
+ if (isList(parentList.node.type.name, extensions) && listType.validContent(parentList.node.content) && dispatch) {
2492
+ return chain().command(() => {
2493
+ tr.setNodeMarkup(parentList.pos, listType);
2494
+ return true;
2495
+ }).command(() => joinListBackwards(tr, listType)).command(() => joinListForwards(tr, listType)).run();
2496
+ }
2497
+ }
2498
+ if (!keepMarks || !marks || !dispatch) {
2499
+ return chain().command(() => {
2500
+ const canWrapInList = can().wrapInList(listType, attributes);
2501
+ if (canWrapInList) {
2502
+ return true;
2503
+ }
2504
+ return commands2.clearNodes();
2505
+ }).wrapInList(listType, attributes).command(() => joinListBackwards(tr, listType)).command(() => joinListForwards(tr, listType)).run();
2506
+ }
2507
+ return chain().command(() => {
2508
+ const canWrapInList = can().wrapInList(listType, attributes);
2509
+ const filteredMarks = marks.filter((mark) => splittableMarks.includes(mark.type.name));
2510
+ tr.ensureMarks(filteredMarks);
2511
+ if (canWrapInList) {
2512
+ return true;
2513
+ }
2514
+ return commands2.clearNodes();
2515
+ }).wrapInList(listType, attributes).command(() => joinListBackwards(tr, listType)).command(() => joinListForwards(tr, listType)).run();
2516
+ };
2517
+ var toggleMark = (typeOrName, attributes = {}, options = {}) => ({ state, commands: commands2 }) => {
2518
+ const { extendEmptyMarkRange = false } = options;
2519
+ const type = getMarkType(typeOrName, state.schema);
2520
+ const isActive = isMarkActive(state, type, attributes);
2521
+ if (isActive) {
2522
+ return commands2.unsetMark(type, { extendEmptyMarkRange });
2523
+ }
2524
+ return commands2.setMark(type, attributes);
2525
+ };
2526
+ var toggleNode = (typeOrName, toggleTypeOrName, attributes = {}) => ({ state, commands: commands2 }) => {
2527
+ const type = getNodeType(typeOrName, state.schema);
2528
+ const toggleType = getNodeType(toggleTypeOrName, state.schema);
2529
+ const isActive = isNodeActive(state, type, attributes);
2530
+ let attributesToCopy;
2531
+ if (state.selection.$anchor.sameParent(state.selection.$head)) {
2532
+ attributesToCopy = state.selection.$anchor.parent.attrs;
2533
+ }
2534
+ if (isActive) {
2535
+ return commands2.setNode(toggleType, attributesToCopy);
2536
+ }
2537
+ return commands2.setNode(type, { ...attributesToCopy, ...attributes });
2538
+ };
2539
+ var toggleWrap = (typeOrName, attributes = {}) => ({ state, commands: commands2 }) => {
2540
+ const type = getNodeType(typeOrName, state.schema);
2541
+ const isActive = isNodeActive(state, type, attributes);
2542
+ if (isActive) {
2543
+ return commands2.lift(type);
2544
+ }
2545
+ return commands2.wrapIn(type, attributes);
2546
+ };
2547
+ var undoInputRule = () => ({ state, dispatch }) => {
2548
+ const plugins = state.plugins;
2549
+ for (let i = 0; i < plugins.length; i += 1) {
2550
+ const plugin = plugins[i];
2551
+ let undoable;
2552
+ if (plugin.spec.isInputRules && (undoable = plugin.getState(state))) {
2553
+ if (dispatch) {
2554
+ const tr = state.tr;
2555
+ const toUndo = undoable.transform;
2556
+ for (let j = toUndo.steps.length - 1; j >= 0; j -= 1) {
2557
+ tr.step(toUndo.steps[j].invert(toUndo.docs[j]));
2558
+ }
2559
+ if (undoable.text) {
2560
+ const marks = tr.doc.resolve(undoable.from).marks();
2561
+ tr.replaceWith(undoable.from, undoable.to, state.schema.text(undoable.text, marks));
2562
+ } else {
2563
+ tr.delete(undoable.from, undoable.to);
2564
+ }
2565
+ }
2566
+ return true;
2567
+ }
2568
+ }
2569
+ return false;
2570
+ };
2571
+ var unsetAllMarks = () => ({ tr, dispatch }) => {
2572
+ const { selection } = tr;
2573
+ const { empty, ranges } = selection;
2574
+ if (empty) {
2575
+ return true;
2576
+ }
2577
+ if (dispatch) {
2578
+ ranges.forEach((range) => {
2579
+ tr.removeMark(range.$from.pos, range.$to.pos);
2580
+ });
2581
+ }
2582
+ return true;
2583
+ };
2584
+ var unsetMark = (typeOrName, options = {}) => ({ tr, state, dispatch }) => {
2585
+ var _a;
2586
+ const { extendEmptyMarkRange = false } = options;
2587
+ const { selection } = tr;
2588
+ const type = getMarkType(typeOrName, state.schema);
2589
+ const { $from, empty, ranges } = selection;
2590
+ if (!dispatch) {
2591
+ return true;
2592
+ }
2593
+ if (empty && extendEmptyMarkRange) {
2594
+ let { from, to } = selection;
2595
+ const attrs = (_a = $from.marks().find((mark) => mark.type === type)) === null || _a === void 0 ? void 0 : _a.attrs;
2596
+ const range = getMarkRange($from, type, attrs);
2597
+ if (range) {
2598
+ from = range.from;
2599
+ to = range.to;
2600
+ }
2601
+ tr.removeMark(from, to, type);
2602
+ } else {
2603
+ ranges.forEach((range) => {
2604
+ tr.removeMark(range.$from.pos, range.$to.pos, type);
2605
+ });
2606
+ }
2607
+ tr.removeStoredMark(type);
2608
+ return true;
2609
+ };
2610
+ var updateAttributes = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {
2611
+ let nodeType = null;
2612
+ let markType = null;
2613
+ const schemaType = getSchemaTypeNameByName(typeof typeOrName === "string" ? typeOrName : typeOrName.name, state.schema);
2614
+ if (!schemaType) {
2615
+ return false;
2616
+ }
2617
+ if (schemaType === "node") {
2618
+ nodeType = getNodeType(typeOrName, state.schema);
2619
+ }
2620
+ if (schemaType === "mark") {
2621
+ markType = getMarkType(typeOrName, state.schema);
2622
+ }
2623
+ if (dispatch) {
2624
+ tr.selection.ranges.forEach((range) => {
2625
+ const from = range.$from.pos;
2626
+ const to = range.$to.pos;
2627
+ state.doc.nodesBetween(from, to, (node, pos) => {
2628
+ if (nodeType && nodeType === node.type) {
2629
+ tr.setNodeMarkup(pos, void 0, {
2630
+ ...node.attrs,
2631
+ ...attributes
2632
+ });
2633
+ }
2634
+ if (markType && node.marks.length) {
2635
+ node.marks.forEach((mark) => {
2636
+ if (markType === mark.type) {
2637
+ const trimmedFrom = Math.max(pos, from);
2638
+ const trimmedTo = Math.min(pos + node.nodeSize, to);
2639
+ tr.addMark(trimmedFrom, trimmedTo, markType.create({
2640
+ ...mark.attrs,
2641
+ ...attributes
2642
+ }));
2643
+ }
2644
+ });
2645
+ }
2646
+ });
2647
+ });
2648
+ }
2649
+ return true;
2650
+ };
2651
+ var wrapIn = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
2652
+ const type = getNodeType(typeOrName, state.schema);
2653
+ return _commands.wrapIn.call(void 0, type, attributes)(state, dispatch);
2654
+ };
2655
+ var wrapInList = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
2656
+ const type = getNodeType(typeOrName, state.schema);
2657
+ return _schemalist.wrapInList.call(void 0, type, attributes)(state, dispatch);
2658
+ };
2659
+ var commands = /* @__PURE__ */ Object.freeze({
2660
+ __proto__: null,
2661
+ blur,
2662
+ clearContent,
2663
+ clearNodes,
2664
+ command,
2665
+ createParagraphNear,
2666
+ cut,
2667
+ deleteCurrentNode,
2668
+ deleteNode,
2669
+ deleteRange,
2670
+ deleteSelection,
2671
+ enter,
2672
+ exitCode,
2673
+ extendMarkRange,
2674
+ first,
2675
+ focus,
2676
+ forEach,
2677
+ insertContent,
2678
+ insertContentAt,
2679
+ joinBackward,
2680
+ joinDown,
2681
+ joinForward,
2682
+ joinItemBackward,
2683
+ joinItemForward,
2684
+ joinTextblockBackward,
2685
+ joinTextblockForward,
2686
+ joinUp,
2687
+ keyboardShortcut,
2688
+ lift,
2689
+ liftEmptyBlock,
2690
+ liftListItem,
2691
+ newlineInCode,
2692
+ resetAttributes,
2693
+ scrollIntoView,
2694
+ selectAll,
2695
+ selectNodeBackward,
2696
+ selectNodeForward,
2697
+ selectParentNode,
2698
+ selectTextblockEnd,
2699
+ selectTextblockStart,
2700
+ setContent,
2701
+ setMark,
2702
+ setMeta,
2703
+ setNode,
2704
+ setNodeSelection,
2705
+ setTextSelection,
2706
+ sinkListItem,
2707
+ splitBlock,
2708
+ splitListItem,
2709
+ toggleList,
2710
+ toggleMark,
2711
+ toggleNode,
2712
+ toggleWrap,
2713
+ undoInputRule,
2714
+ unsetAllMarks,
2715
+ unsetMark,
2716
+ updateAttributes,
2717
+ wrapIn,
2718
+ wrapInList
2719
+ });
2720
+ var Commands = Extension.create({
2721
+ name: "commands",
2722
+ addCommands() {
2723
+ return {
2724
+ ...commands
2725
+ };
2726
+ }
2727
+ });
2728
+ var Drop = Extension.create({
2729
+ name: "drop",
2730
+ addProseMirrorPlugins() {
2731
+ return [
2732
+ new (0, _state.Plugin)({
2733
+ key: new (0, _state.PluginKey)("tiptapDrop"),
2734
+ props: {
2735
+ handleDrop: (_, e, slice, moved) => {
2736
+ this.editor.emit("drop", {
2737
+ editor: this.editor,
2738
+ event: e,
2739
+ slice,
2740
+ moved
2741
+ });
2742
+ }
2743
+ }
2744
+ })
2745
+ ];
2746
+ }
2747
+ });
2748
+ var Editable = Extension.create({
2749
+ name: "editable",
2750
+ addProseMirrorPlugins() {
2751
+ return [
2752
+ new (0, _state.Plugin)({
2753
+ key: new (0, _state.PluginKey)("editable"),
2754
+ props: {
2755
+ editable: () => this.editor.options.editable
2756
+ }
2757
+ })
2758
+ ];
2759
+ }
2760
+ });
2761
+ var FocusEvents = Extension.create({
2762
+ name: "focusEvents",
2763
+ addProseMirrorPlugins() {
2764
+ const { editor } = this;
2765
+ return [
2766
+ new (0, _state.Plugin)({
2767
+ key: new (0, _state.PluginKey)("focusEvents"),
2768
+ props: {
2769
+ handleDOMEvents: {
2770
+ focus: (view, event) => {
2771
+ editor.isFocused = true;
2772
+ const transaction = editor.state.tr.setMeta("focus", { event }).setMeta("addToHistory", false);
2773
+ view.dispatch(transaction);
2774
+ return false;
2775
+ },
2776
+ blur: (view, event) => {
2777
+ editor.isFocused = false;
2778
+ const transaction = editor.state.tr.setMeta("blur", { event }).setMeta("addToHistory", false);
2779
+ view.dispatch(transaction);
2780
+ return false;
2781
+ }
2782
+ }
2783
+ }
2784
+ })
2785
+ ];
2786
+ }
2787
+ });
2788
+ var Keymap = Extension.create({
2789
+ name: "keymap",
2790
+ addKeyboardShortcuts() {
2791
+ const handleBackspace = () => this.editor.commands.first(({ commands: commands2 }) => [
2792
+ () => commands2.undoInputRule(),
2793
+ // maybe convert first text block node to default node
2794
+ () => commands2.command(({ tr }) => {
2795
+ const { selection, doc } = tr;
2796
+ const { empty, $anchor } = selection;
2797
+ const { pos, parent } = $anchor;
2798
+ const $parentPos = $anchor.parent.isTextblock && pos > 0 ? tr.doc.resolve(pos - 1) : $anchor;
2799
+ const parentIsIsolating = $parentPos.parent.type.spec.isolating;
2800
+ const parentPos = $anchor.pos - $anchor.parentOffset;
2801
+ const isAtStart = parentIsIsolating && $parentPos.parent.childCount === 1 ? parentPos === $anchor.pos : _state.Selection.atStart(doc).from === pos;
2802
+ if (!empty || !parent.type.isTextblock || parent.textContent.length || !isAtStart || isAtStart && $anchor.parent.type.name === "paragraph") {
2803
+ return false;
2804
+ }
2805
+ return commands2.clearNodes();
2806
+ }),
2807
+ () => commands2.deleteSelection(),
2808
+ () => commands2.joinBackward(),
2809
+ () => commands2.selectNodeBackward()
2810
+ ]);
2811
+ const handleDelete = () => this.editor.commands.first(({ commands: commands2 }) => [
2812
+ () => commands2.deleteSelection(),
2813
+ () => commands2.deleteCurrentNode(),
2814
+ () => commands2.joinForward(),
2815
+ () => commands2.selectNodeForward()
2816
+ ]);
2817
+ const handleEnter = () => this.editor.commands.first(({ commands: commands2 }) => [
2818
+ () => commands2.newlineInCode(),
2819
+ () => commands2.createParagraphNear(),
2820
+ () => commands2.liftEmptyBlock(),
2821
+ () => commands2.splitBlock()
2822
+ ]);
2823
+ const baseKeymap = {
2824
+ Enter: handleEnter,
2825
+ "Mod-Enter": () => this.editor.commands.exitCode(),
2826
+ Backspace: handleBackspace,
2827
+ "Mod-Backspace": handleBackspace,
2828
+ "Shift-Backspace": handleBackspace,
2829
+ Delete: handleDelete,
2830
+ "Mod-Delete": handleDelete,
2831
+ "Mod-a": () => this.editor.commands.selectAll()
2832
+ };
2833
+ const pcKeymap = {
2834
+ ...baseKeymap
2835
+ };
2836
+ const macKeymap = {
2837
+ ...baseKeymap,
2838
+ "Ctrl-h": handleBackspace,
2839
+ "Alt-Backspace": handleBackspace,
2840
+ "Ctrl-d": handleDelete,
2841
+ "Ctrl-Alt-Backspace": handleDelete,
2842
+ "Alt-Delete": handleDelete,
2843
+ "Alt-d": handleDelete,
2844
+ "Ctrl-a": () => this.editor.commands.selectTextblockStart(),
2845
+ "Ctrl-e": () => this.editor.commands.selectTextblockEnd()
2846
+ };
2847
+ if (isiOS() || isMacOS()) {
2848
+ return macKeymap;
2849
+ }
2850
+ return pcKeymap;
2851
+ },
2852
+ addProseMirrorPlugins() {
2853
+ return [
2854
+ // With this plugin we check if the whole document was selected and deleted.
2855
+ // In this case we will additionally call `clearNodes()` to convert e.g. a heading
2856
+ // to a paragraph if necessary.
2857
+ // This is an alternative to ProseMirror's `AllSelection`, which doesn’t work well
2858
+ // with many other commands.
2859
+ new (0, _state.Plugin)({
2860
+ key: new (0, _state.PluginKey)("clearDocument"),
2861
+ appendTransaction: (transactions, oldState, newState) => {
2862
+ const docChanges = transactions.some((transaction) => transaction.docChanged) && !oldState.doc.eq(newState.doc);
2863
+ const ignoreTr = transactions.some((transaction) => transaction.getMeta("preventClearDocument"));
2864
+ if (!docChanges || ignoreTr) {
2865
+ return;
2866
+ }
2867
+ const { empty, from, to } = oldState.selection;
2868
+ const allFrom = _state.Selection.atStart(oldState.doc).from;
2869
+ const allEnd = _state.Selection.atEnd(oldState.doc).to;
2870
+ const allWasSelected = from === allFrom && to === allEnd;
2871
+ if (empty || !allWasSelected) {
2872
+ return;
2873
+ }
2874
+ const isEmpty = isNodeEmpty(newState.doc);
2875
+ if (!isEmpty) {
2876
+ return;
2877
+ }
2878
+ const tr = newState.tr;
2879
+ const state = createChainableState({
2880
+ state: newState,
2881
+ transaction: tr
2882
+ });
2883
+ const { commands: commands2 } = new CommandManager({
2884
+ editor: this.editor,
2885
+ state
2886
+ });
2887
+ commands2.clearNodes();
2888
+ if (!tr.steps.length) {
2889
+ return;
2890
+ }
2891
+ return tr;
2892
+ }
2893
+ })
2894
+ ];
2895
+ }
2896
+ });
2897
+ var Paste = Extension.create({
2898
+ name: "paste",
2899
+ addProseMirrorPlugins() {
2900
+ return [
2901
+ new (0, _state.Plugin)({
2902
+ key: new (0, _state.PluginKey)("tiptapPaste"),
2903
+ props: {
2904
+ handlePaste: (_view, e, slice) => {
2905
+ this.editor.emit("paste", {
2906
+ editor: this.editor,
2907
+ event: e,
2908
+ slice
2909
+ });
2910
+ }
2911
+ }
2912
+ })
2913
+ ];
2914
+ }
2915
+ });
2916
+ var Tabindex = Extension.create({
2917
+ name: "tabindex",
2918
+ addProseMirrorPlugins() {
2919
+ return [
2920
+ new (0, _state.Plugin)({
2921
+ key: new (0, _state.PluginKey)("tabindex"),
2922
+ props: {
2923
+ attributes: () => this.editor.isEditable ? { tabindex: "0" } : {}
2924
+ }
2925
+ })
2926
+ ];
2927
+ }
2928
+ });
2929
+ var Node = class _Node {
2930
+ constructor(config = {}) {
2931
+ this.type = "node";
2932
+ this.name = "node";
2933
+ this.parent = null;
2934
+ this.child = null;
2935
+ this.config = {
2936
+ name: this.name,
2937
+ defaultOptions: {}
2938
+ };
2939
+ this.config = {
2940
+ ...this.config,
2941
+ ...config
2942
+ };
2943
+ this.name = this.config.name;
2944
+ if (config.defaultOptions && Object.keys(config.defaultOptions).length > 0) {
2945
+ console.warn(`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${this.name}".`);
2946
+ }
2947
+ this.options = this.config.defaultOptions;
2948
+ if (this.config.addOptions) {
2949
+ this.options = callOrReturn(getExtensionField(this, "addOptions", {
2950
+ name: this.name
2951
+ }));
2952
+ }
2953
+ this.storage = callOrReturn(getExtensionField(this, "addStorage", {
2954
+ name: this.name,
2955
+ options: this.options
2956
+ })) || {};
2957
+ }
2958
+ static create(config = {}) {
2959
+ return new _Node(config);
2960
+ }
2961
+ configure(options = {}) {
2962
+ const extension = this.extend({
2963
+ ...this.config,
2964
+ addOptions: () => {
2965
+ return mergeDeep(this.options, options);
2966
+ }
2967
+ });
2968
+ extension.name = this.name;
2969
+ extension.parent = this.parent;
2970
+ return extension;
2971
+ }
2972
+ extend(extendedConfig = {}) {
2973
+ const extension = new _Node(extendedConfig);
2974
+ extension.parent = this;
2975
+ this.child = extension;
2976
+ extension.name = extendedConfig.name ? extendedConfig.name : extension.parent.name;
2977
+ if (extendedConfig.defaultOptions && Object.keys(extendedConfig.defaultOptions).length > 0) {
2978
+ console.warn(`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`);
2979
+ }
2980
+ extension.options = callOrReturn(getExtensionField(extension, "addOptions", {
2981
+ name: extension.name
2982
+ }));
2983
+ extension.storage = callOrReturn(getExtensionField(extension, "addStorage", {
2984
+ name: extension.name,
2985
+ options: extension.options
2986
+ }));
2987
+ return extension;
2988
+ }
2989
+ };
2990
+
2991
+ // src/document.ts
2992
+
2993
+ var _starterkit = require('@tiptap/starter-kit'); var _starterkit2 = _interopRequireDefault(_starterkit);
2994
+ var _prosemirrormarkdown = require('prosemirror-markdown');
2995
+ var _yprosemirror = require('y-prosemirror');
2996
+ var _yjs = require('yjs');
2997
+
2998
+ // src/comment.ts
2999
+ var LIVEBLOCKS_COMMENT_MARK_TYPE = "liveblocksCommentMark";
3000
+ var CommentExtension = Mark.create({
3001
+ name: LIVEBLOCKS_COMMENT_MARK_TYPE,
3002
+ excludes: "",
3003
+ inclusive: false,
3004
+ keepOnSplit: true,
3005
+ addAttributes() {
3006
+ return {
3007
+ orphan: {
3008
+ parseHTML: (element) => !!element.getAttribute("data-orphan"),
3009
+ renderHTML: (attributes) => {
3010
+ return attributes.orphan ? {
3011
+ "data-orphan": "true"
3012
+ } : {};
3013
+ },
3014
+ default: false
3015
+ },
3016
+ threadId: {
3017
+ parseHTML: (element) => element.getAttribute("data-lb-thread-id"),
3018
+ renderHTML: (attributes) => {
3019
+ return {
3020
+ "data-lb-thread-id": attributes.threadId
3021
+ };
3022
+ },
3023
+ default: ""
3024
+ }
3025
+ };
3026
+ },
3027
+ renderHTML({ HTMLAttributes }) {
3028
+ return [
3029
+ "span",
3030
+ mergeAttributes(HTMLAttributes, {
3031
+ class: "lb-root lb-tiptap-thread-mark"
3032
+ })
3033
+ ];
3034
+ }
3035
+ });
3036
+
3037
+ // src/mention.ts
3038
+ var LIVEBLOCKS_MENTION_TYPE = "liveblocksMention";
3039
+ var MentionExtension = Node.create({
3040
+ name: LIVEBLOCKS_MENTION_TYPE,
3041
+ group: "inline",
3042
+ inline: true,
3043
+ selectable: true,
3044
+ atom: true,
3045
+ priority: 101,
3046
+ parseHTML() {
3047
+ return [
3048
+ {
3049
+ tag: "liveblocks-mention"
3050
+ }
3051
+ ];
3052
+ },
3053
+ renderHTML({ HTMLAttributes }) {
3054
+ return ["liveblocks-mention", mergeAttributes(HTMLAttributes)];
3055
+ },
3056
+ addAttributes() {
3057
+ return {
3058
+ id: {
3059
+ default: null,
3060
+ parseHTML: (element) => element.getAttribute("data-id"),
3061
+ renderHTML: (attributes) => {
3062
+ if (!attributes.id) {
3063
+ return {};
3064
+ }
3065
+ return {
3066
+ "data-id": attributes.id
3067
+ // "as" typing because TipTap doesn't have a way to type attributes
3068
+ };
3069
+ }
3070
+ },
3071
+ notificationId: {
3072
+ default: null,
3073
+ parseHTML: (element) => element.getAttribute("data-notification-id"),
3074
+ renderHTML: (attributes) => {
3075
+ if (!attributes.notificationId) {
3076
+ return {};
3077
+ }
3078
+ return {
3079
+ "data-notification-id": attributes.notificationId
3080
+ // "as" typing because TipTap doesn't have a way to type attributes
3081
+ };
3082
+ }
3083
+ }
3084
+ };
3085
+ }
3086
+ });
3087
+
3088
+ // src/document.ts
3089
+ var DEFAULT_SCHEMA = getSchema([
3090
+ _starterkit2.default,
3091
+ CommentExtension,
3092
+ MentionExtension
3093
+ ]);
3094
+ var getLiveblocksDocumentState = async (roomId, client, schema, field) => {
3095
+ const update = new Uint8Array(
3096
+ await client.getYjsDocumentAsBinaryUpdate(roomId)
3097
+ );
3098
+ const ydoc = new (0, _yjs.Doc)();
3099
+ _yjs.applyUpdate.call(void 0, ydoc, update);
3100
+ const fragment = ydoc.getXmlFragment(_nullishCoalesce(field, () => ( "default")));
3101
+ const { mapping, doc } = _yprosemirror.initProseMirrorDoc.call(void 0, fragment, schema);
3102
+ const state = _state.EditorState.create({
3103
+ schema,
3104
+ doc
3105
+ });
3106
+ return {
3107
+ fragment,
3108
+ state,
3109
+ ydoc,
3110
+ mapping
3111
+ };
3112
+ };
3113
+ var createDocumentFromContent = (content, schema) => {
3114
+ try {
3115
+ return schema.nodeFromJSON(content);
3116
+ } catch (error) {
3117
+ console.warn(
3118
+ "[warn]: Invalid content.",
3119
+ "Passed value:",
3120
+ content,
3121
+ "Error:",
3122
+ error
3123
+ );
3124
+ return false;
3125
+ }
3126
+ };
3127
+ async function withProsemirrorDocument({ roomId, schema: maybeSchema, client, field }, callback) {
3128
+ const schema = _nullishCoalesce(maybeSchema, () => ( DEFAULT_SCHEMA));
3129
+ let liveblocksState = await getLiveblocksDocumentState(
3130
+ roomId,
3131
+ client,
3132
+ schema,
3133
+ _nullishCoalesce(field, () => ( "default"))
3134
+ );
3135
+ const val = await callback({
3136
+ /**
3137
+ * Fetches and resyncs the latest document with Liveblocks
3138
+ */
3139
+ async refresh() {
3140
+ liveblocksState = await getLiveblocksDocumentState(
3141
+ roomId,
3142
+ client,
3143
+ schema,
3144
+ _nullishCoalesce(field, () => ( "default"))
3145
+ );
3146
+ },
3147
+ /**
3148
+ * Provide a callback to modify documetns with Lexical's standard api. All calls are discrete.
3149
+ */
3150
+ async update(modifyFn) {
3151
+ const { ydoc, fragment, state, mapping } = liveblocksState;
3152
+ const beforeVector = _yjs.encodeStateVector.call(void 0, ydoc);
3153
+ const afterState = state.apply(modifyFn(state.doc, state.tr));
3154
+ ydoc.transact(() => {
3155
+ _yprosemirror.updateYFragment.call(void 0, ydoc, fragment, afterState.doc, mapping);
3156
+ });
3157
+ const diffUpdate = _yjs.encodeStateAsUpdate.call(void 0, ydoc, beforeVector);
3158
+ await client.sendYjsBinaryUpdate(roomId, diffUpdate);
3159
+ await this.refresh();
3160
+ },
3161
+ /**
3162
+ * allows you to set content similar to TipTap's setcontent. Only accepts nulls, objects or strings.
3163
+ * Unlike TipTap, strings won't be parsed with DOMParser
3164
+ * */
3165
+ async setContent(content) {
3166
+ if (typeof content === "string") {
3167
+ return this.update((doc, tr) => {
3168
+ tr.delete(0, doc.content.size);
3169
+ tr.insertText(content);
3170
+ return tr;
3171
+ });
3172
+ }
3173
+ if (content === null) {
3174
+ return this.clearContent();
3175
+ }
3176
+ const node = createDocumentFromContent(content, schema);
3177
+ if (!node) {
3178
+ throw "Invalid content";
3179
+ }
3180
+ return this.update((doc, tr) => {
3181
+ tr.delete(0, doc.content.size);
3182
+ tr.insert(0, node);
3183
+ return tr;
3184
+ });
3185
+ },
3186
+ async clearContent() {
3187
+ await this.update((doc, tr) => {
3188
+ tr.delete(0, doc.content.size);
3189
+ return tr;
3190
+ });
3191
+ },
3192
+ /**
3193
+ * Uses TipTap's getText function, which allows passing a custom text serializer
3194
+ */
3195
+ getText(options) {
3196
+ const { state } = liveblocksState;
3197
+ return getText(state.doc, options);
3198
+ },
3199
+ /**
3200
+ * Helper function to return prosemirror document in JSON form
3201
+ */
3202
+ toJSON() {
3203
+ return liveblocksState.state.doc.toJSON();
3204
+ },
3205
+ /**
3206
+ * Helper function to return editor state as Markdown. By default it uses the defaultMarkdownSerializer from prosemirror-markdown, but you may pass your own
3207
+ */
3208
+ toMarkdown(serializer) {
3209
+ return (_nullishCoalesce(serializer, () => ( _prosemirrormarkdown.defaultMarkdownSerializer))).serialize(
3210
+ liveblocksState.state.doc
3211
+ );
3212
+ },
3213
+ /**
3214
+ * Helper function to return the editor's current prosemirror state
3215
+ */
3216
+ getEditorState() {
3217
+ return liveblocksState.state;
3218
+ }
3219
+ });
3220
+ return val;
3221
+ }
3222
+
3223
+ // src/index.ts
3224
+ _core.detectDupes.call(void 0, PKG_NAME, PKG_VERSION, PKG_FORMAT);
3225
+
3226
+
3227
+ exports.withProsemirrorDocument = withProsemirrorDocument;
3228
+ //# sourceMappingURL=index.js.map