@trafica/editor 1.0.47 → 1.0.49
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 +80 -122
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +80 -122
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1038,26 +1038,33 @@ function renderCodeBlock(node, path) {
|
|
|
1038
1038
|
return wrapper;
|
|
1039
1039
|
}
|
|
1040
1040
|
function renderImage(node, path) {
|
|
1041
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
1041
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
1042
1042
|
const wrapper = document.createElement("figure");
|
|
1043
1043
|
wrapper.dataset.blockPath = JSON.stringify(path);
|
|
1044
1044
|
wrapper.dataset.imagePath = JSON.stringify(path);
|
|
1045
1045
|
wrapper.contentEditable = "false";
|
|
1046
1046
|
const align = (_a = node.attrs) == null ? void 0 : _a.align;
|
|
1047
|
+
const fx = (_b = node.attrs) == null ? void 0 : _b.x;
|
|
1048
|
+
const fy = (_c = node.attrs) == null ? void 0 : _c.y;
|
|
1047
1049
|
wrapper.className = [
|
|
1048
1050
|
"editor-image-wrapper",
|
|
1049
|
-
|
|
1050
|
-
align === "
|
|
1051
|
-
align === "
|
|
1051
|
+
fx !== void 0 ? "editor-image-floating" : "",
|
|
1052
|
+
!fx && align === "center" ? "editor-image-center" : "",
|
|
1053
|
+
!fx && align === "right" ? "editor-image-right" : "",
|
|
1054
|
+
!fx && align === "left" ? "editor-image-left" : ""
|
|
1052
1055
|
].filter(Boolean).join(" ");
|
|
1056
|
+
if (fx !== void 0) {
|
|
1057
|
+
wrapper.style.left = `${fx}px`;
|
|
1058
|
+
wrapper.style.top = `${fy != null ? fy : 0}px`;
|
|
1059
|
+
}
|
|
1053
1060
|
const img = document.createElement("img");
|
|
1054
|
-
img.src = (
|
|
1055
|
-
img.alt = (
|
|
1061
|
+
img.src = (_e = (_d = node.attrs) == null ? void 0 : _d.src) != null ? _e : "";
|
|
1062
|
+
img.alt = (_g = (_f = node.attrs) == null ? void 0 : _f.alt) != null ? _g : "";
|
|
1056
1063
|
img.className = "editor-image";
|
|
1057
1064
|
img.draggable = false;
|
|
1058
|
-
if ((
|
|
1065
|
+
if ((_h = node.attrs) == null ? void 0 : _h.width) img.style.width = `${node.attrs.width}px`;
|
|
1059
1066
|
wrapper.appendChild(img);
|
|
1060
|
-
const caption = (
|
|
1067
|
+
const caption = (_i = node.attrs) == null ? void 0 : _i.caption;
|
|
1061
1068
|
if (caption !== void 0) {
|
|
1062
1069
|
const figcaption = document.createElement("figcaption");
|
|
1063
1070
|
figcaption.className = "editor-image-caption";
|
|
@@ -1644,7 +1651,7 @@ var htmlSerializer = {
|
|
|
1644
1651
|
}
|
|
1645
1652
|
};
|
|
1646
1653
|
function serializeBlock(node, idCounts = /* @__PURE__ */ new Map(), inCell = false) {
|
|
1647
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A;
|
|
1654
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C;
|
|
1648
1655
|
switch (node.type) {
|
|
1649
1656
|
case "paragraph": {
|
|
1650
1657
|
const alignVal = (_a = node.attrs) == null ? void 0 : _a.align;
|
|
@@ -1696,16 +1703,19 @@ function serializeBlock(node, idCounts = /* @__PURE__ */ new Map(), inCell = fal
|
|
|
1696
1703
|
const width = ((_m = node.attrs) == null ? void 0 : _m.width) ? ` width="${node.attrs.width}"` : "";
|
|
1697
1704
|
const align = ((_n = node.attrs) == null ? void 0 : _n.align) ? ` data-align="${node.attrs.align}"` : "";
|
|
1698
1705
|
const caption = ((_o = node.attrs) == null ? void 0 : _o.caption) ? escapeHTML(node.attrs.caption) : "";
|
|
1706
|
+
const x = (_p = node.attrs) == null ? void 0 : _p.x;
|
|
1707
|
+
const y = (_q = node.attrs) == null ? void 0 : _q.y;
|
|
1708
|
+
const posAttrs = x !== void 0 ? ` data-x="${Math.round(x)}" data-y="${Math.round(y != null ? y : 0)}" style="position:absolute;left:${Math.round(x)}px;top:${Math.round(y != null ? y : 0)}px;"` : "";
|
|
1699
1709
|
if (caption) {
|
|
1700
|
-
return `<figure${align}><img src="${src}" alt="${alt}"${width} /><figcaption>${caption}</figcaption></figure>`;
|
|
1710
|
+
return `<figure${align}${posAttrs}><img src="${src}" alt="${alt}"${width} /><figcaption>${caption}</figcaption></figure>`;
|
|
1701
1711
|
}
|
|
1702
|
-
return `<figure${align}><img src="${src}" alt="${alt}"${width} /></figure>`;
|
|
1712
|
+
return `<figure${align}${posAttrs}><img src="${src}" alt="${alt}"${width} /></figure>`;
|
|
1703
1713
|
}
|
|
1704
1714
|
case "horizontal_rule":
|
|
1705
1715
|
return "<hr />";
|
|
1706
1716
|
case "table": {
|
|
1707
1717
|
const rows = node.children.map((c) => serializeBlock(c)).join("");
|
|
1708
|
-
const colWidths = (
|
|
1718
|
+
const colWidths = (_s = (_r = node.attrs) == null ? void 0 : _r.colWidths) != null ? _s : [];
|
|
1709
1719
|
let colgroup = "";
|
|
1710
1720
|
if (colWidths.length > 0) {
|
|
1711
1721
|
const total = colWidths.reduce((s, w) => s + w, 0) || colWidths.length * 120;
|
|
@@ -1718,15 +1728,15 @@ function serializeBlock(node, idCounts = /* @__PURE__ */ new Map(), inCell = fal
|
|
|
1718
1728
|
return `<tr>${cells}</tr>`;
|
|
1719
1729
|
}
|
|
1720
1730
|
case "table_cell": {
|
|
1721
|
-
if ((
|
|
1722
|
-
const cs = ((
|
|
1723
|
-
const rs = ((
|
|
1731
|
+
if ((_t = node.attrs) == null ? void 0 : _t.covered) return "";
|
|
1732
|
+
const cs = ((_u = node.attrs) == null ? void 0 : _u.colspan) > 1 ? ` colspan="${(_v = node.attrs) == null ? void 0 : _v.colspan}"` : "";
|
|
1733
|
+
const rs = ((_w = node.attrs) == null ? void 0 : _w.rowspan) > 1 ? ` rowspan="${(_x = node.attrs) == null ? void 0 : _x.rowspan}"` : "";
|
|
1724
1734
|
return `<td${cs}${rs} style="border:1px solid #d1d5db;padding:0.5em 0.75em;vertical-align:top;min-width:40px;word-break:break-word;">${node.children.map((c) => serializeBlock(c, /* @__PURE__ */ new Map(), true)).join("")}</td>`;
|
|
1725
1735
|
}
|
|
1726
1736
|
case "table_header": {
|
|
1727
|
-
if ((
|
|
1728
|
-
const cs = ((
|
|
1729
|
-
const rs = ((
|
|
1737
|
+
if ((_y = node.attrs) == null ? void 0 : _y.covered) return "";
|
|
1738
|
+
const cs = ((_z = node.attrs) == null ? void 0 : _z.colspan) > 1 ? ` colspan="${(_A = node.attrs) == null ? void 0 : _A.colspan}"` : "";
|
|
1739
|
+
const rs = ((_B = node.attrs) == null ? void 0 : _B.rowspan) > 1 ? ` rowspan="${(_C = node.attrs) == null ? void 0 : _C.rowspan}"` : "";
|
|
1730
1740
|
return `<th${cs}${rs} style="border:1px solid #d1d5db;padding:0.5em 0.75em;vertical-align:top;min-width:40px;word-break:break-word;background:#f9fafb;font-weight:600;text-align:left;">${node.children.map((c) => serializeBlock(c, /* @__PURE__ */ new Map(), true)).join("")}</th>`;
|
|
1731
1741
|
}
|
|
1732
1742
|
default:
|
|
@@ -1880,6 +1890,10 @@ function parseHTMLNode(node) {
|
|
|
1880
1890
|
const img = el.querySelector("img");
|
|
1881
1891
|
const caption = (_h = (_g = el.querySelector("figcaption")) == null ? void 0 : _g.textContent) != null ? _h : "";
|
|
1882
1892
|
const align = (_i = el.getAttribute("data-align")) != null ? _i : "";
|
|
1893
|
+
const dxRaw = el.getAttribute("data-x");
|
|
1894
|
+
const dyRaw = el.getAttribute("data-y");
|
|
1895
|
+
const fx = dxRaw !== null ? parseFloat(dxRaw) : void 0;
|
|
1896
|
+
const fy = dyRaw !== null ? parseFloat(dyRaw) : void 0;
|
|
1883
1897
|
if (img) {
|
|
1884
1898
|
return {
|
|
1885
1899
|
type: "image",
|
|
@@ -1888,7 +1902,8 @@ function parseHTMLNode(node) {
|
|
|
1888
1902
|
alt: (_k = img.getAttribute("alt")) != null ? _k : "",
|
|
1889
1903
|
...img.getAttribute("width") ? { width: parseFloat(img.getAttribute("width")) } : {},
|
|
1890
1904
|
...align ? { align } : {},
|
|
1891
|
-
...caption ? { caption } : {}
|
|
1905
|
+
...caption ? { caption } : {},
|
|
1906
|
+
...fx !== void 0 && !isNaN(fx) ? { x: fx, y: fy != null ? fy : 0 } : {}
|
|
1892
1907
|
},
|
|
1893
1908
|
children: []
|
|
1894
1909
|
};
|
|
@@ -8036,7 +8051,7 @@ function EditorCore({
|
|
|
8036
8051
|
const isComposingRef = react.useRef(false);
|
|
8037
8052
|
const stateRef = react.useRef(engine.getState());
|
|
8038
8053
|
const [selectedImagePath, setSelectedImagePath] = react.useState(null);
|
|
8039
|
-
const [
|
|
8054
|
+
const [imageDragging, setImageDragging] = react.useState(false);
|
|
8040
8055
|
const [findReplaceOpen, setFindReplaceOpen] = react.useState(false);
|
|
8041
8056
|
const [findReplaceMode, setFindReplaceMode] = react.useState("find");
|
|
8042
8057
|
const [linkPopupOpen, setLinkPopupOpen] = react.useState(false);
|
|
@@ -8520,15 +8535,17 @@ function EditorCore({
|
|
|
8520
8535
|
const path = JSON.parse(fig.dataset.imagePath);
|
|
8521
8536
|
setSelectedImagePath(path);
|
|
8522
8537
|
const imgEl = fig.querySelector("img");
|
|
8523
|
-
const
|
|
8538
|
+
const figRect = fig.getBoundingClientRect();
|
|
8524
8539
|
imageDragRef.current = {
|
|
8525
8540
|
imagePath: path,
|
|
8526
8541
|
startX: e.clientX,
|
|
8527
8542
|
startY: e.clientY,
|
|
8528
8543
|
active: false,
|
|
8529
|
-
ghostW: Math.min(
|
|
8530
|
-
ghostH: Math.min(
|
|
8531
|
-
ghostSrc: (imgEl == null ? void 0 : imgEl.src) || ""
|
|
8544
|
+
ghostW: Math.min(figRect.width || 300, 320),
|
|
8545
|
+
ghostH: Math.min(figRect.height || 200, 200),
|
|
8546
|
+
ghostSrc: (imgEl == null ? void 0 : imgEl.src) || "",
|
|
8547
|
+
offsetX: e.clientX - figRect.left,
|
|
8548
|
+
offsetY: e.clientY - figRect.top
|
|
8532
8549
|
};
|
|
8533
8550
|
return;
|
|
8534
8551
|
}
|
|
@@ -8616,39 +8633,58 @@ function EditorCore({
|
|
|
8616
8633
|
};
|
|
8617
8634
|
}, [engine]);
|
|
8618
8635
|
react.useEffect(() => {
|
|
8619
|
-
const DRAG_THRESHOLD =
|
|
8636
|
+
const DRAG_THRESHOLD = 4;
|
|
8620
8637
|
const onMouseMove = (e) => {
|
|
8621
8638
|
const drag = imageDragRef.current;
|
|
8622
8639
|
if (!drag) return;
|
|
8623
8640
|
const dx = e.clientX - drag.startX;
|
|
8624
8641
|
const dy = e.clientY - drag.startY;
|
|
8625
8642
|
if (!drag.active && Math.sqrt(dx * dx + dy * dy) < DRAG_THRESHOLD) return;
|
|
8626
|
-
drag.active
|
|
8643
|
+
if (!drag.active) {
|
|
8644
|
+
drag.active = true;
|
|
8645
|
+
setImageDragging(true);
|
|
8646
|
+
document.body.style.userSelect = "none";
|
|
8647
|
+
}
|
|
8627
8648
|
const container = containerRef.current;
|
|
8628
|
-
|
|
8629
|
-
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
|
|
8633
|
-
|
|
8634
|
-
|
|
8635
|
-
|
|
8636
|
-
|
|
8637
|
-
|
|
8638
|
-
|
|
8649
|
+
if (!container) return;
|
|
8650
|
+
const cr = container.getBoundingClientRect();
|
|
8651
|
+
const fig = container.querySelector(
|
|
8652
|
+
`[data-image-path="${JSON.stringify(drag.imagePath)}"]`
|
|
8653
|
+
);
|
|
8654
|
+
const figW = (fig == null ? void 0 : fig.offsetWidth) || drag.ghostW;
|
|
8655
|
+
const figH = (fig == null ? void 0 : fig.offsetHeight) || drag.ghostH;
|
|
8656
|
+
const rawX = e.clientX - cr.left - drag.offsetX + container.scrollLeft;
|
|
8657
|
+
const rawY = e.clientY - cr.top - drag.offsetY + container.scrollTop;
|
|
8658
|
+
const x = Math.max(0, Math.min(rawX, container.clientWidth - figW));
|
|
8659
|
+
const y = Math.max(0, Math.min(rawY, container.scrollHeight - figH));
|
|
8660
|
+
if (fig) {
|
|
8661
|
+
fig.style.position = "absolute";
|
|
8662
|
+
fig.style.left = `${x}px`;
|
|
8663
|
+
fig.style.top = `${y}px`;
|
|
8664
|
+
fig.style.margin = "0";
|
|
8665
|
+
fig.style.zIndex = "10";
|
|
8666
|
+
}
|
|
8639
8667
|
};
|
|
8640
8668
|
const onMouseUp = (e) => {
|
|
8641
8669
|
const drag = imageDragRef.current;
|
|
8642
8670
|
if (!drag) return;
|
|
8643
8671
|
imageDragRef.current = null;
|
|
8644
|
-
|
|
8645
|
-
|
|
8646
|
-
|
|
8647
|
-
}
|
|
8672
|
+
document.body.style.userSelect = "";
|
|
8673
|
+
setImageDragging(false);
|
|
8674
|
+
if (!drag.active) return;
|
|
8648
8675
|
const container = containerRef.current;
|
|
8649
|
-
|
|
8650
|
-
|
|
8651
|
-
|
|
8676
|
+
if (!container) return;
|
|
8677
|
+
const cr = container.getBoundingClientRect();
|
|
8678
|
+
const fig = container.querySelector(
|
|
8679
|
+
`[data-image-path="${JSON.stringify(drag.imagePath)}"]`
|
|
8680
|
+
);
|
|
8681
|
+
const figW = (fig == null ? void 0 : fig.offsetWidth) || drag.ghostW;
|
|
8682
|
+
const figH = (fig == null ? void 0 : fig.offsetHeight) || drag.ghostH;
|
|
8683
|
+
const rawX = e.clientX - cr.left - drag.offsetX + container.scrollLeft;
|
|
8684
|
+
const rawY = e.clientY - cr.top - drag.offsetY + container.scrollTop;
|
|
8685
|
+
const x = Math.max(0, Math.min(rawX, container.clientWidth - figW));
|
|
8686
|
+
const y = Math.max(0, Math.min(rawY, container.scrollHeight - figH));
|
|
8687
|
+
setImageAttr(drag.imagePath, { x: Math.round(x), y: Math.round(y) })(engine);
|
|
8652
8688
|
};
|
|
8653
8689
|
document.addEventListener("mousemove", onMouseMove);
|
|
8654
8690
|
document.addEventListener("mouseup", onMouseUp);
|
|
@@ -8774,19 +8810,6 @@ function EditorCore({
|
|
|
8774
8810
|
].join(" ")
|
|
8775
8811
|
}
|
|
8776
8812
|
),
|
|
8777
|
-
imageDragState && (() => {
|
|
8778
|
-
const container = containerRef.current;
|
|
8779
|
-
if (!container) return null;
|
|
8780
|
-
const cr = container.getBoundingClientRect();
|
|
8781
|
-
const relY = imageDragState.dropIndicatorClientY - cr.top + container.scrollTop;
|
|
8782
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8783
|
-
"div",
|
|
8784
|
-
{
|
|
8785
|
-
className: "editor-image-drop-indicator",
|
|
8786
|
-
style: { top: relY }
|
|
8787
|
-
}
|
|
8788
|
-
);
|
|
8789
|
-
})(),
|
|
8790
8813
|
linkTooltip && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8791
8814
|
"div",
|
|
8792
8815
|
{
|
|
@@ -8847,26 +8870,6 @@ function EditorCore({
|
|
|
8847
8870
|
onClose: () => setSelectedImagePath(null)
|
|
8848
8871
|
}
|
|
8849
8872
|
),
|
|
8850
|
-
imageDragState && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8851
|
-
"div",
|
|
8852
|
-
{
|
|
8853
|
-
className: "editor-image-drag-ghost",
|
|
8854
|
-
style: {
|
|
8855
|
-
left: imageDragState.ghostX,
|
|
8856
|
-
top: imageDragState.ghostY,
|
|
8857
|
-
width: imageDragState.ghostW,
|
|
8858
|
-
height: imageDragState.ghostH
|
|
8859
|
-
},
|
|
8860
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8861
|
-
"img",
|
|
8862
|
-
{
|
|
8863
|
-
src: imageDragState.ghostSrc,
|
|
8864
|
-
alt: "",
|
|
8865
|
-
style: { width: "100%", height: "100%", objectFit: "contain", display: "block" }
|
|
8866
|
-
}
|
|
8867
|
-
)
|
|
8868
|
-
}
|
|
8869
|
-
),
|
|
8870
8873
|
!readOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8871
8874
|
"div",
|
|
8872
8875
|
{
|
|
@@ -8889,51 +8892,6 @@ function EditorCore({
|
|
|
8889
8892
|
}
|
|
8890
8893
|
);
|
|
8891
8894
|
}
|
|
8892
|
-
function getImageDropTarget(container, clientY, imagePath) {
|
|
8893
|
-
const fallback = { dropIndex: imagePath[0], indicatorClientY: clientY };
|
|
8894
|
-
if (!container) return fallback;
|
|
8895
|
-
const blocks = Array.from(
|
|
8896
|
-
container.querySelectorAll(":scope > [data-block-path]")
|
|
8897
|
-
);
|
|
8898
|
-
if (blocks.length === 0) return fallback;
|
|
8899
|
-
const gaps = [];
|
|
8900
|
-
gaps.push({ y: blocks[0].getBoundingClientRect().top, index: 0 });
|
|
8901
|
-
for (let i = 0; i < blocks.length - 1; i++) {
|
|
8902
|
-
const bottom = blocks[i].getBoundingClientRect().bottom;
|
|
8903
|
-
const top = blocks[i + 1].getBoundingClientRect().top;
|
|
8904
|
-
gaps.push({ y: (bottom + top) / 2, index: i + 1 });
|
|
8905
|
-
}
|
|
8906
|
-
gaps.push({ y: blocks[blocks.length - 1].getBoundingClientRect().bottom, index: blocks.length });
|
|
8907
|
-
let best = gaps[0];
|
|
8908
|
-
let bestDist = Math.abs(clientY - best.y);
|
|
8909
|
-
for (const gap of gaps) {
|
|
8910
|
-
const dist = Math.abs(clientY - gap.y);
|
|
8911
|
-
if (dist < bestDist) {
|
|
8912
|
-
bestDist = dist;
|
|
8913
|
-
best = gap;
|
|
8914
|
-
}
|
|
8915
|
-
}
|
|
8916
|
-
return { dropIndex: best.index, indicatorClientY: best.y };
|
|
8917
|
-
}
|
|
8918
|
-
function moveImageInDoc(imagePath, targetIndex, engine) {
|
|
8919
|
-
const state = engine.getState();
|
|
8920
|
-
const imageNode = getNodeAtPath(state.doc, imagePath);
|
|
8921
|
-
if (!imageNode) return;
|
|
8922
|
-
const isTopLevel = imagePath.length === 1;
|
|
8923
|
-
const topLevelIndex = imagePath[0];
|
|
8924
|
-
let adj = targetIndex;
|
|
8925
|
-
if (isTopLevel) {
|
|
8926
|
-
if (targetIndex > topLevelIndex) adj = targetIndex - 1;
|
|
8927
|
-
adj = Math.max(0, Math.min(state.doc.children.length - 1, adj));
|
|
8928
|
-
if (adj === topLevelIndex) return;
|
|
8929
|
-
} else {
|
|
8930
|
-
adj = Math.max(0, Math.min(state.doc.children.length, adj));
|
|
8931
|
-
}
|
|
8932
|
-
const tr = createTransaction();
|
|
8933
|
-
tr.steps.push({ type: "delete_node", path: imagePath });
|
|
8934
|
-
tr.steps.push({ type: "insert_node", parentPath: [], index: adj, node: imageNode });
|
|
8935
|
-
engine.dispatch(tr);
|
|
8936
|
-
}
|
|
8937
8895
|
var BLOCK_TAGS = "p|h[1-6]|ul|ol|li|blockquote|pre|figure|table|thead|tbody|tr|th|td";
|
|
8938
8896
|
var _OPEN_ONLY_RE = new RegExp(`^<(${BLOCK_TAGS})(?:\\s[^>]*)?>$`, "i");
|
|
8939
8897
|
var _CLOSE_ONLY_RE = new RegExp(`^<\\/(${BLOCK_TAGS})>$`, "i");
|