@progress/kendo-react-editor
Version:
React Editor enables users to create rich text content through a WYSIWYG interface. KendoReact Editor package
292 lines (291 loc) • 11.8 kB
JavaScript
/**
* @license
*-------------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the package root for more information
*-------------------------------------------------------------------------------------------
*/
import { pmDocToFragment as F, fragmentToHtml as j, TableMap as A, Selection as O, TextSelection as B, CellSelection as U, addColumnAfter as q, addRowAfter as G, parseContent as J } from "@progress/kendo-editor-common";
import { deleteColumnCmd as K, deleteRowCmd as L } from "../tableEdit.mjs";
import { selectedCells as P, parseStyle as S, nodeSize as _, tableCells as Q, setNodeStyle as h } from "./utils.mjs";
import { parentNode as T } from "../utils.mjs";
const N = {
rows: 0,
columns: 0,
width: null,
widthUnit: "",
height: null,
heightUnit: "",
position: null,
textAlign: "",
cellPadding: null,
cellSpacing: null,
backgroundColor: void 0,
borderWidth: null,
borderColor: void 0,
borderStyle: null,
collapseBorders: !1,
id: "",
className: "",
caption: "",
captionAlignment: null,
captionPosition: null,
headerRows: 0,
headerColumns: 0,
associateHeaders: "none"
}, k = {
left: { "margin-left": "", "margin-right": "auto" },
center: { "margin-left": "auto", "margin-right": "auto" },
right: { "margin-left": "auto", "margin-right": "" },
"": {}
}, z = (o) => {
const t = [];
for (let s = 0; s < o.height; s++) {
const l = s * o.width, e = l + o.width;
t.push(o.map.slice(l, e));
}
return t;
}, V = (o, t) => {
let s = 0, l = 0;
const e = z(t);
e.forEach((n) => {
let i = !0;
n.forEach((r) => {
const c = o.nodeAt(r);
c && c.type.name !== "table_header" && (i = !1);
}), i && s++;
});
for (let n = 0; n < t.width; n++) {
let i = !0;
for (let r = 0; r < t.height; r++) {
const c = e[r] && e[r][n], u = typeof c == "number" && o.nodeAt(c);
u && u.type.name !== "table_header" && (i = !1);
}
i && l++;
}
return { rows: s, columns: l };
}, X = (o) => {
const t = /* @__PURE__ */ new Set();
return o.content.forEach((s) => {
s.content.forEach((l) => {
t.add(S(l.attrs.style).padding || "");
});
}), t.size === 1 ? Array.from(t)[0] : "";
}, Y = (o) => {
let t = !0, s = !0;
return o.content.forEach((l) => {
l.content.forEach((e) => {
const n = e.type.name === "table_header", i = e.type.name === "table_cell";
n && !e.attrs.scope && (t = !1), (n && !e.attrs.id || i && !e.attrs.headers) && (s = !1);
});
}), t ? "scope" : s ? "id" : "none";
}, ce = (o) => {
var p, a, b;
const t = P(o), s = o.selection.$from, l = t.length ? T(s, (f) => f.type.spec.tableRole === "table") : null;
if (!l)
return N;
const e = T(s, (f) => f.type.name === "table_wrapper");
let n = "", i = {}, r = {};
e && (r = S(e.node.attrs.style), e.node.content.forEach((f) => {
if (f.type.name === "table_caption_external") {
const y = F(f);
n = j(y), n = n === "<img>" ? "" : n, i = S(f.attrs.style);
}
}));
const c = S(((p = l.node.attrs) == null ? void 0 : p.style) || ""), u = A.get(l.node), d = r["margin-left"] === "auto" && r["margin-right"] === "auto" ? "center" : r["margin-right"] === "auto" ? "left" : r["margin-left"] === "auto" ? "right" : null, g = V(l.node, u), m = X(l.node);
return {
...N,
columns: u.width,
rows: u.height,
..._(l.node, "width"),
...e && /%/.test(r.width || "") ? _(e.node, "width") : {},
..._(l.node, "height"),
textAlign: c["text-align"] || "",
position: d || null,
cellPadding: m ? parseFloat(m) : null,
cellSpacing: c["border-spacing"] ? parseFloat(c["border-spacing"]) : null,
backgroundColor: c["background-color"],
borderWidth: c["border-width"] ? parseFloat(c["border-width"]) : null,
borderColor: c["border-color"],
borderStyle: c["border-style"] || null,
collapseBorders: c["border-collapse"] === "collapse",
caption: n || void 0,
captionAlignment: i["text-align"] || "",
captionPosition: i["caption-side"] || null,
headerRows: g.rows,
headerColumns: g.columns,
associateHeaders: g.rows || g.columns ? Y(l.node) : "none",
id: ((a = l.node.attrs) == null ? void 0 : a.id) || "",
className: ((b = l.node.attrs) == null ? void 0 : b.class) || ""
};
}, $ = (o) => {
const s = o.lastChild.lastChild;
return { node: s, pos: o.content.size - s.nodeSize };
}, R = (o, t, s, l, e) => {
const n = $(s), i = t + n.pos;
if (!o.doc.nodeAt(i))
return o;
const c = o.doc.resolve(i), u = new U(c, c), d = o.tr.setSelection(u);
let g = o.apply(d);
for (let m = 0; m < l; m++)
e(g, (p) => {
g = g.apply(p);
});
return g;
}, x = (o, t, s, l) => {
let e = o;
for (let n = 0; n < s; n++) {
const i = e.doc.nodeAt(t);
if (i) {
const r = $(i), c = t + r.pos, u = e.doc.resolve(c), d = new U(u, u), g = e.tr.setSelection(d);
e = e.apply(g), l(e, (m) => {
e = e.apply(m);
});
}
}
return e;
}, Z = (o, t, s, l) => {
let e = o, n = e.doc.nodeAt(t);
if (!n)
return e;
let i = A.get(n);
return i.width === l && i.height === s || (l > i.width ? e = R(e, t, n, l - i.width, q) : l < i.width && (e = x(e, t, i.width - l, K)), n = e.doc.nodeAt(t), !n) || (i = A.get(n), s > i.height ? e = R(e, t, n, s - i.height, G) : s < i.height && (e = x(e, t, i.height - s, L))), e;
}, W = (o, t, s) => {
const l = o.doc.nodeAt(s);
if (!l)
return o;
let e = { ...l.attrs };
const n = t.width !== null && (t.widthUnit !== "%" || !t.caption && !t.position);
e = h(e, "width", n ? t.width + t.widthUnit : ""), e = h(e, "height", t.height !== null ? t.height + t.heightUnit : ""), e = h(e, "text-align", t.textAlign || ""), e = h(e, "background-color", t.backgroundColor || ""), e = h(e, "border-width", t.borderWidth ? t.borderWidth + "px" : ""), e = h(e, "border-style", t.borderStyle || ""), e = h(e, "border-color", t.borderColor || ""), e = h(e, "border-spacing", t.cellSpacing !== null ? t.cellSpacing + "px" : ""), t.cellSpacing !== null ? e = h(e, "border-collapse", "unset") : e = h(e, "border-collapse", t.collapseBorders ? "collapse" : "");
const i = k[t.position || ""] || {};
Object.keys(i).forEach((c) => {
e = h(e, c, i[c]);
}), e.id = t.id || null, e.class = t.className || null;
const r = o.tr.setNodeMarkup(s, null, e);
return o = o.apply(r), o;
}, H = (o, t, s, l, e) => {
if (t.type.name !== l.name || Object.keys(e).length > 0) {
const n = o.tr.setNodeMarkup(s, l, { ...t.attrs, ...e });
return o.apply(n);
}
return o;
}, I = (o, t) => {
/^cell-[0-9]+-[0-9]+$/.test(o.attrs.id || "") && (t.id = null);
}, ee = (o, t, s) => {
const l = o.doc.nodeAt(s), e = l && A.get(l);
if (!l || !e)
return o;
const n = z(e);
let i = o;
const { table_header: r, table_cell: c } = o.schema.nodes, u = String((/* @__PURE__ */ new Date()).getTime()), d = [], g = (p, a) => {
const b = `cell-${p}${a}-${u}`;
return d[p] || d.push([]), d[p][a] || d[p].push([]), d[p][a] = b, b;
}, m = (p, a, b, f) => {
const y = [];
if (f)
for (let w = 0; w < p; w++)
d[w] && d[w][a] && y.push(d[w][a]);
if (b)
for (let w = 0; w < a; w++)
d[p] && d[p][w] && y.push(d[p][w]);
return y.join(" ");
};
return n.forEach((p, a) => {
p.forEach((b, f) => {
const y = l.nodeAt(b);
if (y) {
const w = f < t.headerColumns, E = a < t.headerRows, C = { ...y.attrs };
I(y, C), C.headers = null, C.scope = null, E || w ? (t.associateHeaders === "scope" && (C.scope = E ? "col" : "row"), t.associateHeaders === "id" && (C.id = g(a, f), (f > 0 || a > 0) && (C.headers = m(a, f, w, E) || null)), i = H(i, y, s + b + 1, r, C)) : (t.associateHeaders === "id" && (C.headers = m(a, f, t.headerColumns > 0, t.headerRows > 0) || null), i = H(i, y, s + b + 1, c, C));
}
});
}), i;
}, te = (o, t, s, l) => {
let e = { ...t.attrs };
return e = h(e, "margin-left", ""), e = h(e, "margin-right", ""), Object.keys(l || {}).forEach((n) => {
e = h(e, n, (l || {})[n] || "");
}), o.apply(o.tr.setNodeMarkup(s, null, e));
}, v = (o, t) => J("<p>" + o + "</p>", t).content.firstChild.content, M = (o, t) => {
if (!o.caption)
return;
let s = { caption: "", style: "display: table-caption" };
o.captionAlignment && (s = h(s, "text-align", o.captionAlignment)), o.captionPosition && (s = h(s, "caption-side", o.captionPosition));
const l = v(o.caption, t);
return l && t.nodes.table_caption_external.createAndFill(s, l) || void 0;
}, D = (o) => o.firstChild && o.firstChild.type.name === "table_caption_external", oe = (o, t, s, l) => {
let e = o, n;
const i = s + 2, r = s + 1, c = e.schema;
if (D(t))
if (n = t.firstChild, l.caption) {
const u = v(l.caption, c);
if (e = e.apply(
e.tr.replaceWith(i, i + n.content.size, u)
), n = e.doc.nodeAt(r), n) {
let d = { ...n.attrs };
d = h(d, "text-align", l.captionAlignment || ""), d = h(d, "caption-side", l.captionPosition || ""), e = e.apply(e.tr.setNodeAttribute(r, "style", d.style));
}
} else
e = e.apply(
e.tr.deleteRange(i, i + n.content.size)
);
else
n = M(l, c), n && (e = e.apply(e.tr.replaceWith(r, r, n)));
return e;
}, ne = (o, t, s, l, e) => {
let n = {
state: o,
pos: s
};
if (!l && (t.position || t.caption)) {
let r = { table: "", style: "display: table" };
const c = [], u = t.position, d = u && k[u];
d && Object.keys(d).forEach((a) => {
r = h(r, a, d[a] || "");
}), typeof t.width == "number" && t.widthUnit === "%" && (r = h(r, "width", t.width + t.widthUnit));
const g = M(t, o.schema);
g && c.push(g);
const m = o.doc.nodeAt(s);
c.push(m);
const p = o.schema.nodes.table_wrapper.createAndFill(r, c);
if (p) {
const a = o.tr.replaceWith(s, s + m.content.size, p);
o = o.apply(a), n = { state: o, pos: s };
}
} else l && (t.position || t.caption || !t.caption && D(l.node)) ? (o = te(
o,
l.node,
e,
t.position && k[t.position]
), o = oe(o, l.node, e, t), n = { state: o, pos: e }) : l && !(t.position || t.caption) ? n = { state: o, node: l.node, pos: o.selection.$from.start(l.depth) - 1 } : n = { state: o, pos: s };
const i = l && n.state.doc.nodeAt(e);
if (i) {
let r;
typeof t.width == "number" && t.widthUnit === "%" ? r = h(i.attrs, "width", t.width + t.widthUnit) : t.widthUnit !== "%" && /%/.test(S(i.attrs.style || "").width || "") && (r = h(i.attrs, "width", "")), r && (n.state = n.state.apply(n.state.tr.setNodeMarkup(e, null, r)));
}
return n;
}, de = (o, t) => {
const s = o.selection.$from, l = T(s, (f) => f.type.spec.tableRole === "table");
if (!l)
return;
const e = s.start(l.depth) - 1;
let n = Z(o, e, t.rows, t.columns);
if (!n)
return;
const i = n.tr;
Q(n).forEach((f) => {
let y = { ...f.node.attrs };
y = h(y, "padding", typeof t.cellPadding == "number" ? t.cellPadding + "px" : ""), i.setNodeMarkup(f.pos, null, y);
}), n = n.apply(i), n = W(n, t, e), n = ee(n, t, e);
const r = T(s, (f) => f.type.name === "table_wrapper"), c = s.start((r == null ? void 0 : r.depth) || 0) - 1, u = ne(n, t, e, r, c);
n = u.state;
const d = u.pos, g = n.doc.nodeAt(u.pos);
if (!g)
return;
const m = d + (r || l).node.content.size, p = o.tr.replaceWith(d, m, g), a = O.atEnd(g), b = B.create(p.doc, d + a.to + 1);
return p.setSelection(b), p;
};
export {
de as applyTableData,
N as initialTableData,
ce as tableDefaultData,
k as tablePositionStyles
};