@zm-editor/react 0.1.0 → 0.1.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/README.ko.md +260 -0
- package/README.md +300 -0
- package/dist/index.js +88 -19
- package/dist/styles.css +8078 -0
- package/dist/variables.css +480 -0
- package/package.json +12 -5
package/dist/index.js
CHANGED
|
@@ -6,8 +6,6 @@ export * from '@zm-editor/core';
|
|
|
6
6
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
7
|
import Image from '@tiptap/extension-image';
|
|
8
8
|
import { Node as Node$1, mergeAttributes } from '@tiptap/core';
|
|
9
|
-
import katex from 'katex';
|
|
10
|
-
import mermaid from 'mermaid';
|
|
11
9
|
|
|
12
10
|
// src/components/Editor.tsx
|
|
13
11
|
|
|
@@ -3413,12 +3411,30 @@ var Bookmark = Node$1.create({
|
|
|
3413
3411
|
return ReactNodeViewRenderer(BookmarkNode);
|
|
3414
3412
|
}
|
|
3415
3413
|
});
|
|
3416
|
-
|
|
3414
|
+
var katexModule = null;
|
|
3415
|
+
var katexLoadError = null;
|
|
3416
|
+
async function loadKatex() {
|
|
3417
|
+
if (katexModule) return katexModule;
|
|
3418
|
+
if (katexLoadError) return null;
|
|
3419
|
+
try {
|
|
3420
|
+
katexModule = await import('katex');
|
|
3421
|
+
return katexModule;
|
|
3422
|
+
} catch (err) {
|
|
3423
|
+
katexLoadError = "KaTeX library is not installed. Please run: npm install katex";
|
|
3424
|
+
console.warn("[zm-editor] KaTeX not available:", katexLoadError);
|
|
3425
|
+
return null;
|
|
3426
|
+
}
|
|
3427
|
+
}
|
|
3428
|
+
async function renderLatexAsync(latex, displayMode) {
|
|
3417
3429
|
if (!latex.trim()) {
|
|
3418
3430
|
return { html: "", error: null };
|
|
3419
3431
|
}
|
|
3432
|
+
const katex = await loadKatex();
|
|
3433
|
+
if (!katex) {
|
|
3434
|
+
return { html: "", error: katexLoadError || "KaTeX library not available" };
|
|
3435
|
+
}
|
|
3420
3436
|
try {
|
|
3421
|
-
const html = katex.renderToString(latex, {
|
|
3437
|
+
const html = katex.default.renderToString(latex, {
|
|
3422
3438
|
displayMode,
|
|
3423
3439
|
throwOnError: true,
|
|
3424
3440
|
strict: false,
|
|
@@ -3436,19 +3452,35 @@ function MathNode({ node, updateAttributes, selected }) {
|
|
|
3436
3452
|
const { latex = "", displayMode = true } = node.attrs;
|
|
3437
3453
|
const [isEditing, setIsEditing] = useState(false);
|
|
3438
3454
|
const [latexValue, setLatexValue] = useState(latex);
|
|
3455
|
+
const [renderedHtml, setRenderedHtml] = useState("");
|
|
3456
|
+
const [renderError, setRenderError] = useState(null);
|
|
3457
|
+
const [isKatexAvailable, setIsKatexAvailable] = useState(null);
|
|
3458
|
+
const textareaRef = useRef(null);
|
|
3459
|
+
useEffect(() => {
|
|
3460
|
+
loadKatex().then((k) => setIsKatexAvailable(k !== null));
|
|
3461
|
+
}, []);
|
|
3439
3462
|
useEffect(() => {
|
|
3440
3463
|
if (!latex) {
|
|
3441
3464
|
setIsEditing(true);
|
|
3442
3465
|
}
|
|
3443
3466
|
}, []);
|
|
3444
|
-
const textareaRef = useRef(null);
|
|
3445
|
-
const rendered = useMemo(() => renderLatex(latexValue, displayMode), [latexValue, displayMode]);
|
|
3446
3467
|
useEffect(() => {
|
|
3447
3468
|
setLatexValue(latex);
|
|
3448
3469
|
if (latex) {
|
|
3449
3470
|
setIsEditing(false);
|
|
3450
3471
|
}
|
|
3451
3472
|
}, [latex]);
|
|
3473
|
+
useEffect(() => {
|
|
3474
|
+
if (!latexValue.trim()) {
|
|
3475
|
+
setRenderedHtml("");
|
|
3476
|
+
setRenderError(null);
|
|
3477
|
+
return;
|
|
3478
|
+
}
|
|
3479
|
+
renderLatexAsync(latexValue, displayMode).then((result) => {
|
|
3480
|
+
setRenderedHtml(result.html);
|
|
3481
|
+
setRenderError(result.error);
|
|
3482
|
+
});
|
|
3483
|
+
}, [latexValue, displayMode]);
|
|
3452
3484
|
const handleSave = useCallback(() => {
|
|
3453
3485
|
const trimmed = latexValue.trim();
|
|
3454
3486
|
if (!trimmed) {
|
|
@@ -3490,6 +3522,14 @@ function MathNode({ node, updateAttributes, selected }) {
|
|
|
3490
3522
|
useEffect(() => {
|
|
3491
3523
|
adjustTextareaHeight();
|
|
3492
3524
|
}, [latexValue, adjustTextareaHeight]);
|
|
3525
|
+
if (isKatexAvailable === false) {
|
|
3526
|
+
return /* @__PURE__ */ jsx(NodeViewWrapper, { className: "zm-math-node-wrapper", children: /* @__PURE__ */ jsx("div", { className: `zm-math-node zm-math-unavailable ${selected ? "is-selected" : ""}`, children: /* @__PURE__ */ jsxs("div", { className: "zm-math-unavailable-content", children: [
|
|
3527
|
+
/* @__PURE__ */ jsx(MathIcon, {}),
|
|
3528
|
+
/* @__PURE__ */ jsx("div", { className: "zm-math-unavailable-title", children: "Math Equations" }),
|
|
3529
|
+
/* @__PURE__ */ jsx("div", { className: "zm-math-unavailable-message", children: "To use math equations, please install the KaTeX package:" }),
|
|
3530
|
+
/* @__PURE__ */ jsx("code", { className: "zm-math-unavailable-code", children: "npm install katex" })
|
|
3531
|
+
] }) }) });
|
|
3532
|
+
}
|
|
3493
3533
|
if (isEditing || !latex) {
|
|
3494
3534
|
return /* @__PURE__ */ jsx(NodeViewWrapper, { className: "zm-math-node-wrapper", children: /* @__PURE__ */ jsx(
|
|
3495
3535
|
"div",
|
|
@@ -3517,19 +3557,18 @@ function MathNode({ node, updateAttributes, selected }) {
|
|
|
3517
3557
|
spellCheck: false
|
|
3518
3558
|
}
|
|
3519
3559
|
),
|
|
3520
|
-
latexValue.trim() && /* @__PURE__ */ jsx("div", { className: "zm-math-preview", children:
|
|
3560
|
+
latexValue.trim() && /* @__PURE__ */ jsx("div", { className: "zm-math-preview", children: renderError ? /* @__PURE__ */ jsx("div", { className: "zm-math-error", children: renderError }) : renderedHtml ? /* @__PURE__ */ jsx(
|
|
3521
3561
|
"div",
|
|
3522
3562
|
{
|
|
3523
3563
|
className: "zm-math-rendered",
|
|
3524
|
-
dangerouslySetInnerHTML: { __html:
|
|
3564
|
+
dangerouslySetInnerHTML: { __html: renderedHtml }
|
|
3525
3565
|
}
|
|
3526
|
-
) }),
|
|
3566
|
+
) : null }),
|
|
3527
3567
|
/* @__PURE__ */ jsx("div", { className: "zm-math-hint", children: locale.nodes.math.hint })
|
|
3528
3568
|
] })
|
|
3529
3569
|
}
|
|
3530
3570
|
) });
|
|
3531
3571
|
}
|
|
3532
|
-
const finalRendered = renderLatex(latex, displayMode);
|
|
3533
3572
|
return /* @__PURE__ */ jsxs(NodeViewWrapper, { className: "zm-math-node-wrapper", children: [
|
|
3534
3573
|
/* @__PURE__ */ jsx(
|
|
3535
3574
|
"div",
|
|
@@ -3537,17 +3576,17 @@ function MathNode({ node, updateAttributes, selected }) {
|
|
|
3537
3576
|
className: `zm-math-node zm-math-display ${selected ? "is-selected" : ""}`,
|
|
3538
3577
|
"data-drag-handle": true,
|
|
3539
3578
|
onClick: handleEdit,
|
|
3540
|
-
children:
|
|
3579
|
+
children: renderError ? /* @__PURE__ */ jsxs("div", { className: "zm-math-error-display", children: [
|
|
3541
3580
|
/* @__PURE__ */ jsx("div", { className: "zm-math-error-icon", children: /* @__PURE__ */ jsx(ErrorIcon, {}) }),
|
|
3542
|
-
/* @__PURE__ */ jsx("div", { className: "zm-math-error-message", children:
|
|
3581
|
+
/* @__PURE__ */ jsx("div", { className: "zm-math-error-message", children: renderError }),
|
|
3543
3582
|
/* @__PURE__ */ jsx("div", { className: "zm-math-error-source", children: latex })
|
|
3544
|
-
] }) : /* @__PURE__ */ jsx(
|
|
3583
|
+
] }) : renderedHtml ? /* @__PURE__ */ jsx(
|
|
3545
3584
|
"div",
|
|
3546
3585
|
{
|
|
3547
3586
|
className: "zm-math-rendered",
|
|
3548
|
-
dangerouslySetInnerHTML: { __html:
|
|
3587
|
+
dangerouslySetInnerHTML: { __html: renderedHtml }
|
|
3549
3588
|
}
|
|
3550
|
-
)
|
|
3589
|
+
) : /* @__PURE__ */ jsx("div", { className: "zm-math-loading", children: "Loading..." })
|
|
3551
3590
|
}
|
|
3552
3591
|
),
|
|
3553
3592
|
selected && /* @__PURE__ */ jsx("div", { className: "zm-math-toolbar", children: /* @__PURE__ */ jsx(
|
|
@@ -4401,7 +4440,7 @@ function TerminalNode({ node, updateAttributes, selected }) {
|
|
|
4401
4440
|
[updateAttributes]
|
|
4402
4441
|
);
|
|
4403
4442
|
const handleOutputInput = useCallback((e) => {
|
|
4404
|
-
const textarea = e.
|
|
4443
|
+
const textarea = e.currentTarget;
|
|
4405
4444
|
textarea.style.height = "auto";
|
|
4406
4445
|
textarea.style.height = `${textarea.scrollHeight}px`;
|
|
4407
4446
|
}, []);
|
|
@@ -4879,8 +4918,22 @@ var ApiBlock = Node$1.create({
|
|
|
4879
4918
|
return ReactNodeViewRenderer(ApiBlockNode);
|
|
4880
4919
|
}
|
|
4881
4920
|
});
|
|
4921
|
+
var mermaidModule = null;
|
|
4922
|
+
var mermaidLoadError = null;
|
|
4882
4923
|
var mermaidInitialized = false;
|
|
4883
|
-
function
|
|
4924
|
+
async function loadMermaid() {
|
|
4925
|
+
if (mermaidModule) return mermaidModule;
|
|
4926
|
+
if (mermaidLoadError) return null;
|
|
4927
|
+
try {
|
|
4928
|
+
mermaidModule = await import('mermaid');
|
|
4929
|
+
return mermaidModule;
|
|
4930
|
+
} catch (err) {
|
|
4931
|
+
mermaidLoadError = "Mermaid library is not installed. Please run: npm install mermaid";
|
|
4932
|
+
console.warn("[zm-editor] Mermaid not available:", mermaidLoadError);
|
|
4933
|
+
return null;
|
|
4934
|
+
}
|
|
4935
|
+
}
|
|
4936
|
+
function initializeMermaid(mermaid) {
|
|
4884
4937
|
if (mermaidInitialized) return;
|
|
4885
4938
|
mermaid.initialize({
|
|
4886
4939
|
startOnLoad: false,
|
|
@@ -4894,9 +4947,13 @@ async function renderMermaid(code, id) {
|
|
|
4894
4947
|
if (!code.trim()) {
|
|
4895
4948
|
return { svg: "", error: null };
|
|
4896
4949
|
}
|
|
4897
|
-
|
|
4950
|
+
const mermaid = await loadMermaid();
|
|
4951
|
+
if (!mermaid) {
|
|
4952
|
+
return { svg: "", error: mermaidLoadError || "Mermaid library not available" };
|
|
4953
|
+
}
|
|
4954
|
+
initializeMermaid(mermaid.default);
|
|
4898
4955
|
try {
|
|
4899
|
-
const { svg } = await mermaid.render(id, code);
|
|
4956
|
+
const { svg } = await mermaid.default.render(id, code);
|
|
4900
4957
|
return { svg, error: null };
|
|
4901
4958
|
} catch (err) {
|
|
4902
4959
|
cleanupOrphanMermaidElements(id);
|
|
@@ -4927,8 +4984,12 @@ function MermaidNode({ node, updateAttributes, selected }) {
|
|
|
4927
4984
|
const [renderedSvg, setRenderedSvg] = useState("");
|
|
4928
4985
|
const [renderError, setRenderError] = useState(null);
|
|
4929
4986
|
const [isRendering, setIsRendering] = useState(false);
|
|
4987
|
+
const [isMermaidAvailable, setIsMermaidAvailable] = useState(null);
|
|
4930
4988
|
const textareaRef = useRef(null);
|
|
4931
4989
|
const renderIdRef = useRef(0);
|
|
4990
|
+
useEffect(() => {
|
|
4991
|
+
loadMermaid().then((m) => setIsMermaidAvailable(m !== null));
|
|
4992
|
+
}, []);
|
|
4932
4993
|
useEffect(() => {
|
|
4933
4994
|
if (!code) {
|
|
4934
4995
|
setIsEditing(true);
|
|
@@ -4996,6 +5057,14 @@ function MermaidNode({ node, updateAttributes, selected }) {
|
|
|
4996
5057
|
useEffect(() => {
|
|
4997
5058
|
adjustTextareaHeight();
|
|
4998
5059
|
}, [codeValue, adjustTextareaHeight]);
|
|
5060
|
+
if (isMermaidAvailable === false) {
|
|
5061
|
+
return /* @__PURE__ */ jsx(NodeViewWrapper, { className: "zm-mermaid-node-wrapper", children: /* @__PURE__ */ jsx("div", { className: `zm-mermaid-node zm-mermaid-unavailable ${selected ? "is-selected" : ""}`, children: /* @__PURE__ */ jsxs("div", { className: "zm-mermaid-unavailable-content", children: [
|
|
5062
|
+
/* @__PURE__ */ jsx(MermaidIcon, {}),
|
|
5063
|
+
/* @__PURE__ */ jsx("div", { className: "zm-mermaid-unavailable-title", children: "Mermaid Diagrams" }),
|
|
5064
|
+
/* @__PURE__ */ jsx("div", { className: "zm-mermaid-unavailable-message", children: "To use Mermaid diagrams, please install the mermaid package:" }),
|
|
5065
|
+
/* @__PURE__ */ jsx("code", { className: "zm-mermaid-unavailable-code", children: "npm install mermaid" })
|
|
5066
|
+
] }) }) });
|
|
5067
|
+
}
|
|
4999
5068
|
if (isEditing || !code) {
|
|
5000
5069
|
return /* @__PURE__ */ jsx(NodeViewWrapper, { className: "zm-mermaid-node-wrapper", children: /* @__PURE__ */ jsx(
|
|
5001
5070
|
"div",
|