@blocknote/core
Version:
A "Notion-style" block-based extensible text editor built on top of Prosemirror and Tiptap.
1,589 lines (1,588 loc) • 137 kB
JavaScript
var Fe = Object.defineProperty;
var Ve = (n, e, t) => e in n ? Fe(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t;
var k = (n, e, t) => Ve(n, typeof e != "symbol" ? e + "" : e, t);
import { Slice as F, Fragment as w, DOMSerializer as me, DOMParser as Ue, Node as ze } from "prosemirror-model";
import { ReplaceStep as Re, ReplaceAroundStep as W } from "prosemirror-transform";
import { n as q, i as V, g as E, b as Z, a as C, t as Ge, U, q as D, r as z, d as je, s as We, u as qe, v, w as B, x as ke, y as Ke, z as be, A as K } from "./blockToNode-BNoNIXU7.js";
import { B as ms, G as ks, C as bs, D as gs, N as Bs, E as ys, O as Cs, F as Ss, H as xs, I as Es, L as Ps, J as Ts, M as Ms, K as ws } from "./blockToNode-BNoNIXU7.js";
import { ak as G, al as Je, am as Ye, an as Qe, aj as P, a as Xe, ao as Ze, ap as et, a5 as tt, a8 as J, aq as ot, ar as nt, a6 as st, as as ee, a9 as ge, at as rt } from "./defaultBlocks-Caw1U1oV.js";
import { aw as Is, av as As, E as Ns, F as _s, r as Ls, N as Ds, a4 as Os, ad as $s, aG as Hs, ax as Fs, b as Vs, d as Us, e as zs, a0 as Rs, aM as Gs, au as js, c as Ws, f as qs, ag as Ks, ah as Js, aB as Ys, x as Qs, y as Xs, A as Zs, z as er, g as tr, h as or, T as nr, j as sr, k as rr, l as ir, n as ar, o as cr, q as lr, s as dr, w as ur, aC as pr, aH as fr, B as hr, C as mr, H as kr, I as br, J as gr, K as Br, aE as yr, aI as Cr, M as Sr, D as xr, G as Er, S as Pr, O as Tr, Q as Mr, W as wr, U as vr, _ as Ir, Z as Ar, a2 as Nr, Y as _r, X as Lr, R as Dr, $ as Or, m as $r, aN as Hr, aK as Fr, az as Vr, af as Ur, i as zr, ay as Rr, aD as Gr, ae as jr, a7 as Wr, t as qr, u as Kr, v as Jr, aJ as Yr, ai as Qr, aL as Xr, a1 as Zr, V as ei, p as ti, a3 as oi, aF as ni, L as si, aO as ri, P as ii, aA as ai } from "./defaultBlocks-Caw1U1oV.js";
import { j as it, k as Be, l as at, m as ct, n as lt, c as Y, F as dt, Y as ut, a as pt, b as ft, S as ht, B as ye, D as mt, L as kt, N as bt, P as gt, g as Bt, i as yt, H as Ct, h as St, e as xt, V as Et, d as Pt } from "./TrailingNode-F9hX_UlQ.js";
import { s as Tt, B as Mt } from "./BlockNoteSchema-dmbNkHA-.js";
import { C as li, b as di, c as ui, a as pi, g as fi, u as hi, w as mi } from "./BlockNoteSchema-dmbNkHA-.js";
import { Node as O, Extension as T, mergeAttributes as wt, Mark as te, extensions as N, isNodeSelection as vt, posToDOMRect as It, selectionToInsertionEnd as At, findParentNodeClosestToPos as Nt, getSchema as _t, createDocument as Lt, Editor as Dt } from "@tiptap/core";
import { E as Ce } from "./EventEmitter-CjSwpTbz.js";
import { Fragment as R, Slice as j } from "@tiptap/pm/model";
import { e as Ot } from "./en-njEqD7AG.js";
import { inputRules as $t, InputRule as Ht } from "@handlewithcare/prosemirror-inputrules";
import { keymap as Ft } from "@tiptap/pm/keymap";
import { c as Vt, o as Ut } from "./BlockNoteExtension-C2X7LW-V.js";
import { a as bi } from "./BlockNoteExtension-C2X7LW-V.js";
import { Gapcursor as zt } from "@tiptap/extensions/gap-cursor";
import { Link as Rt } from "@tiptap/extension-link";
import { Text as Gt } from "@tiptap/extension-text";
import { NodeSelection as $, TextSelection as S, Plugin as oe } from "prosemirror-state";
import { CellSelection as ne, TableMap as re } from "prosemirror-tables";
import { S as jt } from "./ShowSelection-B0ch3unP.js";
import Wt from "remark-gfm";
import qt from "remark-parse";
import Kt, { defaultHandlers as ie } from "remark-rehype";
import Jt from "rehype-stringify";
import { unified as Yt } from "unified";
import { TextSelection as Qt } from "@tiptap/pm/state";
function Xt(n, e) {
const t = [
{
tag: `[data-inline-content-type="${n.type}"]`,
contentElement: (o) => {
const s = o;
return s.matches("[data-editable]") ? s : s.querySelector("[data-editable]") || s;
}
}
];
return e && t.push({
tag: "*",
getAttrs(o) {
if (typeof o == "string")
return !1;
const s = e == null ? void 0 : e(o);
return s === void 0 ? !1 : s;
}
}), t;
}
function ls(n, e) {
var o;
const t = O.create({
name: n.type,
inline: !0,
group: "inline",
draggable: (o = e.meta) == null ? void 0 : o.draggable,
selectable: n.content === "styled",
atom: n.content === "none",
content: n.content === "styled" ? "inline*" : "",
addAttributes() {
return Ye(n.propSchema);
},
addKeyboardShortcuts() {
return Je(n);
},
parseHTML() {
return Xt(
n,
e.parse
);
},
renderHTML({ node: s }) {
const r = this.options.editor, i = e.render.call(
{ renderType: "dom", props: void 0 },
q(
s,
r.schema.inlineContentSchema,
r.schema.styleSchema
),
// TODO: fix cast
() => {
},
r
);
return G(
i,
n.type,
s.attrs,
n.propSchema
);
},
addNodeView() {
return (s) => {
const { node: r, getPos: i } = s, l = this.options.editor, a = e.render.call(
{ renderType: "nodeView", props: s },
q(
r,
l.schema.inlineContentSchema,
l.schema.styleSchema
),
// TODO: fix cast
(c) => {
const d = V([c], l.pmSchema), u = i();
u && l.transact(
(p) => p.replaceWith(u, u + r.nodeSize, d)
);
},
l
);
return G(
a,
n.type,
r.attrs,
n.propSchema
);
};
}
});
return Qe(
t,
n.propSchema,
{
...e,
toExternalHTML: e.toExternalHTML,
render(s, r, i) {
const l = e.render(
s,
r,
i
);
return G(
l,
n.type,
s.props,
n.propSchema
);
}
}
);
}
function Zt(n, e, t, o = "before") {
const s = typeof t == "string" ? t : t.id, r = E(n), i = e.map(
(d) => Z(d, r)
), l = P(s, n.doc);
if (!l)
throw new Error(`Block with ID ${s} not found`);
let a = l.posBeforeNode;
return o === "after" && (a += l.node.nodeSize), n.step(
new Re(a, a, new F(w.from(i), 0, 0))
), i.map(
(d) => C(d, r)
);
}
function Q(n) {
if (!n || n.type.name !== "column")
throw new Error("Invalid columnPos: does not point to column node.");
const e = n.firstChild;
if (!e)
throw new Error("Invalid column: does not have child node.");
const t = e.firstChild;
if (!t)
throw new Error("Invalid blockContainer: does not have child node.");
return n.childCount === 1 && e.childCount === 1 && t.type.name === "paragraph" && t.content.content.length === 0;
}
function eo(n, e) {
const t = n.doc.resolve(e), o = t.nodeAfter;
if (!o || o.type.name !== "columnList")
throw new Error(
"Invalid columnListPos: does not point to columnList node."
);
for (let s = o.childCount - 1; s >= 0; s--) {
const r = n.doc.resolve(t.pos + 1).posAtIndex(s), l = n.doc.resolve(r).nodeAfter;
if (!l || l.type.name !== "column")
throw new Error("Invalid columnPos: does not point to column node.");
Q(l) && n.delete(r, r + l.nodeSize);
}
}
function H(n, e) {
eo(n, e);
const o = n.doc.resolve(e).nodeAfter;
if (!o || o.type.name !== "columnList")
throw new Error(
"Invalid columnListPos: does not point to columnList node."
);
if (o.childCount > 2)
return;
if (o.childCount < 2)
throw new Error("Invalid columnList: contains fewer than two children.");
const s = e + 1, i = n.doc.resolve(s).nodeAfter, l = e + o.nodeSize - 1, c = n.doc.resolve(l).nodeBefore;
if (!i || !c)
throw new Error("Invalid columnList: does not contain children.");
const d = Q(i), u = Q(c);
if (d && u) {
n.delete(e, e + o.nodeSize);
return;
}
if (d) {
n.step(
new W(
// Replaces `columnList`.
e,
e + o.nodeSize,
// Replaces with content of last `column`.
l - c.nodeSize + 1,
l - 1,
// Doesn't append anything.
F.empty,
0,
!1
)
);
return;
}
if (u) {
n.step(
new W(
// Replaces `columnList`.
e,
e + o.nodeSize,
// Replaces with content of first `column`.
s + 1,
s + i.nodeSize - 1,
// Doesn't append anything.
F.empty,
0,
!1
)
);
return;
}
}
function ae(n, e, t) {
const o = E(n), s = t.map(
(u) => Z(u, o)
), r = new Set(
e.map(
(u) => typeof u == "string" ? u : u.id
)
), i = [], l = /* @__PURE__ */ new Set(), a = typeof e[0] == "string" ? e[0] : e[0].id;
let c = 0;
if (n.doc.descendants((u, p) => {
if (r.size === 0)
return !1;
if (!u.type.isInGroup("bnBlock") || !r.has(u.attrs.id))
return !0;
if (i.push(C(u, o)), r.delete(u.attrs.id), t.length > 0 && u.attrs.id === a) {
const b = n.doc.nodeSize;
n.insert(p, s);
const g = n.doc.nodeSize;
c += b - g;
}
const h = n.doc.nodeSize, f = n.doc.resolve(p - c);
f.node().type.name === "column" ? l.add(f.before(-1)) : f.node().type.name === "columnList" && l.add(f.before()), f.node().type.name === "blockGroup" && f.node(f.depth - 1).type.name !== "doc" && f.node().childCount === 1 ? n.delete(f.before(), f.after()) : n.delete(p - c, p - c + u.nodeSize);
const m = n.doc.nodeSize;
return c += h - m, !1;
}), r.size > 0) {
const u = [...r].join(`
`);
throw Error(
"Blocks with the following IDs could not be found in the editor: " + u
);
}
return l.forEach((u) => H(n, u)), { insertedBlocks: s.map(
(u) => C(u, o)
), removedBlocks: i };
}
function to(n, e, t, o, s) {
let r;
if (e)
if (typeof e == "string")
r = V([e], n.pmSchema, o);
else if (Array.isArray(e))
r = V(e, n.pmSchema, o);
else if (e.type === "tableContent")
r = Ge(e, n.pmSchema);
else
throw new U(e.type);
else throw new Error("blockContent is required");
const l = ((s == null ? void 0 : s.document) ?? document).createDocumentFragment();
for (const a of r)
if (a.type.name !== "text" && n.schema.inlineContentSchema[a.type.name]) {
const c = n.schema.inlineContentSpecs[a.type.name].implementation;
if (c) {
const d = q(
a,
n.schema.inlineContentSchema,
n.schema.styleSchema
), u = c.render.call(
{
renderType: "dom",
props: void 0
},
d,
() => {
},
n
);
if (u) {
if (l.appendChild(u.dom), u.contentDOM) {
const p = t.serializeFragment(
a.content,
s
);
u.contentDOM.dataset.editable = "", u.contentDOM.appendChild(p);
}
continue;
}
}
} else if (a.type.name === "text") {
let c = document.createTextNode(
a.textContent
);
for (const d of a.marks.toReversed())
if (d.type.name in n.schema.styleSpecs) {
const u = n.schema.styleSpecs[d.type.name].implementation.render(d.attrs.stringValue, n);
u.contentDOM.appendChild(c), c = u.dom;
} else {
const u = d.type.spec.toDOM(d, !0), p = me.renderSpec(document, u);
p.contentDOM.appendChild(c), c = p.dom;
}
l.appendChild(c);
} else {
const c = t.serializeFragment(
w.from([a]),
s
);
l.appendChild(c);
}
return l;
}
function oo(n, e, t, o) {
var u, p, h, f, m;
const s = n.pmSchema.nodes.blockContainer, r = e.props || {};
for (const [b, g] of Object.entries(
n.schema.blockSchema[e.type].propSchema
))
!(b in r) && g.default !== void 0 && (r[b] = g.default);
const i = e.children || [], a = n.blockImplementations[e.type].implementation.render.call(
{
renderType: "dom",
props: void 0
},
{ ...e, props: r, children: i },
n
);
if (a.contentDOM && e.content) {
const b = to(
n,
e.content,
// TODO
t,
e.type,
o
);
a.contentDOM.appendChild(b);
}
if (n.pmSchema.nodes[e.type].isInGroup("bnBlock")) {
if (e.children && e.children.length > 0) {
const b = Se(
n,
e.children,
t,
o
);
(u = a.contentDOM) == null || u.append(b);
}
return a.dom;
}
const d = (h = (p = s.spec) == null ? void 0 : p.toDOM) == null ? void 0 : h.call(
p,
s.create({
id: e.id,
...r
})
);
return (f = d.contentDOM) == null || f.appendChild(a.dom), e.children && e.children.length > 0 && ((m = d.contentDOM) == null || m.appendChild(
xe(n, e.children, t, o)
)), d.dom;
}
function Se(n, e, t, o) {
const r = ((o == null ? void 0 : o.document) ?? document).createDocumentFragment();
for (const i of e) {
const l = oo(n, i, t, o);
r.appendChild(l);
}
return r;
}
const xe = (n, e, t, o) => {
var l;
const s = n.pmSchema.nodes.blockGroup, r = s.spec.toDOM(s.create({})), i = Se(n, e, t, o);
return (l = r.contentDOM) == null || l.appendChild(i), r.dom;
}, no = (n) => (n.querySelectorAll(
'[data-content-type="numberedListItem"]'
).forEach((t) => {
var s, r;
const o = (r = (s = t.closest(".bn-block-outer")) == null ? void 0 : s.previousElementSibling) == null ? void 0 : r.querySelector(
'[data-content-type="numberedListItem"]'
);
if (!o)
t.setAttribute(
"data-index",
t.getAttribute("data-start") || "1"
);
else {
const i = o.getAttribute("data-index");
t.setAttribute(
"data-index",
(parseInt(i || "0") + 1).toString()
);
}
}), n), so = (n) => (n.querySelectorAll(
'[data-content-type="checkListItem"] input'
).forEach((t) => {
t.disabled = !0;
}), n), ro = (n) => (n.querySelectorAll(
'.bn-toggle-wrapper[data-show-children="false"]'
).forEach((t) => {
t.setAttribute("data-show-children", "true");
}), n), io = (n) => (n.querySelectorAll('[data-content-type="table"] table').forEach((t) => {
t.setAttribute(
"style",
`--default-cell-min-width: ${Xe}px;`
), t.setAttribute("data-show-children", "true");
}), n), ao = (n) => (n.querySelectorAll('[data-content-type="table"] table').forEach((t) => {
var r;
const o = document.createElement("div");
o.className = "tableWrapper";
const s = document.createElement("div");
s.className = "tableWrapper-inner", o.appendChild(s), (r = t.parentElement) == null || r.appendChild(o), o.appendChild(t);
}), n), co = (n) => (n.querySelectorAll(
".bn-inline-content:empty"
).forEach((t) => {
const o = document.createElement("span");
o.className = "ProseMirror-trailingBreak", o.setAttribute("style", "display: inline-block;"), t.appendChild(o);
}), n), lo = (n, e) => {
const t = me.fromSchema(n), o = [
no,
so,
ro,
io,
ao,
co
];
return {
serializeBlocks: (s, r) => {
let i = xe(
e,
s,
t,
r
);
for (const l of o)
i = l(i);
return i.outerHTML;
}
};
};
function uo(n) {
return n.transact((e) => {
const t = D(e.doc, e.selection.anchor);
if (e.selection instanceof ne)
return {
type: "cell",
anchorBlockId: t.node.attrs.id,
anchorCellOffset: e.selection.$anchorCell.pos - t.posBeforeNode,
headCellOffset: e.selection.$headCell.pos - t.posBeforeNode
};
if (e.selection instanceof $)
return {
type: "node",
anchorBlockId: t.node.attrs.id
};
{
const o = D(e.doc, e.selection.head);
return {
type: "text",
anchorBlockId: t.node.attrs.id,
headBlockId: o.node.attrs.id,
anchorOffset: e.selection.anchor - t.posBeforeNode,
headOffset: e.selection.head - o.posBeforeNode
};
}
});
}
function po(n, e) {
var s, r;
const t = (s = P(e.anchorBlockId, n.doc)) == null ? void 0 : s.posBeforeNode;
if (t === void 0)
throw new Error(
`Could not find block with ID ${e.anchorBlockId} to update selection`
);
let o;
if (e.type === "cell")
o = ne.create(
n.doc,
t + e.anchorCellOffset,
t + e.headCellOffset
);
else if (e.type === "node")
o = $.create(n.doc, t + 1);
else {
const i = (r = P(e.headBlockId, n.doc)) == null ? void 0 : r.posBeforeNode;
if (i === void 0)
throw new Error(
`Could not find block with ID ${e.headBlockId} to update selection`
);
o = S.create(
n.doc,
t + e.anchorOffset,
i + e.headOffset
);
}
n.setSelection(o);
}
function X(n) {
return n.map((e) => e.type === "columnList" ? e.children.map((t) => X(t.children)).flat() : {
...e,
children: X(e.children)
}).flat();
}
function Ee(n, e, t) {
n.transact((o) => {
var i;
const s = ((i = n.getSelection()) == null ? void 0 : i.blocks) || [
n.getTextCursorPosition().block
], r = uo(n);
n.removeBlocks(s), n.insertBlocks(X(s), e, t), po(o, r);
});
}
function Pe(n) {
return !n || n.type !== "columnList";
}
function Te(n, e, t) {
let o, s;
if (e ? e.children.length > 0 ? (o = e.children[e.children.length - 1], s = "after") : (o = e, s = "before") : t && (o = t, s = "before"), !o || !s)
return;
const r = n.getParentBlock(o);
return Pe(r) ? { referenceBlock: o, placement: s } : Te(
n,
s === "after" ? o : n.getPrevBlock(o),
r
);
}
function Me(n, e, t) {
let o, s;
if (e ? e.children.length > 0 ? (o = e.children[0], s = "before") : (o = e, s = "after") : t && (o = t, s = "after"), !o || !s)
return;
const r = n.getParentBlock(o);
return Pe(r) ? { referenceBlock: o, placement: s } : Me(
n,
s === "before" ? o : n.getNextBlock(o),
r
);
}
function fo(n) {
n.transact(() => {
const e = n.getSelection(), t = (e == null ? void 0 : e.blocks[0]) || n.getTextCursorPosition().block, o = Te(
n,
n.getPrevBlock(t),
n.getParentBlock(t)
);
o && Ee(
n,
o.referenceBlock,
o.placement
);
});
}
function ho(n) {
n.transact(() => {
const e = n.getSelection(), t = (e == null ? void 0 : e.blocks[(e == null ? void 0 : e.blocks.length) - 1]) || n.getTextCursorPosition().block, o = Me(
n,
n.getNextBlock(t),
n.getParentBlock(t)
);
o && Ee(
n,
o.referenceBlock,
o.placement
);
});
}
function mo(n, e, t) {
const { $from: o, $to: s } = n.selection, r = o.blockRange(
s,
(f) => f.childCount > 0 && (f.type.name === "blockGroup" || f.type.name === "column")
// change necessary to not look at first item child type
);
if (!r)
return !1;
const i = r.startIndex;
if (i === 0)
return !1;
const a = r.parent.child(i - 1);
if (a.type !== e)
return !1;
const c = a.lastChild && a.lastChild.type === t, d = w.from(c ? e.create() : null), u = new F(
w.from(
e.create(null, w.from(t.create(null, d)))
// change necessary to create "groupType" instead of parent.type
),
c ? 3 : 1,
0
), p = r.start, h = r.end;
return n.step(
new W(
p - (c ? 3 : 1),
h,
p,
h,
u,
1,
!0
)
).scrollIntoView(), !0;
}
function we(n) {
return n.transact((e) => mo(
e,
n.pmSchema.nodes.blockContainer,
n.pmSchema.nodes.blockGroup
));
}
function ko(n) {
n._tiptapEditor.commands.liftListItem("blockContainer");
}
function bo(n) {
return n.transact((e) => {
const { bnBlock: t } = z(e);
return e.doc.resolve(t.beforePos).nodeBefore !== null;
});
}
function go(n) {
return n.transact((e) => {
const { bnBlock: t } = z(e);
return e.doc.resolve(t.beforePos).depth > 1;
});
}
function Bo(n, e) {
const t = typeof e == "string" ? e : e.id, o = E(n), s = P(t, n);
if (s)
return C(s.node, o);
}
function yo(n, e) {
const t = typeof e == "string" ? e : e.id, o = P(t, n), s = E(n);
if (!o)
return;
const i = n.resolve(o.posBeforeNode).nodeBefore;
if (i)
return C(i, s);
}
function Co(n, e) {
const t = typeof e == "string" ? e : e.id, o = P(t, n), s = E(n);
if (!o)
return;
const i = n.resolve(
o.posBeforeNode + o.node.nodeSize
).nodeAfter;
if (i)
return C(i, s);
}
function So(n, e) {
const t = typeof e == "string" ? e : e.id, o = E(n), s = P(t, n);
if (!s)
return;
const r = n.resolve(s.posBeforeNode), i = r.node(), l = r.node(-1), a = l.type.name !== "doc" ? i.type.name === "blockGroup" ? l : i : void 0;
if (a)
return C(a, o);
}
class xo {
constructor(e) {
this.editor = e;
}
/**
* Gets a snapshot of all top-level (non-nested) blocks in the editor.
* @returns A snapshot of all top-level (non-nested) blocks in the editor.
*/
get document() {
return this.editor.transact((e) => je(e.doc, this.editor.pmSchema));
}
/**
* Gets a snapshot of an existing block from the editor.
* @param blockIdentifier The identifier of an existing block that should be
* retrieved.
* @returns The block that matches the identifier, or `undefined` if no
* matching block was found.
*/
getBlock(e) {
return this.editor.transact((t) => Bo(t.doc, e));
}
/**
* Gets a snapshot of the previous sibling of an existing block from the
* editor.
* @param blockIdentifier The identifier of an existing block for which the
* previous sibling should be retrieved.
* @returns The previous sibling of the block that matches the identifier.
* `undefined` if no matching block was found, or it's the first child/block
* in the document.
*/
getPrevBlock(e) {
return this.editor.transact((t) => yo(t.doc, e));
}
/**
* Gets a snapshot of the next sibling of an existing block from the editor.
* @param blockIdentifier The identifier of an existing block for which the
* next sibling should be retrieved.
* @returns The next sibling of the block that matches the identifier.
* `undefined` if no matching block was found, or it's the last child/block in
* the document.
*/
getNextBlock(e) {
return this.editor.transact((t) => Co(t.doc, e));
}
/**
* Gets a snapshot of the parent of an existing block from the editor.
* @param blockIdentifier The identifier of an existing block for which the
* parent should be retrieved.
* @returns The parent of the block that matches the identifier. `undefined`
* if no matching block was found, or the block isn't nested.
*/
getParentBlock(e) {
return this.editor.transact(
(t) => So(t.doc, e)
);
}
/**
* Traverses all blocks in the editor depth-first, and executes a callback for each.
* @param callback The callback to execute for each block. Returning `false` stops the traversal.
* @param reverse Whether the blocks should be traversed in reverse order.
*/
forEachBlock(e, t = !1) {
const o = this.document.slice();
t && o.reverse();
function s(r) {
for (const i of r) {
if (e(i) === !1)
return !1;
const l = t ? i.children.slice().reverse() : i.children;
if (!s(l))
return !1;
}
return !0;
}
s(o);
}
/**
* Inserts new blocks into the editor. If a block's `id` is undefined, BlockNote generates one automatically. Throws an
* error if the reference block could not be found.
* @param blocksToInsert An array of partial blocks that should be inserted.
* @param referenceBlock An identifier for an existing block, at which the new blocks should be inserted.
* @param placement Whether the blocks should be inserted just before, just after, or nested inside the
* `referenceBlock`.
*/
insertBlocks(e, t, o = "before") {
return this.editor.transact(
(s) => Zt(s, e, t, o)
);
}
/**
* Updates an existing block in the editor. Since updatedBlock is a PartialBlock object, some fields might not be
* defined. These undefined fields are kept as-is from the existing block. Throws an error if the block to update could
* not be found.
* @param blockToUpdate The block that should be updated.
* @param update A partial block which defines how the existing block should be changed.
*/
updateBlock(e, t) {
return this.editor.transact((o) => Ze(o, e, t));
}
/**
* Removes existing blocks from the editor. Throws an error if any of the blocks could not be found.
* @param blocksToRemove An array of identifiers for existing blocks that should be removed.
*/
removeBlocks(e) {
return this.editor.transact(
(t) => ae(t, e, []).removedBlocks
);
}
/**
* Replaces existing blocks in the editor with new blocks. If the blocks that should be removed are not adjacent or
* are at different nesting levels, `blocksToInsert` will be inserted at the position of the first block in
* `blocksToRemove`. Throws an error if any of the blocks to remove could not be found.
* @param blocksToRemove An array of blocks that should be replaced.
* @param blocksToInsert An array of partial blocks to replace the old ones with.
*/
replaceBlocks(e, t) {
return this.editor.transact(
(o) => ae(o, e, t)
);
}
/**
* Checks if the block containing the text cursor can be nested.
*/
canNestBlock() {
return bo(this.editor);
}
/**
* Nests the block containing the text cursor into the block above it.
*/
nestBlock() {
we(this.editor);
}
/**
* Checks if the block containing the text cursor is nested.
*/
canUnnestBlock() {
return go(this.editor);
}
/**
* Lifts the block containing the text cursor out of its parent.
*/
unnestBlock() {
ko(this.editor);
}
/**
* Moves the selected blocks up. If the previous block has children, moves
* them to the end of its children. If there is no previous block, but the
* current blocks share a common parent, moves them out of & before it.
*/
moveBlocksUp() {
return fo(this.editor);
}
/**
* Moves the selected blocks down. If the next block has children, moves
* them to the start of its children. If there is no next block, but the
* current blocks share a common parent, moves them out of & after it.
*/
moveBlocksDown() {
return ho(this.editor);
}
}
class Eo extends Ce {
constructor(e) {
super(), this.editor = e, e.on("create", () => {
e._tiptapEditor.on(
"update",
({ transaction: t, appendedTransactions: o }) => {
this.emit("onChange", { editor: e, transaction: t, appendedTransactions: o });
}
), e._tiptapEditor.on("selectionUpdate", ({ transaction: t }) => {
this.emit("onSelectionChange", { editor: e, transaction: t });
}), e._tiptapEditor.on("mount", () => {
this.emit("onMount", { editor: e });
}), e._tiptapEditor.on("unmount", () => {
this.emit("onUnmount", { editor: e });
});
});
}
/**
* Register a callback that will be called when the editor changes.
*/
onChange(e, t = !0) {
const o = ({
transaction: s,
appendedTransactions: r
}) => {
!t && ce(s) || e(this.editor, {
getChanges() {
return it(
s,
r
);
}
});
};
return this.on("onChange", o), () => {
this.off("onChange", o);
};
}
/**
* Register a callback that will be called when the selection changes.
*/
onSelectionChange(e, t = !1) {
const o = (s) => {
!t && ce(s.transaction) || e(this.editor);
};
return this.on("onSelectionChange", o), () => {
this.off("onSelectionChange", o);
};
}
/**
* Register a callback that will be called when the editor is mounted.
*/
onMount(e) {
return this.on("onMount", e), () => {
this.off("onMount", e);
};
}
/**
* Register a callback that will be called when the editor is unmounted.
*/
onUnmount(e) {
return this.on("onUnmount", e), () => {
this.off("onUnmount", e);
};
}
}
function ce(n) {
return !!n.getMeta("y-sync$");
}
function Po(n) {
return Array.prototype.indexOf.call(n.parentElement.childNodes, n);
}
function To(n) {
return n.nodeType === 3 && !/\S/.test(n.nodeValue || "");
}
function Mo(n) {
n.querySelectorAll("li > ul, li > ol").forEach((e) => {
const t = Po(e), o = e.parentElement, s = Array.from(o.childNodes).slice(
t + 1
);
e.remove(), s.forEach((r) => {
r.remove();
}), o.insertAdjacentElement("afterend", e), s.reverse().forEach((r) => {
if (To(r))
return;
const i = document.createElement("li");
i.append(r), e.insertAdjacentElement("afterend", i);
}), o.childNodes.length === 0 && o.remove();
});
}
function wo(n) {
n.querySelectorAll("li + ul, li + ol").forEach((e) => {
var r, i;
const t = e.previousElementSibling, o = document.createElement("div");
t.insertAdjacentElement("afterend", o), o.append(t);
const s = document.createElement("div");
for (s.setAttribute("data-node-type", "blockGroup"), o.append(s); ((r = o.nextElementSibling) == null ? void 0 : r.nodeName) === "UL" || ((i = o.nextElementSibling) == null ? void 0 : i.nodeName) === "OL"; )
s.append(o.nextElementSibling);
});
}
let le = null;
function vo() {
return le || (le = document.implementation.createHTMLDocument("title"));
}
function Io(n) {
if (typeof n == "string") {
const e = vo().createElement("div");
e.innerHTML = n, n = e;
}
return Mo(n), wo(n), n;
}
function ve(n, e) {
const t = Io(n), s = Ue.fromSchema(e).parse(t, {
topNode: e.nodes.blockGroup.create()
}), r = [];
for (let i = 0; i < s.childCount; i++)
r.push(C(s.child(i), e));
return r;
}
function Ao(n, e) {
const t = e.value ? e.value : "", o = {};
e.lang && (o["data-language"] = e.lang);
let s = {
type: "element",
tagName: "code",
properties: o,
children: [{ type: "text", value: t }]
};
return e.meta && (s.data = { meta: e.meta }), n.patch(e, s), s = n.applyData(e, s), s = {
type: "element",
tagName: "pre",
properties: {},
children: [s]
}, n.patch(e, s), s;
}
function No(n, e) {
var r;
const t = String((e == null ? void 0 : e.url) || ""), o = e != null && e.title ? String(e.title) : void 0;
let s = {
type: "element",
tagName: "video",
properties: {
src: t,
"data-name": o,
"data-url": t,
controls: !0
},
children: []
};
return (r = n.patch) == null || r.call(n, e, s), s = n.applyData ? n.applyData(e, s) : s, s;
}
function Ie(n) {
return Yt().use(qt).use(Wt).use(Kt, {
handlers: {
...ie,
image: (t, o) => {
const s = String((o == null ? void 0 : o.url) || "");
return et(s) ? No(t, o) : ie.image(t, o);
},
code: Ao,
blockquote: (t, o) => {
const s = {
type: "element",
tagName: "blockquote",
properties: {},
// The only difference from the original is that we don't wrap the children with line endings
children: t.wrap(t.all(o), !1)
};
return t.patch(o, s), t.applyData(o, s);
}
}
}).use(Jt).processSync(n).value;
}
function _o(n, e) {
const t = Ie(n);
return ve(t, e);
}
class Lo {
constructor(e) {
this.editor = e;
}
/**
* Exports blocks into a simplified HTML string. To better conform to HTML standards, children of blocks which aren't list
* items are un-nested in the output HTML.
*
* @param blocks An array of blocks that should be serialized into HTML.
* @returns The blocks, serialized as an HTML string.
*/
blocksToHTMLLossy(e = this.editor.document) {
return Be(
this.editor.pmSchema,
this.editor
).exportBlocks(e, {});
}
/**
* Serializes blocks into an HTML string in the format that would normally be rendered by the editor.
*
* Use this method if you want to server-side render HTML (for example, a blog post that has been edited in BlockNote)
* and serve it to users without loading the editor on the client (i.e.: displaying the blog post)
*
* @param blocks An array of blocks that should be serialized into HTML.
* @returns The blocks, serialized as an HTML string.
*/
blocksToFullHTML(e = this.editor.document) {
return lo(
this.editor.pmSchema,
this.editor
).serializeBlocks(e, {});
}
/**
* Parses blocks from an HTML string. Tries to create `Block` objects out of any HTML block-level elements, and
* `InlineNode` objects from any HTML inline elements, though not all element types are recognized. If BlockNote
* doesn't recognize an HTML element's tag, it will parse it as a paragraph or plain text.
* @param html The HTML string to parse blocks from.
* @returns The blocks parsed from the HTML string.
*/
tryParseHTMLToBlocks(e) {
return ve(e, this.editor.pmSchema);
}
/**
* Serializes blocks into a Markdown string. The output is simplified as Markdown does not support all features of
* BlockNote - children of blocks which aren't list items are un-nested and certain styles are removed.
* @param blocks An array of blocks that should be serialized into Markdown.
* @returns The blocks, serialized as a Markdown string.
*/
blocksToMarkdownLossy(e = this.editor.document) {
return at(e, this.editor.pmSchema, this.editor, {});
}
/**
* Creates a list of blocks from a Markdown string. Tries to create `Block` and `InlineNode` objects based on
* Markdown syntax, though not all symbols are recognized. If BlockNote doesn't recognize a symbol, it will parse it
* as text.
* @param markdown The Markdown string to parse blocks from.
* @returns The blocks parsed from the Markdown string.
*/
tryParseMarkdownToBlocks(e) {
return _o(e, this.editor.pmSchema);
}
/**
* Paste HTML into the editor. Defaults to converting HTML to BlockNote HTML.
* @param html The HTML to paste.
* @param raw Whether to paste the HTML as is, or to convert it to BlockNote HTML.
*/
pasteHTML(e, t = !1) {
var s;
let o = e;
if (!t) {
const r = this.tryParseHTMLToBlocks(e);
o = this.blocksToFullHTML(r);
}
o && ((s = this.editor.prosemirrorView) == null || s.pasteHTML(o));
}
/**
* Paste text into the editor. Defaults to interpreting text as markdown.
* @param text The text to paste.
*/
pasteText(e) {
var t;
return (t = this.editor.prosemirrorView) == null ? void 0 : t.pasteText(e);
}
/**
* Paste markdown into the editor.
* @param markdown The markdown to paste.
*/
pasteMarkdown(e) {
const t = Ie(e);
return this.pasteHTML(t);
}
}
const se = [
"vscode-editor-data",
"blocknote/html",
"text/markdown",
"text/html",
"text/plain",
"Files"
];
function Do(n, e) {
if (!n.startsWith(".") || !e.startsWith("."))
throw new Error("The strings provided are not valid file extensions.");
return n === e;
}
function Oo(n, e) {
const t = n.split("/"), o = e.split("/");
if (t.length !== 2)
throw new Error(`The string ${n} is not a valid MIME type.`);
if (o.length !== 2)
throw new Error(`The string ${e} is not a valid MIME type.`);
return t[1] === "*" || o[1] === "*" ? t[0] === o[0] : (t[0] === "*" || o[0] === "*" || t[0] === o[0]) && t[1] === o[1];
}
function de(n, e, t, o = "after") {
let s;
return Array.isArray(e.content) && e.content.length === 0 ? s = n.updateBlock(e, t).id : s = n.insertBlocks(
[t],
e,
o
)[0].id, s;
}
async function Ae(n, e) {
var r;
if (!e.uploadFile) {
console.warn(
"Attempted ot insert file, but uploadFile is not set in the BlockNote editor options"
);
return;
}
const t = "dataTransfer" in n ? n.dataTransfer : n.clipboardData;
if (t === null)
return;
let o = null;
for (const i of se)
if (t.types.includes(i)) {
o = i;
break;
}
if (o !== "Files")
return;
const s = t.items;
if (s) {
n.preventDefault();
for (let i = 0; i < s.length; i++) {
let l = "file";
for (const c of Object.values(e.schema.blockSpecs))
for (const d of ((r = c.implementation.meta) == null ? void 0 : r.fileBlockAccept) || []) {
const u = d.startsWith("."), p = s[i].getAsFile();
if (p && (!u && p.type && Oo(s[i].type, d) || u && Do(
"." + p.name.split(".").pop(),
d
))) {
l = c.config.type;
break;
}
}
const a = s[i].getAsFile();
if (a) {
const c = {
type: l,
props: {
name: a.name
}
};
let d;
if (n.type === "paste") {
const h = e.getTextCursorPosition().block;
d = de(e, h, c);
} else if (n.type === "drop") {
const h = {
left: n.clientX,
top: n.clientY
}, f = e.prosemirrorView.posAtCoords(h);
if (!f)
return;
d = e.transact((m) => {
var y;
const b = D(m.doc, f.pos), g = (y = e.domElement) == null ? void 0 : y.querySelector(
`[data-id="${b.node.attrs.id}"]`
), x = g == null ? void 0 : g.getBoundingClientRect();
return de(
e,
e.getBlock(b.node.attrs.id),
c,
x && (x.top + x.bottom) / 2 > h.top ? "before" : "after"
);
});
} else
return;
const u = await e.uploadFile(a, d), p = typeof u == "string" ? {
props: {
url: u
}
} : { ...u };
e.updateBlock(d, p);
}
}
}
}
const $o = (n) => T.create({
name: "dropFile",
addProseMirrorPlugins() {
return [
new oe({
props: {
handleDOMEvents: {
drop(e, t) {
if (!n.isEditable)
return;
let o = null;
for (const s of se)
if (t.dataTransfer.types.includes(s)) {
o = s;
break;
}
return o === null ? !0 : o === "Files" ? (Ae(t, n), !0) : !1;
}
}
}
})
];
}
}), Ho = /(^|\n) {0,3}#{1,6} {1,8}[^\n]{1,64}\r?\n\r?\n\s{0,32}\S/, Fo = /(_|__|\*|\*\*|~~|==|\+\+)(?!\s)(?:[^\s](?:.{0,62}[^\s])?|\S)(?=\1)/, Vo = /\[[^\]]{1,128}\]\(https?:\/\/\S{1,999}\)/, Uo = /(?:\s|^)`(?!\s)(?:[^\s`](?:[^`]{0,46}[^\s`])?|[^\s`])`([^\w]|$)/, zo = /(?:^|\n)\s{0,5}-\s{1}[^\n]+\n\s{0,15}-\s/, Ro = /(?:^|\n)\s{0,5}\d+\.\s{1}[^\n]+\n\s{0,15}\d+\.\s/, Go = /\n{2} {0,3}-{2,48}\n{2}/, jo = /(?:\n|^)(```|~~~|\$\$)(?!`|~)[^\s]{0,64} {0,64}[^\n]{0,64}\n[\s\S]{0,9999}?\s*\1 {0,64}(?:\n+|$)/, Wo = /(?:\n|^)(?!\s)\w[^\n]{0,64}\r?\n(-|=)\1{0,64}\n\n\s{0,64}(\w|$)/, qo = /(?:^|(\r?\n\r?\n))( {0,3}>[^\n]{1,333}\n){1,999}($|(\r?\n))/, Ko = /^\s*\|(.+\|)+\s*$/m, Jo = /^\s*\|(\s*[-:]+[-:]\s*\|)+\s*$/m, Yo = /^\s*\|(.+\|)+\s*$/m, Qo = (n) => Ho.test(n) || Fo.test(n) || Vo.test(n) || Uo.test(n) || zo.test(n) || Ro.test(n) || Go.test(n) || jo.test(n) || Wo.test(n) || qo.test(n) || Ko.test(n) || Jo.test(n) || Yo.test(n);
async function Xo(n, e) {
const { schema: t } = e.state;
if (!n.clipboardData)
return !1;
const o = n.clipboardData.getData("text/plain");
if (!o)
return !1;
if (!t.nodes.codeBlock)
return e.pasteText(o), !0;
const s = n.clipboardData.getData("vscode-editor-data"), r = s ? JSON.parse(s) : void 0, i = r == null ? void 0 : r.mode;
return i ? (e.pasteHTML(
`<pre><code class="language-${i}">${o.replace(
/\r\n?/g,
`
`
)}</code></pre>`
), !0) : !1;
}
function Zo({
event: n,
editor: e,
prioritizeMarkdownOverHTML: t,
plainTextAsMarkdown: o
}) {
var l;
if (e.transact(
(a) => a.selection.$from.parent.type.spec.code && a.selection.$to.parent.type.spec.code
)) {
const a = (l = n.clipboardData) == null ? void 0 : l.getData("text/plain");
if (a)
return e.pasteText(a), !0;
}
let r;
for (const a of se)
if (n.clipboardData.types.includes(a)) {
r = a;
break;
}
if (!r)
return !0;
if (r === "vscode-editor-data")
return Xo(n, e.prosemirrorView), !0;
if (r === "Files")
return Ae(n, e), !0;
const i = n.clipboardData.getData(r);
if (r === "blocknote/html")
return e.pasteHTML(i, !0), !0;
if (r === "text/markdown")
return e.pasteMarkdown(i), !0;
if (t) {
const a = n.clipboardData.getData("text/plain");
if (Qo(a))
return e.pasteMarkdown(a), !0;
}
return r === "text/html" ? (e.pasteHTML(i), !0) : o ? (e.pasteMarkdown(i), !0) : (e.pasteText(i), !0);
}
const en = (n, e) => T.create({
name: "pasteFromClipboard",
addProseMirrorPlugins() {
return [
new oe({
props: {
handleDOMEvents: {
paste(t, o) {
if (o.preventDefault(), !!n.isEditable)
return e({
event: o,
editor: n,
defaultPasteHandler: ({
prioritizeMarkdownOverHTML: s = !0,
plainTextAsMarkdown: r = !0
} = {}) => Zo({
event: o,
editor: n,
prioritizeMarkdownOverHTML: s,
plainTextAsMarkdown: r
})
});
}
}
}
})
];
}
});
function tn(n, e, t) {
var l;
let o = !1;
const s = n.state.selection instanceof ne;
if (!s) {
const a = n.state.doc.slice(
n.state.selection.from,
n.state.selection.to,
!1
).content, c = [];
for (let d = 0; d < a.childCount; d++)
c.push(a.child(d));
o = c.find(
(d) => d.type.isInGroup("bnBlock") || d.type.name === "blockGroup" || d.type.spec.group === "blockContent"
) === void 0, o && (e = a);
}
let r;
const i = Be(
n.state.schema,
t
);
if (s) {
((l = e.firstChild) == null ? void 0 : l.type.name) === "table" && (e = e.firstChild.content);
const a = We(
e,
t.schema.inlineContentSchema,
t.schema.styleSchema
);
r = `<table>${i.exportInlineContent(
a,
{}
)}</table>`;
} else if (o) {
const a = qe(
e,
t.schema.inlineContentSchema,
t.schema.styleSchema
);
r = i.exportInlineContent(a, {});
} else {
const a = lt(e);
r = i.exportBlocks(a, {});
}
return r;
}
function Ne(n, e) {
"node" in n.state.selection && n.state.selection.node.type.spec.group === "blockContent" && e.transact(
(i) => i.setSelection(
new $(i.doc.resolve(n.state.selection.from - 1))
)
);
const t = n.serializeForClipboard(
n.state.selection.content()
).dom.innerHTML, o = n.state.selection.content().content, s = tn(
n,
o,
e
), r = ct(s);
return { clipboardHTML: t, externalHTML: s, markdown: r };
}
const ue = () => {
const n = window.getSelection();
if (!n || n.isCollapsed)
return !0;
let e = n.focusNode;
for (; e; ) {
if (e instanceof HTMLElement && e.getAttribute("contenteditable") === "false")
return !0;
e = e.parentElement;
}
return !1;
}, pe = (n, e, t) => {
t.preventDefault(), t.clipboardData.clearData();
const { clipboardHTML: o, externalHTML: s, markdown: r } = Ne(
e,
n
);
t.clipboardData.setData("blocknote/html", o), t.clipboardData.setData("text/html", s), t.clipboardData.setData("text/plain", r);
}, on = (n) => T.create({
name: "copyToClipboard",
addProseMirrorPlugins() {
return [
new oe({
props: {
handleDOMEvents: {
copy(e, t) {
return ue() || pe(n, e, t), !0;
},
cut(e, t) {
return ue() || (pe(n, e, t), e.editable && e.dispatch(e.state.tr.deleteSelection())), !0;
},
// This is for the use-case in which only a block without content
// is selected, e.g. an image block, and dragged (not using the
// drag handle).
dragstart(e, t) {
if (!("node" in e.state.selection) || e.state.selection.node.type.spec.group !== "blockContent")
return;
n.transact(
(i) => i.setSelection(
new $(
i.doc.resolve(e.state.selection.from - 1)
)
)
), t.preventDefault(), t.dataTransfer.clearData();
const { clipboardHTML: o, externalHTML: s, markdown: r } = Ne(e, n);
return t.dataTransfer.setData("blocknote/html", o), t.dataTransfer.setData("text/html", s), t.dataTransfer.setData("text/plain", r), !0;
}
}
}
})
];
}
}), nn = T.create({
name: "blockBackgroundColor",
addGlobalAttributes() {
return [
{
types: ["tableCell", "tableHeader"],
attributes: {
backgroundColor: tt()
}
}
];
}
}), sn = O.create({
name: "hardBreak",
inline: !0,
group: "inline",
selectable: !1,
linebreakReplacement: !0,
priority: 10,
parseHTML() {
return [{ tag: "br" }];
},
renderHTML({ HTMLAttributes: n }) {
return ["br", wt(this.options.HTMLAttributes, n)];
},
renderText() {
return `
`;
}
}), _e = (n, e) => {
var l;
const t = n.resolve(e), o = t.depth - 1, s = t.before(o), r = n.resolve(s).nodeAfter;
return r ? (l = r.type.spec.group) != null && l.includes("bnBlock") ? v(
n.resolve(s)
) : _e(n, s) : void 0;
}, L = (n, e) => {
const t = n.resolve(e), o = t.index();
if (o === 0)
return;
const s = t.posAtIndex(o - 1);
return v(
n.resolve(s)
);
}, _ = (n, e) => {
const t = n.resolve(e), o = t.index();
if (o === t.node().childCount - 1)
return;
const s = t.posAtIndex(o + 1);
return v(
n.resolve(s)
);
}, Le = (n, e) => {
for (; e.childContainer; ) {
const t = e.childContainer.node, o = n.resolve(e.childContainer.beforePos + 1).posAtIndex(t.childCount - 1);
e = v(n.resolve(o));
}
return e;
}, rn = (n, e) => n.isBlockContainer && n.blockContent.node.type.spec.content === "inline*" && n.blockContent.node.childCount > 0 && e.isBlockContainer && e.blockContent.node.type.spec.content === "inline*", an = (n, e, t, o) => {
if (!o.isBlockContainer)
throw new Error(
`Attempted to merge block at position ${o.bnBlock.beforePos} into previous block at position ${t.bnBlock.beforePos}, but next block is not a block container`
);
if (o.childContainer) {
const s = n.doc.resolve(
o.childContainer.beforePos + 1
), r = n.doc.resolve(
o.childContainer.afterPos - 1
), i = s.blockRange(r);
if (e) {
const l = n.doc.resolve(o.bnBlock.beforePos);
n.tr.lift(i, l.depth);
}
}
if (e) {
if (!t.isBlockContainer)
throw new Error(
`Attempted to merge block at position ${o.bnBlock.beforePos} into previous block at position ${t.bnBlock.beforePos}, but previous block is not a block container`
);
e(
n.tr.delete(
t.blockContent.afterPos - 1,
o.blockContent.beforePos + 1
)
);
}
return !0;
}, fe = (n) => ({
state: e,
dispatch: t
}) => {
const o = e.doc.resolve(n), s = v(o), r = L(
e.doc,
s.bnBlock.beforePos
);
if (!r)
return !1;
const i = Le(
e.doc,
r
);
return rn(i, s) ? an(e, t, i, s) : !1;
}, cn = T.create({
priority: 50,
// TODO: The shortcuts need a refactor. Do we want to use a command priority
// design as there is now, or clump the logic into a single function?
addKeyboardShortcuts() {
const n = () => this.editor.commands.first(({ chain: o, commands: s }) => [
// Deletes the selection if it's not empty.
() => s.deleteSelection(),
// Undoes an input rule if one was triggered in the last editor state change.
() => s.undoInputRule(),
// Reverts block content type to a paragraph if the selection is at the start of the block.
() => s.command(({ state: r }) => {
const i = B(r);
if (!i.isBlockContainer)
return !1;
const l = r.selection.from === i.blockContent.beforePos + 1, a = i.blockContent.node.type.name === "paragraph";
return l && !a ? s.command(
nt(i.bnBlock.beforePos, {
type: "paragraph",
props: {}
})
) : !1;
}),
// Removes a level of nesting if the block is indented if the selection is at the start of the block.
() => s.command(({ state: r }) => {
const i = B(r);
if (!i.isBlockContainer)
return !1;
const { blockContent: l } = i;
return r.selection.from === l.beforePos + 1 ? s.liftListItem("blockContainer") : !1;
}),
// Merges block with the previous one if it isn't indented, and the selection is at the start of the
// block. The target block for merging must contain inline content.
() => s.command(({ state: r }) => {
const i = B(r);
if (!i.isBlockContainer)
return !1;
const { bnBlock: l, blockContent: a } = i, c = L(
r.doc,
i.bnBlock.beforePos
);
if (!c || !c.isBlockContainer || c.blockContent.node.type.spec.content !== "inline*")
return !1;
const d = r.selection.from === a.beforePos + 1, u = r.selection.empty, p = l.beforePos;
return d && u ? o().command(fe(p)).scrollIntoView().run() : !1;
}),
// If the previous block is a columnList, moves the current block to
// the end of the last column in it.
() => s.command(({ state: r, tr: i, dispatch: l }) => {
const a = B(r);
if (!a.isBlockContainer)
return !1;
const c = L(
r.doc,
a.bnBlock.beforePos
);
if (!c || c.isBlockContainer)