UNPKG

@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
/** * @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 };