@editora/core 1.0.0 → 1.0.2
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.md +9 -0
- package/dist/A11yCheckerPlugin.native-CZKpi3uF.mjs +475 -0
- package/dist/A11yCheckerPlugin.native-CZKpi3uF.mjs.map +1 -0
- package/dist/AnchorPlugin.native-7es9PVZ9.mjs +340 -0
- package/dist/AnchorPlugin.native-7es9PVZ9.mjs.map +1 -0
- package/dist/BackgroundColorPlugin.native-Dip5uqTg.mjs +449 -0
- package/dist/BackgroundColorPlugin.native-Dip5uqTg.mjs.map +1 -0
- package/dist/BlockquotePlugin.native-JFmOLsxN.mjs +48 -0
- package/dist/BlockquotePlugin.native-JFmOLsxN.mjs.map +1 -0
- package/dist/BoldPlugin.native-BAzzoqU5.mjs +45 -0
- package/dist/BoldPlugin.native-BAzzoqU5.mjs.map +1 -0
- package/dist/CapitalizationPlugin.native-DOMsh5R7.mjs +79 -0
- package/dist/CapitalizationPlugin.native-DOMsh5R7.mjs.map +1 -0
- package/dist/ChecklistPlugin.native-Dccs3nLe.mjs +153 -0
- package/dist/ChecklistPlugin.native-Dccs3nLe.mjs.map +1 -0
- package/dist/ClearFormattingPlugin.native-BZPDHswo.mjs +27 -0
- package/dist/ClearFormattingPlugin.native-BZPDHswo.mjs.map +1 -0
- package/dist/CodePlugin.native-DD9xFIid.mjs +1679 -0
- package/dist/CodePlugin.native-DD9xFIid.mjs.map +1 -0
- package/dist/CodeSamplePlugin.native-DMbEdO9j.mjs +326 -0
- package/dist/CodeSamplePlugin.native-DMbEdO9j.mjs.map +1 -0
- package/dist/CommentsPlugin.native-2zQV8Ia4.mjs +473 -0
- package/dist/CommentsPlugin.native-2zQV8Ia4.mjs.map +1 -0
- package/dist/DirectionPlugin.native-Be7wCzkI.mjs +59 -0
- package/dist/DirectionPlugin.native-Be7wCzkI.mjs.map +1 -0
- package/dist/DocumentManagerPlugin.native-BvZL5CSG.mjs +116 -0
- package/dist/DocumentManagerPlugin.native-BvZL5CSG.mjs.map +1 -0
- package/dist/EmbedIframePlugin.native-ifr9KLdN.mjs +461 -0
- package/dist/EmbedIframePlugin.native-ifr9KLdN.mjs.map +1 -0
- package/dist/EmojisPlugin.native-D6mJSnSR.mjs +1033 -0
- package/dist/EmojisPlugin.native-D6mJSnSR.mjs.map +1 -0
- package/dist/FontFamilyPlugin.native-BzS_9qbM.mjs +106 -0
- package/dist/FontFamilyPlugin.native-BzS_9qbM.mjs.map +1 -0
- package/dist/FontSizePlugin.native-DkLMLPue.mjs +186 -0
- package/dist/FontSizePlugin.native-DkLMLPue.mjs.map +1 -0
- package/dist/FootnotePlugin.native-BciVc9W6.mjs +128 -0
- package/dist/FootnotePlugin.native-BciVc9W6.mjs.map +1 -0
- package/dist/FullscreenPlugin.native-ChXyxeNw.mjs +77 -0
- package/dist/FullscreenPlugin.native-ChXyxeNw.mjs.map +1 -0
- package/dist/HeadingPlugin.native-DrLYwQnQ.mjs +64 -0
- package/dist/HeadingPlugin.native-DrLYwQnQ.mjs.map +1 -0
- package/dist/HistoryPlugin.native-DoDRifCf.mjs +89 -0
- package/dist/HistoryPlugin.native-DoDRifCf.mjs.map +1 -0
- package/dist/IndentPlugin.native-CbFugPoi.mjs +133 -0
- package/dist/IndentPlugin.native-CbFugPoi.mjs.map +1 -0
- package/dist/ItalicPlugin.native-CQjjDyUL.mjs +43 -0
- package/dist/ItalicPlugin.native-CQjjDyUL.mjs.map +1 -0
- package/dist/LineHeightPlugin.native-CWQT2FIa.mjs +73 -0
- package/dist/LineHeightPlugin.native-CWQT2FIa.mjs.map +1 -0
- package/dist/LinkPlugin.native-BdAOV-iu.mjs +206 -0
- package/dist/LinkPlugin.native-BdAOV-iu.mjs.map +1 -0
- package/dist/ListPlugin.native-CLFU5AUQ.mjs +59 -0
- package/dist/ListPlugin.native-CLFU5AUQ.mjs.map +1 -0
- package/dist/MathPlugin.native-DE_ii-LA.mjs +182 -0
- package/dist/MathPlugin.native-DE_ii-LA.mjs.map +1 -0
- package/dist/MediaManagerPlugin.native-DaYFDzNM.mjs +533 -0
- package/dist/MediaManagerPlugin.native-DaYFDzNM.mjs.map +1 -0
- package/dist/MergeTagPlugin.native-CrxyThyn.mjs +178 -0
- package/dist/MergeTagPlugin.native-CrxyThyn.mjs.map +1 -0
- package/dist/PageBreakPlugin.native-DDjcDyRW.mjs +172 -0
- package/dist/PageBreakPlugin.native-DDjcDyRW.mjs.map +1 -0
- package/dist/PreviewPlugin.native-DBvfpmIv.mjs +322 -0
- package/dist/PreviewPlugin.native-DBvfpmIv.mjs.map +1 -0
- package/dist/PrintPlugin.native-BUpm52VJ.mjs +311 -0
- package/dist/PrintPlugin.native-BUpm52VJ.mjs.map +1 -0
- package/dist/SpecialCharactersPlugin.native-x7a2SWXc.mjs +731 -0
- package/dist/SpecialCharactersPlugin.native-x7a2SWXc.mjs.map +1 -0
- package/dist/SpellCheckPlugin.native-B7yTh0iE.mjs +465 -0
- package/dist/SpellCheckPlugin.native-B7yTh0iE.mjs.map +1 -0
- package/dist/StrikethroughPlugin.native-ChaZLaXw.mjs +43 -0
- package/dist/StrikethroughPlugin.native-ChaZLaXw.mjs.map +1 -0
- package/dist/TablePlugin.native-EEWXn1-s.mjs +491 -0
- package/dist/TablePlugin.native-EEWXn1-s.mjs.map +1 -0
- package/dist/TemplatePlugin.native-BlSn1c9h.mjs +564 -0
- package/dist/TemplatePlugin.native-BlSn1c9h.mjs.map +1 -0
- package/dist/TextAlignmentPlugin.native-CQIs1m7R.mjs +97 -0
- package/dist/TextAlignmentPlugin.native-CQIs1m7R.mjs.map +1 -0
- package/dist/TextColorPlugin.native-D6SmTglm.mjs +432 -0
- package/dist/TextColorPlugin.native-D6SmTglm.mjs.map +1 -0
- package/dist/UnderlinePlugin.native-QpIcK4L2.mjs +35 -0
- package/dist/UnderlinePlugin.native-QpIcK4L2.mjs.map +1 -0
- package/dist/core.css +1 -0
- package/dist/documentManager-irzj9n3V.mjs +37627 -0
- package/dist/documentManager-irzj9n3V.mjs.map +1 -0
- package/dist/editorContainerHelpers-C7kdWnS0.mjs +27 -0
- package/dist/editorContainerHelpers-C7kdWnS0.mjs.map +1 -0
- package/dist/editora.min.js +519 -4
- package/dist/editora.min.js.map +1 -0
- package/dist/editora.umd.js +519 -4
- package/dist/editora.umd.js.map +1 -0
- package/dist/index-BF5RBhL9.js +4 -0
- package/dist/index-BF5RBhL9.js.map +1 -0
- package/dist/index-BPsf460l.mjs +1243 -0
- package/dist/index-BPsf460l.mjs.map +1 -0
- package/dist/index.cjs.js +517 -4
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.es-CuicffkQ.mjs +6665 -0
- package/dist/index.es-CuicffkQ.mjs.map +1 -0
- package/dist/index.esm.js +1403 -122
- package/dist/index.esm.js.map +1 -0
- package/dist/plugin-loader.js +55 -0
- package/dist/plugin-loader.js.map +1 -0
- package/dist/purify.es-CKpwg8Tk.mjs +471 -0
- package/dist/purify.es-CKpwg8Tk.mjs.map +1 -0
- package/dist/webcomponent-core.js +1243 -0
- package/dist/webcomponent-core.js.map +1 -0
- package/dist/webcomponent-core.min.css +1 -0
- package/dist/webcomponent-core.min.js +597 -0
- package/dist/webcomponent-core.min.js.map +1 -0
- package/dist/webcomponent.cjs.js +2 -0
- package/dist/webcomponent.cjs.js.map +1 -0
- package/dist/webcomponent.esm.js +6 -0
- package/dist/webcomponent.esm.js.map +1 -0
- package/dist/webcomponent.js +1286 -0
- package/dist/webcomponent.js.map +1 -0
- package/dist/webcomponent.min.css +1 -0
- package/dist/webcomponent.min.js +4076 -0
- package/dist/webcomponent.min.js.map +1 -0
- package/package.json +64 -6
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
let r = null, a = !1, i = null;
|
|
2
|
+
const v = (e) => {
|
|
3
|
+
if (!e) return null;
|
|
4
|
+
let t = e;
|
|
5
|
+
for (; t; ) {
|
|
6
|
+
if (t.hasAttribute("contenteditable") && t.getAttribute("contenteditable") === "true" || t.hasAttribute("data-editora-content"))
|
|
7
|
+
return t;
|
|
8
|
+
t = t.parentElement;
|
|
9
|
+
}
|
|
10
|
+
return null;
|
|
11
|
+
}, w = (e) => {
|
|
12
|
+
if (!r) {
|
|
13
|
+
console.warn("No selection range stored");
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const t = r.startContainer, n = t.nodeType === Node.TEXT_NODE ? t.parentElement : t, s = v(n);
|
|
17
|
+
if (s) {
|
|
18
|
+
if (a && i) {
|
|
19
|
+
i.href = e.url, i.textContent = e.text, i.target = e.target, e.target === "_blank" ? i.setAttribute("rel", "noopener noreferrer") : i.removeAttribute("rel"), e.title ? i.title = e.title : i.removeAttribute("title");
|
|
20
|
+
const o = document.createRange();
|
|
21
|
+
o.selectNodeContents(i);
|
|
22
|
+
const l = window.getSelection();
|
|
23
|
+
l && (l.removeAllRanges(), l.addRange(o));
|
|
24
|
+
} else {
|
|
25
|
+
const o = document.createElement("a");
|
|
26
|
+
o.href = e.url, o.textContent = e.text, o.target = e.target, e.target === "_blank" && o.setAttribute("rel", "noopener noreferrer"), e.title && (o.title = e.title), r.deleteContents(), r.insertNode(o), r.setStartAfter(o), r.setEndAfter(o);
|
|
27
|
+
const l = window.getSelection();
|
|
28
|
+
l && (l.removeAllRanges(), l.addRange(r));
|
|
29
|
+
}
|
|
30
|
+
s.focus(), r = null, a = !1, i = null;
|
|
31
|
+
}
|
|
32
|
+
}, g = (e) => {
|
|
33
|
+
const t = document.createElement("div");
|
|
34
|
+
t.className = "link-dialog-overlay", t.style.cssText = `
|
|
35
|
+
position: fixed;
|
|
36
|
+
top: 0;
|
|
37
|
+
left: 0;
|
|
38
|
+
right: 0;
|
|
39
|
+
bottom: 0;
|
|
40
|
+
background: rgba(0, 0, 0, 0.5);
|
|
41
|
+
display: flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
justify-content: center;
|
|
44
|
+
z-index: 10000;
|
|
45
|
+
`;
|
|
46
|
+
const n = document.createElement("div");
|
|
47
|
+
n.className = "link-dialog", n.style.cssText = `
|
|
48
|
+
background: white;
|
|
49
|
+
border-radius: 8px;
|
|
50
|
+
width: 500px;
|
|
51
|
+
max-width: 90%;
|
|
52
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
|
53
|
+
`, n.innerHTML = `
|
|
54
|
+
<div class="link-dialog-header" style="padding: 16px 20px; border-bottom: 1px solid #ddd; display: flex; justify-content: space-between; align-items: center;">
|
|
55
|
+
<h3 style="margin: 0; font-size: 18px;">${e.isEditing ? "Edit Link" : "Insert Link"}</h3>
|
|
56
|
+
<button class="link-dialog-close" style="background: none; border: none; font-size: 24px; cursor: pointer; padding: 0; width: 30px; height: 30px;">×</button>
|
|
57
|
+
</div>
|
|
58
|
+
<form id="link-form">
|
|
59
|
+
<div class="link-dialog-body" style="padding: 20px;">
|
|
60
|
+
<div class="form-group" style="margin-bottom: 16px;">
|
|
61
|
+
<label for="link-text" style="display: block; margin-bottom: 6px; font-weight: 500;">Link Text:</label>
|
|
62
|
+
<input
|
|
63
|
+
id="link-text"
|
|
64
|
+
type="text"
|
|
65
|
+
value="${e.text || ""}"
|
|
66
|
+
placeholder="Enter link text"
|
|
67
|
+
style="width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; font-size: 14px;"
|
|
68
|
+
/>
|
|
69
|
+
</div>
|
|
70
|
+
<div class="form-group" style="margin-bottom: 16px;">
|
|
71
|
+
<label for="link-url" style="display: block; margin-bottom: 6px; font-weight: 500;">URL:</label>
|
|
72
|
+
<input
|
|
73
|
+
id="link-url"
|
|
74
|
+
type="url"
|
|
75
|
+
value="${e.url || ""}"
|
|
76
|
+
placeholder="https://example.com"
|
|
77
|
+
required
|
|
78
|
+
style="width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; font-size: 14px;"
|
|
79
|
+
/>
|
|
80
|
+
</div>
|
|
81
|
+
<div class="form-group" style="margin-bottom: 16px;">
|
|
82
|
+
<label for="link-title" style="display: block; margin-bottom: 6px; font-weight: 500;">Title (optional):</label>
|
|
83
|
+
<input
|
|
84
|
+
id="link-title"
|
|
85
|
+
type="text"
|
|
86
|
+
value="${e.title || ""}"
|
|
87
|
+
placeholder="Link tooltip text"
|
|
88
|
+
style="width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; font-size: 14px;"
|
|
89
|
+
/>
|
|
90
|
+
</div>
|
|
91
|
+
<div class="form-group" style="margin-bottom: 0;">
|
|
92
|
+
<label style="display: flex; align-items: center; cursor: pointer;">
|
|
93
|
+
<input
|
|
94
|
+
id="link-target"
|
|
95
|
+
type="checkbox"
|
|
96
|
+
${e.target === "_blank" ? "checked" : ""}
|
|
97
|
+
style="margin-right: 8px;"
|
|
98
|
+
/>
|
|
99
|
+
Open in new window/tab
|
|
100
|
+
</label>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
<div class="link-dialog-footer" style="padding: 12px 20px; border-top: 1px solid #ddd; display: flex; justify-content: flex-end; gap: 10px;">
|
|
104
|
+
<button type="button" class="btn-cancel" style="padding: 8px 16px; border: 1px solid #ccc; background: white; border-radius: 4px; cursor: pointer;">Cancel</button>
|
|
105
|
+
<button type="submit" class="btn-submit" style="padding: 8px 16px; border: none; background: #007bff; color: white; border-radius: 4px; cursor: pointer;">
|
|
106
|
+
${e.isEditing ? "Update Link" : "Insert Link"}
|
|
107
|
+
</button>
|
|
108
|
+
</div>
|
|
109
|
+
</form>
|
|
110
|
+
`, t.appendChild(n), document.body.appendChild(t);
|
|
111
|
+
const s = n.querySelector("#link-form"), o = n.querySelector("#link-text"), l = n.querySelector("#link-url"), x = n.querySelector("#link-title"), k = n.querySelector("#link-target"), y = n.querySelector(".link-dialog-close"), h = n.querySelector(".btn-cancel"), d = () => {
|
|
112
|
+
document.body.removeChild(t);
|
|
113
|
+
};
|
|
114
|
+
y.addEventListener("click", d), h.addEventListener("click", d), t.addEventListener("click", (c) => {
|
|
115
|
+
c.target === t && d();
|
|
116
|
+
}), s.addEventListener("submit", (c) => {
|
|
117
|
+
c.preventDefault();
|
|
118
|
+
const u = l.value.trim();
|
|
119
|
+
u && (w({
|
|
120
|
+
text: o.value.trim() || u,
|
|
121
|
+
url: u,
|
|
122
|
+
target: k.checked ? "_blank" : "_self",
|
|
123
|
+
title: x.value.trim() || void 0
|
|
124
|
+
}), d());
|
|
125
|
+
}), setTimeout(() => o.focus(), 100);
|
|
126
|
+
}, b = () => {
|
|
127
|
+
const e = window.getSelection();
|
|
128
|
+
if (!e || e.rangeCount === 0) return !1;
|
|
129
|
+
const t = e.getRangeAt(0).cloneRange();
|
|
130
|
+
r = t;
|
|
131
|
+
const n = e.toString() || "", s = t.startContainer, o = s.nodeType === Node.TEXT_NODE ? s.parentElement : s, l = o == null ? void 0 : o.closest("a");
|
|
132
|
+
return l ? (a = !0, i = l, g({
|
|
133
|
+
text: l.textContent || "",
|
|
134
|
+
url: l.href,
|
|
135
|
+
target: l.target || "_self",
|
|
136
|
+
title: l.title || "",
|
|
137
|
+
isEditing: !0
|
|
138
|
+
})) : (a = !1, i = null, g({
|
|
139
|
+
text: n,
|
|
140
|
+
url: "",
|
|
141
|
+
target: "_self",
|
|
142
|
+
isEditing: !1
|
|
143
|
+
})), !0;
|
|
144
|
+
}, m = () => (document.execCommand("unlink", !1), !0), p = (e, t) => {
|
|
145
|
+
var n;
|
|
146
|
+
typeof window != "undefined" && ((n = window.registerEditorCommand) == null || n.call(window, e, t));
|
|
147
|
+
}, f = () => {
|
|
148
|
+
p("openLinkDialog", b), p("removeLink", m), p("createLink", (e) => {
|
|
149
|
+
e && document.execCommand("createLink", !1, e);
|
|
150
|
+
});
|
|
151
|
+
};
|
|
152
|
+
typeof window != "undefined" && (document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", f) : f());
|
|
153
|
+
const L = () => ({
|
|
154
|
+
name: "link",
|
|
155
|
+
marks: {
|
|
156
|
+
link: {
|
|
157
|
+
attrs: {
|
|
158
|
+
href: {},
|
|
159
|
+
title: { default: null },
|
|
160
|
+
target: { default: null }
|
|
161
|
+
},
|
|
162
|
+
parseDOM: [
|
|
163
|
+
{
|
|
164
|
+
tag: "a[href]",
|
|
165
|
+
getAttrs: (e) => ({
|
|
166
|
+
href: e.getAttribute("href"),
|
|
167
|
+
title: e.getAttribute("title"),
|
|
168
|
+
target: e.getAttribute("target")
|
|
169
|
+
})
|
|
170
|
+
}
|
|
171
|
+
],
|
|
172
|
+
toDOM: (e) => [
|
|
173
|
+
"a",
|
|
174
|
+
{
|
|
175
|
+
href: e.attrs.href,
|
|
176
|
+
title: e.attrs.title,
|
|
177
|
+
target: e.attrs.target,
|
|
178
|
+
rel: e.attrs.target === "_blank" ? "noopener noreferrer" : null
|
|
179
|
+
},
|
|
180
|
+
0
|
|
181
|
+
]
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
toolbar: [
|
|
185
|
+
{
|
|
186
|
+
label: "Link",
|
|
187
|
+
command: "openLinkDialog",
|
|
188
|
+
type: "button",
|
|
189
|
+
icon: '<svg width="24" height="24" focusable="false"><path d="M6.2 12.3a1 1 0 0 1 1.4 1.4l-2 2a2 2 0 1 0 2.6 2.8l4.8-4.8a1 1 0 0 0 0-1.4 1 1 0 1 1 1.4-1.3 2.9 2.9 0 0 1 0 4L9.6 20a3.9 3.9 0 0 1-5.5-5.5l2-2Zm11.6-.6a1 1 0 0 1-1.4-1.4l2-2a2 2 0 1 0-2.6-2.8L11 10.3a1 1 0 0 0 0 1.4A1 1 0 1 1 9.6 13a2.9 2.9 0 0 1 0-4L14.4 4a3.9 3.9 0 0 1 5.5 5.5l-2 2Z" fill-rule="nonzero"></path></svg>',
|
|
190
|
+
shortcut: "Mod-k"
|
|
191
|
+
}
|
|
192
|
+
],
|
|
193
|
+
commands: {
|
|
194
|
+
openLinkDialog: b,
|
|
195
|
+
removeLink: m
|
|
196
|
+
},
|
|
197
|
+
keymap: {
|
|
198
|
+
"Mod-k": "openLinkDialog"
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
export {
|
|
202
|
+
L as LinkPlugin,
|
|
203
|
+
b as openLinkDialog,
|
|
204
|
+
m as removeLink
|
|
205
|
+
};
|
|
206
|
+
//# sourceMappingURL=LinkPlugin.native-BdAOV-iu.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LinkPlugin.native-BdAOV-iu.mjs","sources":["../../plugins/link/src/LinkPlugin.native.ts"],"sourcesContent":["import { Plugin } from '@editora/core';\n\n/**\n * Link Plugin - Native Implementation\n * Author: Ajay Kumar <ajaykr089@gmail.com>\n * \n * Provides hyperlink functionality with:\n * - Dialog-based link insertion/editing\n * - Link text, URL, title, and target options\n * - Edit existing links\n * - Smart link detection\n * - Security (rel=\"noopener noreferrer\" for _blank)\n */\n\ninterface LinkData {\n text: string;\n url: string;\n target: '_blank' | '_self';\n title?: string;\n}\n\nlet selectionRange: Range | null = null;\nlet isEditingLink = false;\nlet editingLinkElement: HTMLAnchorElement | null = null;\n\n/**\n * Find editor content element\n */\nconst findContentElement = (element: HTMLElement | null): HTMLElement | null => {\n if (!element) return null;\n \n let current: HTMLElement | null = element;\n while (current) {\n if (current.hasAttribute('contenteditable') && current.getAttribute('contenteditable') === 'true') {\n return current;\n }\n if (current.hasAttribute('data-editora-content')) {\n return current;\n }\n current = current.parentElement;\n }\n return null;\n};\n\n/**\n * Insert or update link\n */\nconst handleInsertLink = (linkData: LinkData): void => {\n if (!selectionRange) {\n console.warn('No selection range stored');\n return;\n }\n\n const rangeNode = selectionRange.startContainer;\n const element = rangeNode.nodeType === Node.TEXT_NODE \n ? rangeNode.parentElement \n : rangeNode as HTMLElement;\n\n const contentEl = findContentElement(element);\n if (!contentEl) return;\n\n if (isEditingLink && editingLinkElement) {\n // Edit existing link\n editingLinkElement.href = linkData.url;\n editingLinkElement.textContent = linkData.text;\n editingLinkElement.target = linkData.target;\n \n if (linkData.target === '_blank') {\n editingLinkElement.setAttribute('rel', 'noopener noreferrer');\n } else {\n editingLinkElement.removeAttribute('rel');\n }\n \n if (linkData.title) {\n editingLinkElement.title = linkData.title;\n } else {\n editingLinkElement.removeAttribute('title');\n }\n\n // Select the edited link\n const range = document.createRange();\n range.selectNodeContents(editingLinkElement);\n const selection = window.getSelection();\n if (selection) {\n selection.removeAllRanges();\n selection.addRange(range);\n }\n } else {\n // Create new link\n const linkElement = document.createElement('a');\n linkElement.href = linkData.url;\n linkElement.textContent = linkData.text;\n linkElement.target = linkData.target;\n \n if (linkData.target === '_blank') {\n linkElement.setAttribute('rel', 'noopener noreferrer');\n }\n \n if (linkData.title) {\n linkElement.title = linkData.title;\n }\n\n // Insert the link\n selectionRange.deleteContents();\n selectionRange.insertNode(linkElement);\n\n // Move cursor after the link\n selectionRange.setStartAfter(linkElement);\n selectionRange.setEndAfter(linkElement);\n const selection = window.getSelection();\n if (selection) {\n selection.removeAllRanges();\n selection.addRange(selectionRange);\n }\n }\n\n // Focus back to editor\n contentEl.focus();\n\n // Reset state\n selectionRange = null;\n isEditingLink = false;\n editingLinkElement = null;\n};\n\n/**\n * Create and show link dialog\n */\nconst showLinkDialog = (initialData: Partial<LinkData> & { isEditing?: boolean }): void => {\n // Create overlay\n const overlay = document.createElement('div');\n overlay.className = 'link-dialog-overlay';\n overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n `;\n\n // Create dialog\n const dialog = document.createElement('div');\n dialog.className = 'link-dialog';\n dialog.style.cssText = `\n background: white;\n border-radius: 8px;\n width: 500px;\n max-width: 90%;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n `;\n\n // Dialog HTML\n dialog.innerHTML = `\n <div class=\"link-dialog-header\" style=\"padding: 16px 20px; border-bottom: 1px solid #ddd; display: flex; justify-content: space-between; align-items: center;\">\n <h3 style=\"margin: 0; font-size: 18px;\">${initialData.isEditing ? 'Edit Link' : 'Insert Link'}</h3>\n <button class=\"link-dialog-close\" style=\"background: none; border: none; font-size: 24px; cursor: pointer; padding: 0; width: 30px; height: 30px;\">×</button>\n </div>\n <form id=\"link-form\">\n <div class=\"link-dialog-body\" style=\"padding: 20px;\">\n <div class=\"form-group\" style=\"margin-bottom: 16px;\">\n <label for=\"link-text\" style=\"display: block; margin-bottom: 6px; font-weight: 500;\">Link Text:</label>\n <input\n id=\"link-text\"\n type=\"text\"\n value=\"${initialData.text || ''}\"\n placeholder=\"Enter link text\"\n style=\"width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; font-size: 14px;\"\n />\n </div>\n <div class=\"form-group\" style=\"margin-bottom: 16px;\">\n <label for=\"link-url\" style=\"display: block; margin-bottom: 6px; font-weight: 500;\">URL:</label>\n <input\n id=\"link-url\"\n type=\"url\"\n value=\"${initialData.url || ''}\"\n placeholder=\"https://example.com\"\n required\n style=\"width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; font-size: 14px;\"\n />\n </div>\n <div class=\"form-group\" style=\"margin-bottom: 16px;\">\n <label for=\"link-title\" style=\"display: block; margin-bottom: 6px; font-weight: 500;\">Title (optional):</label>\n <input\n id=\"link-title\"\n type=\"text\"\n value=\"${initialData.title || ''}\"\n placeholder=\"Link tooltip text\"\n style=\"width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; font-size: 14px;\"\n />\n </div>\n <div class=\"form-group\" style=\"margin-bottom: 0;\">\n <label style=\"display: flex; align-items: center; cursor: pointer;\">\n <input\n id=\"link-target\"\n type=\"checkbox\"\n ${initialData.target === '_blank' ? 'checked' : ''}\n style=\"margin-right: 8px;\"\n />\n Open in new window/tab\n </label>\n </div>\n </div>\n <div class=\"link-dialog-footer\" style=\"padding: 12px 20px; border-top: 1px solid #ddd; display: flex; justify-content: flex-end; gap: 10px;\">\n <button type=\"button\" class=\"btn-cancel\" style=\"padding: 8px 16px; border: 1px solid #ccc; background: white; border-radius: 4px; cursor: pointer;\">Cancel</button>\n <button type=\"submit\" class=\"btn-submit\" style=\"padding: 8px 16px; border: none; background: #007bff; color: white; border-radius: 4px; cursor: pointer;\">\n ${initialData.isEditing ? 'Update Link' : 'Insert Link'}\n </button>\n </div>\n </form>\n `;\n\n overlay.appendChild(dialog);\n document.body.appendChild(overlay);\n\n // Get form elements\n const form = dialog.querySelector('#link-form') as HTMLFormElement;\n const textInput = dialog.querySelector('#link-text') as HTMLInputElement;\n const urlInput = dialog.querySelector('#link-url') as HTMLInputElement;\n const titleInput = dialog.querySelector('#link-title') as HTMLInputElement;\n const targetCheckbox = dialog.querySelector('#link-target') as HTMLInputElement;\n const closeBtn = dialog.querySelector('.link-dialog-close') as HTMLButtonElement;\n const cancelBtn = dialog.querySelector('.btn-cancel') as HTMLButtonElement;\n\n // Close dialog function\n const closeDialog = () => {\n document.body.removeChild(overlay);\n };\n\n // Event listeners\n closeBtn.addEventListener('click', closeDialog);\n cancelBtn.addEventListener('click', closeDialog);\n overlay.addEventListener('click', (e) => {\n if (e.target === overlay) closeDialog();\n });\n\n form.addEventListener('submit', (e) => {\n e.preventDefault();\n const url = urlInput.value.trim();\n if (url) {\n handleInsertLink({\n text: textInput.value.trim() || url,\n url,\n target: targetCheckbox.checked ? '_blank' : '_self',\n title: titleInput.value.trim() || undefined\n });\n closeDialog();\n }\n });\n\n // Focus first input\n setTimeout(() => textInput.focus(), 100);\n};\n\n/**\n * Open link dialog\n */\nexport const openLinkDialog = (): boolean => {\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return false;\n\n const range = selection.getRangeAt(0).cloneRange();\n selectionRange = range;\n\n const selectedText = selection.toString() || '';\n\n // Check if selection is within a link\n const startContainer = range.startContainer;\n const startElement = startContainer.nodeType === Node.TEXT_NODE\n ? startContainer.parentElement\n : startContainer as HTMLElement;\n\n const linkElement = startElement?.closest('a') as HTMLAnchorElement;\n\n if (linkElement) {\n // Edit mode\n isEditingLink = true;\n editingLinkElement = linkElement;\n showLinkDialog({\n text: linkElement.textContent || '',\n url: linkElement.href,\n target: (linkElement.target as '_blank' | '_self') || '_self',\n title: linkElement.title || '',\n isEditing: true\n });\n } else {\n // Insert mode\n isEditingLink = false;\n editingLinkElement = null;\n showLinkDialog({\n text: selectedText,\n url: '',\n target: '_self',\n isEditing: false\n });\n }\n\n return true;\n};\n\n/**\n * Remove link from selection\n */\nexport const removeLink = (): boolean => {\n document.execCommand('unlink', false);\n return true;\n};\n\n/**\n * Register commands globally\n */\nconst registerCommand = (command: string, handler: (...args: any[]) => void): void => {\n if (typeof window !== 'undefined') {\n (window as any).registerEditorCommand?.(command, handler);\n }\n};\n\n/**\n * Initialize global command registration\n */\nconst initializeCommands = (): void => {\n registerCommand('openLinkDialog', openLinkDialog);\n registerCommand('removeLink', removeLink);\n registerCommand('createLink', (url?: string) => {\n if (url) document.execCommand('createLink', false, url);\n });\n};\n\n// Initialize on load\nif (typeof window !== 'undefined') {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', initializeCommands);\n } else {\n initializeCommands();\n }\n}\n\nexport const LinkPlugin = (): Plugin => ({\n name: 'link',\n\n marks: {\n link: {\n attrs: {\n href: {},\n title: { default: null },\n target: { default: null }\n },\n parseDOM: [\n {\n tag: 'a[href]',\n getAttrs: (dom: HTMLElement) => ({\n href: dom.getAttribute('href'),\n title: dom.getAttribute('title'),\n target: dom.getAttribute('target')\n })\n }\n ],\n toDOM: (mark: any) => [\n 'a',\n {\n href: mark.attrs.href,\n title: mark.attrs.title,\n target: mark.attrs.target,\n rel: mark.attrs.target === '_blank' ? 'noopener noreferrer' : null\n },\n 0\n ]\n }\n },\n\n toolbar: [\n {\n label: 'Link',\n command: 'openLinkDialog',\n type: 'button',\n icon: '<svg width=\"24\" height=\"24\" focusable=\"false\"><path d=\"M6.2 12.3a1 1 0 0 1 1.4 1.4l-2 2a2 2 0 1 0 2.6 2.8l4.8-4.8a1 1 0 0 0 0-1.4 1 1 0 1 1 1.4-1.3 2.9 2.9 0 0 1 0 4L9.6 20a3.9 3.9 0 0 1-5.5-5.5l2-2Zm11.6-.6a1 1 0 0 1-1.4-1.4l2-2a2 2 0 1 0-2.6-2.8L11 10.3a1 1 0 0 0 0 1.4A1 1 0 1 1 9.6 13a2.9 2.9 0 0 1 0-4L14.4 4a3.9 3.9 0 0 1 5.5 5.5l-2 2Z\" fill-rule=\"nonzero\"></path></svg>',\n shortcut: 'Mod-k'\n }\n ],\n\n commands: {\n openLinkDialog,\n removeLink\n },\n\n keymap: {\n 'Mod-k': 'openLinkDialog'\n }\n});\n"],"names":["selectionRange","isEditingLink","editingLinkElement","findContentElement","element","current","handleInsertLink","linkData","rangeNode","contentEl","range","selection","linkElement","showLinkDialog","initialData","overlay","dialog","form","textInput","urlInput","titleInput","targetCheckbox","closeBtn","cancelBtn","closeDialog","e","url","openLinkDialog","selectedText","startContainer","startElement","removeLink","registerCommand","command","handler","_a","initializeCommands","LinkPlugin","dom","mark"],"mappings":"AAqBA,IAAIA,IAA+B,MAC/BC,IAAgB,IAChBC,IAA+C;AAKnD,MAAMC,IAAqB,CAACC,MAAoD;AAC9E,MAAI,CAACA,EAAS,QAAO;AAErB,MAAIC,IAA8BD;AAClC,SAAOC,KAAS;AAId,QAHIA,EAAQ,aAAa,iBAAiB,KAAKA,EAAQ,aAAa,iBAAiB,MAAM,UAGvFA,EAAQ,aAAa,sBAAsB;AAC7C,aAAOA;AAET,IAAAA,IAAUA,EAAQ;AAAA,EACpB;AACA,SAAO;AACT,GAKMC,IAAmB,CAACC,MAA6B;AACrD,MAAI,CAACP,GAAgB;AACnB,YAAQ,KAAK,2BAA2B;AACxC;AAAA,EACF;AAEA,QAAMQ,IAAYR,EAAe,gBAC3BI,IAAUI,EAAU,aAAa,KAAK,YACxCA,EAAU,gBACVA,GAEEC,IAAYN,EAAmBC,CAAO;AAC5C,MAAKK,GAEL;AAAA,QAAIR,KAAiBC,GAAoB;AAEvC,MAAAA,EAAmB,OAAOK,EAAS,KACnCL,EAAmB,cAAcK,EAAS,MAC1CL,EAAmB,SAASK,EAAS,QAEjCA,EAAS,WAAW,WACtBL,EAAmB,aAAa,OAAO,qBAAqB,IAE5DA,EAAmB,gBAAgB,KAAK,GAGtCK,EAAS,QACXL,EAAmB,QAAQK,EAAS,QAEpCL,EAAmB,gBAAgB,OAAO;AAI5C,YAAMQ,IAAQ,SAAS,YAAA;AACvB,MAAAA,EAAM,mBAAmBR,CAAkB;AAC3C,YAAMS,IAAY,OAAO,aAAA;AACzB,MAAIA,MACFA,EAAU,gBAAA,GACVA,EAAU,SAASD,CAAK;AAAA,IAE5B,OAAO;AAEL,YAAME,IAAc,SAAS,cAAc,GAAG;AAC9C,MAAAA,EAAY,OAAOL,EAAS,KAC5BK,EAAY,cAAcL,EAAS,MACnCK,EAAY,SAASL,EAAS,QAE1BA,EAAS,WAAW,YACtBK,EAAY,aAAa,OAAO,qBAAqB,GAGnDL,EAAS,UACXK,EAAY,QAAQL,EAAS,QAI/BP,EAAe,eAAA,GACfA,EAAe,WAAWY,CAAW,GAGrCZ,EAAe,cAAcY,CAAW,GACxCZ,EAAe,YAAYY,CAAW;AACtC,YAAMD,IAAY,OAAO,aAAA;AACzB,MAAIA,MACFA,EAAU,gBAAA,GACVA,EAAU,SAASX,CAAc;AAAA,IAErC;AAGA,IAAAS,EAAU,MAAA,GAGVT,IAAiB,MACjBC,IAAgB,IAChBC,IAAqB;AAAA;AACvB,GAKMW,IAAiB,CAACC,MAAmE;AAEzF,QAAMC,IAAU,SAAS,cAAc,KAAK;AAC5C,EAAAA,EAAQ,YAAY,uBACpBA,EAAQ,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAcxB,QAAMC,IAAS,SAAS,cAAc,KAAK;AAC3C,EAAAA,EAAO,YAAY,eACnBA,EAAO,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KASvBA,EAAO,YAAY;AAAA;AAAA,gDAE2BF,EAAY,YAAY,cAAc,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAU9EA,EAAY,QAAQ,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAUtBA,EAAY,OAAO,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAWrBA,EAAY,SAAS,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAU5BA,EAAY,WAAW,WAAW,YAAY,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAUpDA,EAAY,YAAY,gBAAgB,aAAa;AAAA;AAAA;AAAA;AAAA,KAM/DC,EAAQ,YAAYC,CAAM,GAC1B,SAAS,KAAK,YAAYD,CAAO;AAGjC,QAAME,IAAOD,EAAO,cAAc,YAAY,GACxCE,IAAYF,EAAO,cAAc,YAAY,GAC7CG,IAAWH,EAAO,cAAc,WAAW,GAC3CI,IAAaJ,EAAO,cAAc,aAAa,GAC/CK,IAAiBL,EAAO,cAAc,cAAc,GACpDM,IAAWN,EAAO,cAAc,oBAAoB,GACpDO,IAAYP,EAAO,cAAc,aAAa,GAG9CQ,IAAc,MAAM;AACxB,aAAS,KAAK,YAAYT,CAAO;AAAA,EACnC;AAGA,EAAAO,EAAS,iBAAiB,SAASE,CAAW,GAC9CD,EAAU,iBAAiB,SAASC,CAAW,GAC/CT,EAAQ,iBAAiB,SAAS,CAACU,MAAM;AACvC,IAAIA,EAAE,WAAWV,KAASS,EAAA;AAAA,EAC5B,CAAC,GAEDP,EAAK,iBAAiB,UAAU,CAACQ,MAAM;AACrC,IAAAA,EAAE,eAAA;AACF,UAAMC,IAAMP,EAAS,MAAM,KAAA;AAC3B,IAAIO,MACFpB,EAAiB;AAAA,MACf,MAAMY,EAAU,MAAM,KAAA,KAAUQ;AAAA,MAChC,KAAAA;AAAA,MACA,QAAQL,EAAe,UAAU,WAAW;AAAA,MAC5C,OAAOD,EAAW,MAAM,UAAU;AAAA,IAAA,CACnC,GACDI,EAAA;AAAA,EAEJ,CAAC,GAGD,WAAW,MAAMN,EAAU,MAAA,GAAS,GAAG;AACzC,GAKaS,IAAiB,MAAe;AAC3C,QAAMhB,IAAY,OAAO,aAAA;AACzB,MAAI,CAACA,KAAaA,EAAU,eAAe,EAAG,QAAO;AAErD,QAAMD,IAAQC,EAAU,WAAW,CAAC,EAAE,WAAA;AACtC,EAAAX,IAAiBU;AAEjB,QAAMkB,IAAejB,EAAU,SAAA,KAAc,IAGvCkB,IAAiBnB,EAAM,gBACvBoB,IAAeD,EAAe,aAAa,KAAK,YAClDA,EAAe,gBACfA,GAEEjB,IAAckB,KAAA,gBAAAA,EAAc,QAAQ;AAE1C,SAAIlB,KAEFX,IAAgB,IAChBC,IAAqBU,GACrBC,EAAe;AAAA,IACb,MAAMD,EAAY,eAAe;AAAA,IACjC,KAAKA,EAAY;AAAA,IACjB,QAASA,EAAY,UAAiC;AAAA,IACtD,OAAOA,EAAY,SAAS;AAAA,IAC5B,WAAW;AAAA,EAAA,CACZ,MAGDX,IAAgB,IAChBC,IAAqB,MACrBW,EAAe;AAAA,IACb,MAAMe;AAAA,IACN,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,WAAW;AAAA,EAAA,CACZ,IAGI;AACT,GAKaG,IAAa,OACxB,SAAS,YAAY,UAAU,EAAK,GAC7B,KAMHC,IAAkB,CAACC,GAAiBC,MAA4C;AAtStF,MAAAC;AAuSE,EAAI,OAAO,UAAW,iBACnBA,IAAA,OAAe,0BAAf,QAAAA,EAAA,aAAuCF,GAASC;AAErD,GAKME,IAAqB,MAAY;AACrC,EAAAJ,EAAgB,kBAAkBL,CAAc,GAChDK,EAAgB,cAAcD,CAAU,GACxCC,EAAgB,cAAc,CAACN,MAAiB;AAC9C,IAAIA,KAAK,SAAS,YAAY,cAAc,IAAOA,CAAG;AAAA,EACxD,CAAC;AACH;AAGI,OAAO,UAAW,gBAChB,SAAS,eAAe,YAC1B,SAAS,iBAAiB,oBAAoBU,CAAkB,IAEhEA,EAAA;AAIG,MAAMC,IAAa,OAAe;AAAA,EACvC,MAAM;AAAA,EAEN,OAAO;AAAA,IACL,MAAM;AAAA,MACJ,OAAO;AAAA,QACL,MAAM,CAAA;AAAA,QACN,OAAO,EAAE,SAAS,KAAA;AAAA,QAClB,QAAQ,EAAE,SAAS,KAAA;AAAA,MAAK;AAAA,MAE1B,UAAU;AAAA,QACR;AAAA,UACE,KAAK;AAAA,UACL,UAAU,CAACC,OAAsB;AAAA,YAC/B,MAAMA,EAAI,aAAa,MAAM;AAAA,YAC7B,OAAOA,EAAI,aAAa,OAAO;AAAA,YAC/B,QAAQA,EAAI,aAAa,QAAQ;AAAA,UAAA;AAAA,QACnC;AAAA,MACF;AAAA,MAEF,OAAO,CAACC,MAAc;AAAA,QACpB;AAAA,QACA;AAAA,UACE,MAAMA,EAAK,MAAM;AAAA,UACjB,OAAOA,EAAK,MAAM;AAAA,UAClB,QAAQA,EAAK,MAAM;AAAA,UACnB,KAAKA,EAAK,MAAM,WAAW,WAAW,wBAAwB;AAAA,QAAA;AAAA,QAEhE;AAAA,MAAA;AAAA,IACF;AAAA,EACF;AAAA,EAGF,SAAS;AAAA,IACP;AAAA,MACE,OAAO;AAAA,MACP,SAAS;AAAA,MACT,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,IAAA;AAAA,EACZ;AAAA,EAGF,UAAU;AAAA,IACR,gBAAAZ;AAAA,IACA,YAAAI;AAAA,EAAA;AAAA,EAGF,QAAQ;AAAA,IACN,SAAS;AAAA,EAAA;AAEb;"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const l = () => (document.execCommand("insertUnorderedList", !1), !0), s = () => (document.execCommand("insertOrderedList", !1), !0), e = (d, i) => {
|
|
2
|
+
var t;
|
|
3
|
+
typeof window != "undefined" && ((t = window.registerEditorCommand) == null || t.call(window, d, i));
|
|
4
|
+
}, o = () => {
|
|
5
|
+
e("toggleBulletList", l), e("toggleOrderedList", s);
|
|
6
|
+
};
|
|
7
|
+
typeof window != "undefined" && (document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", o) : o());
|
|
8
|
+
const a = () => ({
|
|
9
|
+
name: "list",
|
|
10
|
+
nodes: {
|
|
11
|
+
bulletList: {
|
|
12
|
+
content: "listItem+",
|
|
13
|
+
group: "block",
|
|
14
|
+
parseDOM: [{ tag: "ul" }],
|
|
15
|
+
toDOM: () => ["ul", 0]
|
|
16
|
+
},
|
|
17
|
+
orderedList: {
|
|
18
|
+
content: "listItem+",
|
|
19
|
+
group: "block",
|
|
20
|
+
parseDOM: [{ tag: "ol" }],
|
|
21
|
+
toDOM: () => ["ol", 0]
|
|
22
|
+
},
|
|
23
|
+
listItem: {
|
|
24
|
+
content: "paragraph",
|
|
25
|
+
parseDOM: [{ tag: "li" }],
|
|
26
|
+
toDOM: () => ["li", 0]
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
toolbar: [
|
|
30
|
+
{
|
|
31
|
+
label: "Bullet List",
|
|
32
|
+
command: "toggleBulletList",
|
|
33
|
+
type: "button",
|
|
34
|
+
icon: '<svg width="24" height="24" focusable="false"><path d="M11 5h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2Zm0 6h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2Zm0 6h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2ZM4.5 6c0 .4.1.8.4 1 .3.4.7.5 1.1.5.4 0 .8-.1 1-.4.4-.3.5-.7.5-1.1 0-.4-.1-.8-.4-1-.3-.4-.7-.5-1.1-.5-.4 0-.8.1-1 .4-.4.3-.5.7-.5 1.1Zm0 6c0 .4.1.8.4 1 .3.4.7.5 1.1.5.4 0 .8-.1 1-.4.4-.3.5-.7.5-1.1 0-.4-.1-.8-.4-1-.3-.4-.7-.5-1.1-.5-.4 0-.8.1-1 .4-.4.3-.5.7-.5 1.1Zm0 6c0 .4.1.8.4 1 .3.4.7.5 1.1.5.4 0 .8-.1 1-.4.4-.3.5-.7.5-1.1 0-.4-.1-.8-.4-1-.3-.4-.7-.5-1.1-.5-.4 0-.8.1-1 .4-.4.3-.5.7-.5 1.1Z" fill-rule="evenodd"></path></svg>',
|
|
35
|
+
shortcut: "Mod-Shift-8"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
label: "Numbered List",
|
|
39
|
+
command: "toggleOrderedList",
|
|
40
|
+
type: "button",
|
|
41
|
+
icon: '<svg width="24" height="24" focusable="false"><path d="M10 17h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2Zm0-6h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2Zm0-6h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 1 1 0-2ZM6 4v3.5c0 .3-.2.5-.5.5a.5.5 0 0 1-.5-.5V5h-.5a.5.5 0 0 1 0-1H6Zm-1 8.8l.2.2h1.3c.3 0 .5.2.5.5s-.2.5-.5.5H4.9a1 1 0 0 1-.9-1V13c0-.4.3-.8.6-1l1.2-.4.2-.3a.2.2 0 0 0 0-.2l-.7.3a.5.5 0 0 1-.7-.3.5.5 0 0 1 .3-.6l.7-.4c.5-.2 1.1 0 1.4.4.3.5.3 1.1-.1 1.5l-1.2.7Zm0 3.7v.5c0 .3.2.5.5.5h1c.3 0 .5.2.5.5s-.2.5-.5.5h-1a1.5 1.5 0 0 1-1.5-1.5v-.5c0-.3.1-.6.3-.8l1.3-1.4c.3-.4.1-.9-.2-1-.1 0-.2 0-.3.2l-.4.5a.5.5 0 0 1-.7.1.5.5 0 0 1-.1-.7l.4-.5c.5-.5 1.2-.6 1.8-.4.6.3 1 .9 1 1.6 0 .4-.2.8-.5 1.1l-1.3 1.4-.3.4Z" fill-rule="evenodd"></path></svg>',
|
|
42
|
+
shortcut: "Mod-Shift-7"
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
commands: {
|
|
46
|
+
toggleBulletList: l,
|
|
47
|
+
toggleOrderedList: s
|
|
48
|
+
},
|
|
49
|
+
keymap: {
|
|
50
|
+
"Mod-Shift-8": "toggleBulletList",
|
|
51
|
+
"Mod-Shift-7": "toggleOrderedList"
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
export {
|
|
55
|
+
a as ListPlugin,
|
|
56
|
+
l as toggleBulletList,
|
|
57
|
+
s as toggleOrderedList
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=ListPlugin.native-CLFU5AUQ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListPlugin.native-CLFU5AUQ.mjs","sources":["../../plugins/list/src/ListPlugin.native.ts"],"sourcesContent":["import { Plugin } from '@editora/core';\n\n/**\n * List Plugin - Native Implementation\n * Author: Ajay Kumar <ajaykr089@gmail.com>\n * \n * Provides bullet and ordered list functionality with:\n * - Bullet lists (unordered lists with • markers)\n * - Numbered lists (ordered lists with 1, 2, 3... markers)\n * - Toggle on/off behavior\n * - Keyboard shortcuts (Cmd-Shift-8, Cmd-Shift-7)\n * - Global command registration\n */\n\n/**\n * Toggle bullet (unordered) list\n */\nexport const toggleBulletList = (): boolean => {\n document.execCommand('insertUnorderedList', false);\n return true;\n};\n\n/**\n * Toggle numbered (ordered) list\n */\nexport const toggleOrderedList = (): boolean => {\n document.execCommand('insertOrderedList', false);\n return true;\n};\n\n/**\n * Register commands globally\n */\nconst registerCommand = (command: string, handler: () => void): void => {\n if (typeof window !== 'undefined') {\n (window as any).registerEditorCommand?.(command, handler);\n }\n};\n\n/**\n * Initialize global command registration\n */\nconst initializeCommands = (): void => {\n registerCommand('toggleBulletList', toggleBulletList);\n registerCommand('toggleOrderedList', toggleOrderedList);\n};\n\n// Initialize on load\nif (typeof window !== 'undefined') {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', initializeCommands);\n } else {\n initializeCommands();\n }\n}\n\nexport const ListPlugin = (): Plugin => ({\n name: 'list',\n\n nodes: {\n bulletList: {\n content: 'listItem+',\n group: 'block',\n parseDOM: [{ tag: 'ul' }],\n toDOM: () => ['ul', 0]\n },\n orderedList: {\n content: 'listItem+',\n group: 'block',\n parseDOM: [{ tag: 'ol' }],\n toDOM: () => ['ol', 0]\n },\n listItem: {\n content: 'paragraph',\n parseDOM: [{ tag: 'li' }],\n toDOM: () => ['li', 0]\n }\n },\n\n toolbar: [\n {\n label: 'Bullet List',\n command: 'toggleBulletList',\n type: 'button',\n icon: '<svg width=\"24\" height=\"24\" focusable=\"false\"><path d=\"M11 5h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2Zm0 6h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2Zm0 6h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2ZM4.5 6c0 .4.1.8.4 1 .3.4.7.5 1.1.5.4 0 .8-.1 1-.4.4-.3.5-.7.5-1.1 0-.4-.1-.8-.4-1-.3-.4-.7-.5-1.1-.5-.4 0-.8.1-1 .4-.4.3-.5.7-.5 1.1Zm0 6c0 .4.1.8.4 1 .3.4.7.5 1.1.5.4 0 .8-.1 1-.4.4-.3.5-.7.5-1.1 0-.4-.1-.8-.4-1-.3-.4-.7-.5-1.1-.5-.4 0-.8.1-1 .4-.4.3-.5.7-.5 1.1Zm0 6c0 .4.1.8.4 1 .3.4.7.5 1.1.5.4 0 .8-.1 1-.4.4-.3.5-.7.5-1.1 0-.4-.1-.8-.4-1-.3-.4-.7-.5-1.1-.5-.4 0-.8.1-1 .4-.4.3-.5.7-.5 1.1Z\" fill-rule=\"evenodd\"></path></svg>',\n shortcut: 'Mod-Shift-8'\n },\n {\n label: 'Numbered List',\n command: 'toggleOrderedList',\n type: 'button',\n icon: '<svg width=\"24\" height=\"24\" focusable=\"false\"><path d=\"M10 17h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2Zm0-6h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 0 1 0-2Zm0-6h8c.6 0 1 .4 1 1s-.4 1-1 1h-8a1 1 0 1 1 0-2ZM6 4v3.5c0 .3-.2.5-.5.5a.5.5 0 0 1-.5-.5V5h-.5a.5.5 0 0 1 0-1H6Zm-1 8.8l.2.2h1.3c.3 0 .5.2.5.5s-.2.5-.5.5H4.9a1 1 0 0 1-.9-1V13c0-.4.3-.8.6-1l1.2-.4.2-.3a.2.2 0 0 0 0-.2l-.7.3a.5.5 0 0 1-.7-.3.5.5 0 0 1 .3-.6l.7-.4c.5-.2 1.1 0 1.4.4.3.5.3 1.1-.1 1.5l-1.2.7Zm0 3.7v.5c0 .3.2.5.5.5h1c.3 0 .5.2.5.5s-.2.5-.5.5h-1a1.5 1.5 0 0 1-1.5-1.5v-.5c0-.3.1-.6.3-.8l1.3-1.4c.3-.4.1-.9-.2-1-.1 0-.2 0-.3.2l-.4.5a.5.5 0 0 1-.7.1.5.5 0 0 1-.1-.7l.4-.5c.5-.5 1.2-.6 1.8-.4.6.3 1 .9 1 1.6 0 .4-.2.8-.5 1.1l-1.3 1.4-.3.4Z\" fill-rule=\"evenodd\"></path></svg>',\n shortcut: 'Mod-Shift-7'\n }\n ],\n\n commands: {\n toggleBulletList,\n toggleOrderedList\n },\n\n keymap: {\n 'Mod-Shift-8': 'toggleBulletList',\n 'Mod-Shift-7': 'toggleOrderedList'\n }\n});\n"],"names":["toggleBulletList","toggleOrderedList","registerCommand","command","handler","_a","initializeCommands","ListPlugin"],"mappings":"AAiBO,MAAMA,IAAmB,OAC9B,SAAS,YAAY,uBAAuB,EAAK,GAC1C,KAMIC,IAAoB,OAC/B,SAAS,YAAY,qBAAqB,EAAK,GACxC,KAMHC,IAAkB,CAACC,GAAiBC,MAA8B;AAhBjE,MAAAC;AAiBL,EAAI,OAAO,UAAW,iBACnBA,IAAA,OAAe,0BAAf,QAAAA,EAAA,aAAuCF,GAASC;AAErD,GAKME,IAAqB,MAAY;AACrC,EAAAJ,EAAgB,oBAAoBF,CAAgB,GACpDE,EAAgB,qBAAqBD,CAAiB;AACxD;AAGI,OAAO,UAAW,gBAChB,SAAS,eAAe,YAC1B,SAAS,iBAAiB,oBAAoBK,CAAkB,IAEhEA,EAAA;AAIG,MAAMC,IAAa,OAAe;AAAA,EACvC,MAAM;AAAA,EAEN,OAAO;AAAA,IACL,YAAY;AAAA,MACV,SAAS;AAAA,MACT,OAAO;AAAA,MACP,UAAU,CAAC,EAAE,KAAK,MAAM;AAAA,MACxB,OAAO,MAAM,CAAC,MAAM,CAAC;AAAA,IAAA;AAAA,IAEvB,aAAa;AAAA,MACX,SAAS;AAAA,MACT,OAAO;AAAA,MACP,UAAU,CAAC,EAAE,KAAK,MAAM;AAAA,MACxB,OAAO,MAAM,CAAC,MAAM,CAAC;AAAA,IAAA;AAAA,IAEvB,UAAU;AAAA,MACR,SAAS;AAAA,MACT,UAAU,CAAC,EAAE,KAAK,MAAM;AAAA,MACxB,OAAO,MAAM,CAAC,MAAM,CAAC;AAAA,IAAA;AAAA,EACvB;AAAA,EAGF,SAAS;AAAA,IACP;AAAA,MACE,OAAO;AAAA,MACP,SAAS;AAAA,MACT,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,IAAA;AAAA,IAEZ;AAAA,MACE,OAAO;AAAA,MACP,SAAS;AAAA,MACT,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,IAAA;AAAA,EACZ;AAAA,EAGF,UAAU;AAAA,IACR,kBAAAP;AAAA,IACA,mBAAAC;AAAA,EAAA;AAAA,EAGF,QAAQ;AAAA,IACN,eAAe;AAAA,IACf,eAAe;AAAA,EAAA;AAEnB;"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
const T = {
|
|
2
|
+
latex: [
|
|
3
|
+
{ name: "Fraction", formula: "\\frac{a}{b}", description: "Simple fraction" },
|
|
4
|
+
{ name: "Square Root", formula: "\\sqrt{x}", description: "Square root" },
|
|
5
|
+
{ name: "Power", formula: "x^{2}", description: "Exponent/power" },
|
|
6
|
+
{ name: "Subscript", formula: "x_{sub}", description: "Subscript" },
|
|
7
|
+
{ name: "Integral", formula: "\\int_{a}^{b} f(x) \\, dx", description: "Definite integral" },
|
|
8
|
+
{ name: "Summation", formula: "\\sum_{i=1}^{n} x_{i}", description: "Summation" },
|
|
9
|
+
{ name: "Limit", formula: "\\lim_{x \\to 0} f(x)", description: "Limit" },
|
|
10
|
+
{ name: "Derivative", formula: "\\frac{d}{dx} f(x)", description: "Derivative" },
|
|
11
|
+
{ name: "Matrix 2x2", formula: "\\begin{pmatrix} a & b \\\\ c & d \\end{pmatrix}", description: "2x2 matrix" },
|
|
12
|
+
{ name: "System", formula: "\\begin{cases} x + y = 1 \\\\ 2x - y = 0 \\end{cases}", description: "System of equations" }
|
|
13
|
+
],
|
|
14
|
+
mathml: [
|
|
15
|
+
{ name: "Fraction", formula: "<mfrac><mi>a</mi><mi>b</mi></mfrac>", description: "Simple fraction" },
|
|
16
|
+
{ name: "Square Root", formula: "<msqrt><mi>x</mi></msqrt>", description: "Square root" },
|
|
17
|
+
{ name: "Power", formula: "<msup><mi>x</mi><mn>2</mn></msup>", description: "Exponent/power" },
|
|
18
|
+
{ name: "Subscript", formula: "<msub><mi>x</mi><mi>sub</mi></msub>", description: "Subscript" },
|
|
19
|
+
{ name: "Parentheses", formula: '<mfenced open="(" close=")"><mi>a</mi><mo>+</mo><mi>b</mi></mfenced>', description: "Grouped expression" }
|
|
20
|
+
]
|
|
21
|
+
};
|
|
22
|
+
let u = null, h = null, w = !1;
|
|
23
|
+
const $ = () => new Promise((n, d) => {
|
|
24
|
+
if (window.katex) {
|
|
25
|
+
n(window.katex);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (w) {
|
|
29
|
+
const i = setInterval(() => {
|
|
30
|
+
window.katex && (clearInterval(i), n(window.katex));
|
|
31
|
+
}, 100);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
w = !0;
|
|
35
|
+
const r = document.createElement("link");
|
|
36
|
+
r.rel = "stylesheet", r.href = "https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css", document.head.appendChild(r);
|
|
37
|
+
const o = document.createElement("script");
|
|
38
|
+
o.src = "https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js", o.onload = () => n(window.katex), o.onerror = d, document.head.appendChild(o);
|
|
39
|
+
}), k = async (n) => {
|
|
40
|
+
const d = window.getSelection();
|
|
41
|
+
d && d.rangeCount > 0 && (u = d.getRangeAt(0).cloneRange()), await $();
|
|
42
|
+
const r = document.createElement("div");
|
|
43
|
+
r.style.cssText = "position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); display: flex; align-items: center; justify-content: center; z-index: 99999;";
|
|
44
|
+
const o = document.createElement("div");
|
|
45
|
+
o.style.cssText = "background: white; border-radius: 8px; width: 90%; max-width: 600px; max-height: 90vh; overflow: hidden; display: flex; flex-direction: column; box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);";
|
|
46
|
+
let i = (n == null ? void 0 : n.format) || "latex", s = (n == null ? void 0 : n.formula) || "", f = (n == null ? void 0 : n.inline) !== !1;
|
|
47
|
+
o.innerHTML = `
|
|
48
|
+
<div style="display: flex; justify-content: space-between; align-items: center; padding: 16px 20px; border-bottom: 1px solid #e1e5e9; background: #f8f9fa;">
|
|
49
|
+
<h2 style="margin: 0; font-size: 18px; font-weight: 600;">${n ? "Edit" : "Insert"} Math Formula</h2>
|
|
50
|
+
<button class="close-btn" style="background: none; border: none; font-size: 28px; cursor: pointer; color: #6c757d; padding: 0; width: 30px; height: 30px; line-height: 1;">×</button>
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
<div style="padding: 20px; overflow-y: auto; flex: 1;">
|
|
54
|
+
<div style="margin-bottom: 20px;">
|
|
55
|
+
<label style="display: block; font-weight: 600; margin-bottom: 8px; font-size: 14px;">Format:</label>
|
|
56
|
+
<div style="display: flex; gap: 16px;">
|
|
57
|
+
<label style="cursor: pointer;"><input type="radio" name="format" value="latex" ${i === "latex" ? "checked" : ""} style="margin-right: 6px;"> LaTeX</label>
|
|
58
|
+
<label style="cursor: pointer;"><input type="radio" name="format" value="mathml" ${i === "mathml" ? "checked" : ""} style="margin-right: 6px;"> MathML</label>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<div style="margin-bottom: 20px;">
|
|
63
|
+
<label style="display: block; font-weight: 600; margin-bottom: 8px; font-size: 14px;">Quick Templates:</label>
|
|
64
|
+
<div id="templates-grid" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; max-height: 200px; overflow-y: auto;"></div>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<div style="margin-bottom: 20px;">
|
|
68
|
+
<label style="cursor: pointer;"><input type="checkbox" id="inline-cb" ${f ? "checked" : ""} style="margin-right: 8px;"> Inline math</label>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<div style="margin-bottom: 20px;">
|
|
72
|
+
<label style="display: block; font-weight: 600; margin-bottom: 8px; font-size: 14px;">Formula:</label>
|
|
73
|
+
<textarea id="formula-input" rows="4" style="width: 100%; padding: 10px; border: 1px solid #ced4da; border-radius: 4px; font-family: 'Courier New', monospace; font-size: 14px;">${s}</textarea>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<div style="margin-bottom: 20px;">
|
|
77
|
+
<label style="display: block; font-weight: 600; margin-bottom: 8px; font-size: 14px;">Preview:</label>
|
|
78
|
+
<div id="preview-area" style="min-height: 60px; padding: 15px; border: 1px solid #dee2e6; border-radius: 4px; background: #f8f9fa; display: flex; align-items: center; justify-content: center; color: #6c757d;"></div>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
<div style="display: flex; justify-content: flex-end; gap: 10px; padding: 16px 20px; border-top: 1px solid #e1e5e9; background: #f8f9fa;">
|
|
83
|
+
<button class="cancel-btn" style="padding: 10px 20px; background: #fff; border: 1px solid #ced4da; border-radius: 4px; cursor: pointer; font-size: 14px;">Cancel</button>
|
|
84
|
+
<button id="insert-btn" style="padding: 10px 20px; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px;" disabled>${n ? "Update" : "Insert"}</button>
|
|
85
|
+
</div>
|
|
86
|
+
`, r.appendChild(o), document.body.appendChild(r);
|
|
87
|
+
const l = o.querySelector("#formula-input"), c = o.querySelector("#preview-area"), g = o.querySelector("#templates-grid"), M = o.querySelectorAll('input[name="format"]'), L = o.querySelector("#inline-cb"), x = o.querySelector("#insert-btn"), E = o.querySelector(".close-btn"), S = o.querySelector(".cancel-btn"), y = () => {
|
|
88
|
+
const e = T[i];
|
|
89
|
+
g.innerHTML = e.map((t) => `
|
|
90
|
+
<button type="button" data-formula="${t.formula.replace(/"/g, """)}" title="${t.description}" style="padding: 8px; border: 1px solid #ced4da; border-radius: 4px; background: #fff; cursor: pointer; text-align: left;">
|
|
91
|
+
<div style="font-weight: 600; font-size: 12px;">${t.name}</div>
|
|
92
|
+
<div style="font-size: 10px; color: #6c757d; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">${t.formula.substring(0, 20)}...</div>
|
|
93
|
+
</button>
|
|
94
|
+
`).join(""), g.querySelectorAll("button").forEach((t) => {
|
|
95
|
+
t.addEventListener("click", () => {
|
|
96
|
+
l.value = t.getAttribute("data-formula") || "", s = l.value, m();
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
}, m = () => {
|
|
100
|
+
const e = l.value.trim();
|
|
101
|
+
if (!e) {
|
|
102
|
+
c.innerHTML = '<span style="color: #6c757d;">Enter a formula to see preview</span>', x.disabled = !0;
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
x.disabled = !1;
|
|
106
|
+
try {
|
|
107
|
+
if (i === "latex") {
|
|
108
|
+
const t = window.katex;
|
|
109
|
+
c.innerHTML = t.renderToString(e, { displayMode: !1, throwOnError: !1 });
|
|
110
|
+
} else
|
|
111
|
+
e.trim().startsWith("<math") ? c.innerHTML = e : c.innerHTML = `<math xmlns="http://www.w3.org/1998/Math/MathML" display="inline">${e}</math>`;
|
|
112
|
+
} catch (t) {
|
|
113
|
+
c.innerHTML = '<span style="color: #cc0000;">Invalid formula</span>';
|
|
114
|
+
}
|
|
115
|
+
}, p = () => document.body.removeChild(r), v = () => {
|
|
116
|
+
const e = l.value.trim();
|
|
117
|
+
if (!e) return;
|
|
118
|
+
const t = { formula: e, format: i, inline: L.checked }, a = t.inline ? document.createElement("span") : document.createElement("div");
|
|
119
|
+
if (a.className = t.inline ? "math-formula" : "math-block", a.setAttribute("data-math-formula", e), a.setAttribute("data-math-format", i), a.contentEditable = "false", a.style.cssText = t.inline ? "background: #f0f8ff; border: 1px solid #b8daff; border-radius: 4px; padding: 2px 6px; margin: 0 2px; color: #004085; display: inline-block; cursor: pointer;" : "background: #f8f9fa; border: 1px solid #dee2e6; border-radius: 4px; padding: 12px; margin: 8px 0; text-align: center; display: block; cursor: pointer;", i === "latex") {
|
|
120
|
+
const b = window.katex;
|
|
121
|
+
try {
|
|
122
|
+
a.innerHTML = b.renderToString(e, {
|
|
123
|
+
displayMode: !t.inline,
|
|
124
|
+
throwOnError: !1
|
|
125
|
+
});
|
|
126
|
+
} catch (q) {
|
|
127
|
+
a.textContent = t.inline ? `$${e}$` : `$$${e}$$`;
|
|
128
|
+
}
|
|
129
|
+
} else if (e.trim().startsWith("<math"))
|
|
130
|
+
a.innerHTML = e;
|
|
131
|
+
else {
|
|
132
|
+
const b = `<math xmlns="http://www.w3.org/1998/Math/MathML" display="${t.inline ? "inline" : "block"}">${e}</math>`;
|
|
133
|
+
a.innerHTML = b;
|
|
134
|
+
}
|
|
135
|
+
h ? h.replaceWith(a) : u && (u.deleteContents(), u.insertNode(a)), p();
|
|
136
|
+
};
|
|
137
|
+
E.addEventListener("click", p), S.addEventListener("click", p), x.addEventListener("click", v), r.addEventListener("click", (e) => {
|
|
138
|
+
e.target === r && p();
|
|
139
|
+
}), M.forEach((e) => {
|
|
140
|
+
e.addEventListener("change", (t) => {
|
|
141
|
+
i = t.target.value, y(), m();
|
|
142
|
+
});
|
|
143
|
+
}), l.addEventListener("input", () => {
|
|
144
|
+
s = l.value, m();
|
|
145
|
+
}), l.addEventListener("keydown", (e) => {
|
|
146
|
+
(e.ctrlKey || e.metaKey) && e.key === "Enter" && (e.preventDefault(), v());
|
|
147
|
+
}), y(), m(), l.focus();
|
|
148
|
+
};
|
|
149
|
+
if (typeof window != "undefined" && !window.__mathPluginDoubleClickInitialized) {
|
|
150
|
+
window.__mathPluginDoubleClickInitialized = !0;
|
|
151
|
+
const n = (r) => {
|
|
152
|
+
const i = r.target.closest(".math-formula, .math-block");
|
|
153
|
+
if (i) {
|
|
154
|
+
r.preventDefault(), r.stopPropagation(), r.stopImmediatePropagation(), h = i;
|
|
155
|
+
const s = i.getAttribute("data-math-formula") || "", f = i.getAttribute("data-math-format") || "latex", l = i.classList.contains("math-formula");
|
|
156
|
+
k({ formula: s, format: f, inline: l });
|
|
157
|
+
}
|
|
158
|
+
}, d = () => {
|
|
159
|
+
document.addEventListener("dblclick", n, { capture: !0 });
|
|
160
|
+
};
|
|
161
|
+
document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", d) : setTimeout(d, 100);
|
|
162
|
+
}
|
|
163
|
+
const C = () => ({
|
|
164
|
+
name: "math",
|
|
165
|
+
toolbar: [
|
|
166
|
+
{
|
|
167
|
+
label: "Insert Math",
|
|
168
|
+
command: "insertMath",
|
|
169
|
+
icon: '<svg width="24" height="24" focusable="false"><path fill-rule="evenodd" clip-rule="evenodd" d="M9 4.8c.1-.5.5-.8 1-.8h10a1 1 0 1 1 0 2h-9.2L8.3 19.2a1 1 0 0 1-1.7.4l-3.4-4.2a1 1 0 0 1 1.6-1.2l2 2.5L9 4.8Zm9.7 5.5c.4.4.4 1 0 1.4L17 13.5l1.8 1.8a1 1 0 0 1-1.4 1.4L15.5 15l-1.8 1.8a1 1 0 0 1-1.4-1.4l1.8-1.8-1.8-1.8a1 1 0 0 1 1.4-1.4l1.8 1.8 1.8-1.8a1 1 0 0 1 1.4 0Z"></path></svg>'
|
|
170
|
+
}
|
|
171
|
+
],
|
|
172
|
+
commands: {
|
|
173
|
+
insertMath: () => (k(), !0)
|
|
174
|
+
},
|
|
175
|
+
keymap: {
|
|
176
|
+
"Mod-Shift-m": "insertMath"
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
export {
|
|
180
|
+
C as MathPlugin
|
|
181
|
+
};
|
|
182
|
+
//# sourceMappingURL=MathPlugin.native-DE_ii-LA.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MathPlugin.native-DE_ii-LA.mjs","sources":["../../plugins/math/src/MathPlugin.native.ts"],"sourcesContent":["import type { Plugin } from '@editora/core';\n\n/**\n * MathPlugin - Native implementation for mathematical equations\n * \n * Features:\n * - Math dialog with LaTeX/MathML templates\n * - Live KaTeX preview\n * - Double-click to edit formulas\n * - Inline/block math support\n */\n\nconst MATH_TEMPLATES = {\n latex: [\n { name: 'Fraction', formula: '\\\\frac{a}{b}', description: 'Simple fraction' },\n { name: 'Square Root', formula: '\\\\sqrt{x}', description: 'Square root' },\n { name: 'Power', formula: 'x^{2}', description: 'Exponent/power' },\n { name: 'Subscript', formula: 'x_{sub}', description: 'Subscript' },\n { name: 'Integral', formula: '\\\\int_{a}^{b} f(x) \\\\, dx', description: 'Definite integral' },\n { name: 'Summation', formula: '\\\\sum_{i=1}^{n} x_{i}', description: 'Summation' },\n { name: 'Limit', formula: '\\\\lim_{x \\\\to 0} f(x)', description: 'Limit' },\n { name: 'Derivative', formula: '\\\\frac{d}{dx} f(x)', description: 'Derivative' },\n { name: 'Matrix 2x2', formula: '\\\\begin{pmatrix} a & b \\\\\\\\ c & d \\\\end{pmatrix}', description: '2x2 matrix' },\n { name: 'System', formula: '\\\\begin{cases} x + y = 1 \\\\\\\\ 2x - y = 0 \\\\end{cases}', description: 'System of equations' },\n ],\n mathml: [\n { name: 'Fraction', formula: '<mfrac><mi>a</mi><mi>b</mi></mfrac>', description: 'Simple fraction' },\n { name: 'Square Root', formula: '<msqrt><mi>x</mi></msqrt>', description: 'Square root' },\n { name: 'Power', formula: '<msup><mi>x</mi><mn>2</mn></msup>', description: 'Exponent/power' },\n { name: 'Subscript', formula: '<msub><mi>x</mi><mi>sub</mi></msub>', description: 'Subscript' },\n { name: 'Parentheses', formula: '<mfenced open=\"(\" close=\")\"><mi>a</mi><mo>+</mo><mi>b</mi></mfenced>', description: 'Grouped expression' },\n ],\n};\n\nlet savedSelection: Range | null = null;\nlet editingMathElement: HTMLElement | null = null;\nlet katexLoaded = false;\n\n// Global flag to ensure listener is added only once across all instances\ndeclare global {\n interface Window {\n __mathPluginDoubleClickInitialized?: boolean;\n }\n}\n\nconst loadKaTeX = (): Promise<any> => {\n return new Promise((resolve, reject) => {\n if ((window as any).katex) {\n resolve((window as any).katex);\n return;\n }\n\n if (katexLoaded) {\n const checkInterval = setInterval(() => {\n if ((window as any).katex) {\n clearInterval(checkInterval);\n resolve((window as any).katex);\n }\n }, 100);\n return;\n }\n\n katexLoaded = true;\n\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = 'https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css';\n document.head.appendChild(link);\n\n const script = document.createElement('script');\n script.src = 'https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js';\n script.onload = () => resolve((window as any).katex);\n script.onerror = reject;\n document.head.appendChild(script);\n });\n};\n\nconst showMathDialog = async (initialData?: { formula: string; format: 'latex' | 'mathml'; inline: boolean }) => {\n const selection = window.getSelection();\n if (selection && selection.rangeCount > 0) {\n savedSelection = selection.getRangeAt(0).cloneRange();\n }\n\n await loadKaTeX();\n\n const overlay = document.createElement('div');\n overlay.style.cssText = 'position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); display: flex; align-items: center; justify-content: center; z-index: 99999;';\n\n const dialog = document.createElement('div');\n dialog.style.cssText = 'background: white; border-radius: 8px; width: 90%; max-width: 600px; max-height: 90vh; overflow: hidden; display: flex; flex-direction: column; box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);';\n\n let currentFormat: 'latex' | 'mathml' = initialData?.format || 'latex';\n let currentFormula = initialData?.formula || '';\n let currentInline = initialData?.inline !== false;\n\n dialog.innerHTML = `\n <div style=\"display: flex; justify-content: space-between; align-items: center; padding: 16px 20px; border-bottom: 1px solid #e1e5e9; background: #f8f9fa;\">\n <h2 style=\"margin: 0; font-size: 18px; font-weight: 600;\">${initialData ? 'Edit' : 'Insert'} Math Formula</h2>\n <button class=\"close-btn\" style=\"background: none; border: none; font-size: 28px; cursor: pointer; color: #6c757d; padding: 0; width: 30px; height: 30px; line-height: 1;\">×</button>\n </div>\n \n <div style=\"padding: 20px; overflow-y: auto; flex: 1;\">\n <div style=\"margin-bottom: 20px;\">\n <label style=\"display: block; font-weight: 600; margin-bottom: 8px; font-size: 14px;\">Format:</label>\n <div style=\"display: flex; gap: 16px;\">\n <label style=\"cursor: pointer;\"><input type=\"radio\" name=\"format\" value=\"latex\" ${currentFormat === 'latex' ? 'checked' : ''} style=\"margin-right: 6px;\"> LaTeX</label>\n <label style=\"cursor: pointer;\"><input type=\"radio\" name=\"format\" value=\"mathml\" ${currentFormat === 'mathml' ? 'checked' : ''} style=\"margin-right: 6px;\"> MathML</label>\n </div>\n </div>\n\n <div style=\"margin-bottom: 20px;\">\n <label style=\"display: block; font-weight: 600; margin-bottom: 8px; font-size: 14px;\">Quick Templates:</label>\n <div id=\"templates-grid\" style=\"display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; max-height: 200px; overflow-y: auto;\"></div>\n </div>\n\n <div style=\"margin-bottom: 20px;\">\n <label style=\"cursor: pointer;\"><input type=\"checkbox\" id=\"inline-cb\" ${currentInline ? 'checked' : ''} style=\"margin-right: 8px;\"> Inline math</label>\n </div>\n\n <div style=\"margin-bottom: 20px;\">\n <label style=\"display: block; font-weight: 600; margin-bottom: 8px; font-size: 14px;\">Formula:</label>\n <textarea id=\"formula-input\" rows=\"4\" style=\"width: 100%; padding: 10px; border: 1px solid #ced4da; border-radius: 4px; font-family: 'Courier New', monospace; font-size: 14px;\">${currentFormula}</textarea>\n </div>\n\n <div style=\"margin-bottom: 20px;\">\n <label style=\"display: block; font-weight: 600; margin-bottom: 8px; font-size: 14px;\">Preview:</label>\n <div id=\"preview-area\" style=\"min-height: 60px; padding: 15px; border: 1px solid #dee2e6; border-radius: 4px; background: #f8f9fa; display: flex; align-items: center; justify-content: center; color: #6c757d;\"></div>\n </div>\n </div>\n\n <div style=\"display: flex; justify-content: flex-end; gap: 10px; padding: 16px 20px; border-top: 1px solid #e1e5e9; background: #f8f9fa;\">\n <button class=\"cancel-btn\" style=\"padding: 10px 20px; background: #fff; border: 1px solid #ced4da; border-radius: 4px; cursor: pointer; font-size: 14px;\">Cancel</button>\n <button id=\"insert-btn\" style=\"padding: 10px 20px; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px;\" disabled>${initialData ? 'Update' : 'Insert'}</button>\n </div>\n `;\n\n overlay.appendChild(dialog);\n document.body.appendChild(overlay);\n\n const formulaInput = dialog.querySelector('#formula-input') as HTMLTextAreaElement;\n const previewArea = dialog.querySelector('#preview-area') as HTMLDivElement;\n const templatesGrid = dialog.querySelector('#templates-grid') as HTMLDivElement;\n const formatRadios = dialog.querySelectorAll('input[name=\"format\"]') as NodeListOf<HTMLInputElement>;\n const inlineCb = dialog.querySelector('#inline-cb') as HTMLInputElement;\n const insertBtn = dialog.querySelector('#insert-btn') as HTMLButtonElement;\n const closeBtn = dialog.querySelector('.close-btn') as HTMLButtonElement;\n const cancelBtn = dialog.querySelector('.cancel-btn') as HTMLButtonElement;\n\n const updateTemplates = () => {\n const templates = MATH_TEMPLATES[currentFormat];\n templatesGrid.innerHTML = templates.map(t => `\n <button type=\"button\" data-formula=\"${t.formula.replace(/\"/g, '"')}\" title=\"${t.description}\" style=\"padding: 8px; border: 1px solid #ced4da; border-radius: 4px; background: #fff; cursor: pointer; text-align: left;\">\n <div style=\"font-weight: 600; font-size: 12px;\">${t.name}</div>\n <div style=\"font-size: 10px; color: #6c757d; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\">${t.formula.substring(0, 20)}...</div>\n </button>\n `).join('');\n\n templatesGrid.querySelectorAll('button').forEach(btn => {\n btn.addEventListener('click', () => {\n formulaInput.value = btn.getAttribute('data-formula') || '';\n currentFormula = formulaInput.value;\n updatePreview();\n });\n });\n };\n\n const updatePreview = () => {\n const formula = formulaInput.value.trim();\n \n if (!formula) {\n previewArea.innerHTML = '<span style=\"color: #6c757d;\">Enter a formula to see preview</span>';\n insertBtn.disabled = true;\n return;\n }\n\n insertBtn.disabled = false;\n\n try {\n if (currentFormat === 'latex') {\n const katex = (window as any).katex;\n previewArea.innerHTML = katex.renderToString(formula, { displayMode: false, throwOnError: false });\n } else {\n // For MathML, check if it starts with <math>, if not, wrap it\n if (formula.trim().startsWith('<math')) {\n previewArea.innerHTML = formula;\n } else {\n // Wrap in <math> tag and render\n previewArea.innerHTML = `<math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"inline\">${formula}</math>`;\n }\n }\n } catch {\n previewArea.innerHTML = '<span style=\"color: #cc0000;\">Invalid formula</span>';\n }\n };\n\n const closeDialog = () => document.body.removeChild(overlay);\n\n const insertMath = () => {\n const formula = formulaInput.value.trim();\n if (!formula) return;\n\n const mathData = { formula, format: currentFormat, inline: inlineCb.checked };\n const mathEl = mathData.inline ? document.createElement('span') : document.createElement('div');\n \n mathEl.className = mathData.inline ? 'math-formula' : 'math-block';\n mathEl.setAttribute('data-math-formula', formula);\n mathEl.setAttribute('data-math-format', currentFormat);\n mathEl.contentEditable = 'false';\n mathEl.style.cssText = mathData.inline \n ? 'background: #f0f8ff; border: 1px solid #b8daff; border-radius: 4px; padding: 2px 6px; margin: 0 2px; color: #004085; display: inline-block; cursor: pointer;'\n : 'background: #f8f9fa; border: 1px solid #dee2e6; border-radius: 4px; padding: 12px; margin: 8px 0; text-align: center; display: block; cursor: pointer;';\n \n // Render with KaTeX for LaTeX formulas\n if (currentFormat === 'latex') {\n const katex = (window as any).katex;\n try {\n mathEl.innerHTML = katex.renderToString(formula, { \n displayMode: !mathData.inline, \n throwOnError: false \n });\n } catch {\n mathEl.textContent = mathData.inline ? `$${formula}$` : `$$${formula}$$`;\n }\n } else {\n // For MathML, wrap in <math> tag if not already wrapped\n if (formula.trim().startsWith('<math')) {\n mathEl.innerHTML = formula;\n } else {\n // Create proper MathML with namespace\n const mathContent = `<math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"${mathData.inline ? 'inline' : 'block'}\">${formula}</math>`;\n mathEl.innerHTML = mathContent;\n }\n }\n\n if (editingMathElement) {\n editingMathElement.replaceWith(mathEl);\n } else if (savedSelection) {\n savedSelection.deleteContents();\n savedSelection.insertNode(mathEl);\n }\n\n closeDialog();\n };\n\n closeBtn.addEventListener('click', closeDialog);\n cancelBtn.addEventListener('click', closeDialog);\n insertBtn.addEventListener('click', insertMath);\n overlay.addEventListener('click', (e) => { if (e.target === overlay) closeDialog(); });\n\n formatRadios.forEach(radio => {\n radio.addEventListener('change', (e) => {\n currentFormat = (e.target as HTMLInputElement).value as 'latex' | 'mathml';\n updateTemplates();\n updatePreview();\n });\n });\n\n formulaInput.addEventListener('input', () => {\n currentFormula = formulaInput.value;\n updatePreview();\n });\n\n formulaInput.addEventListener('keydown', (e) => {\n if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {\n e.preventDefault();\n insertMath();\n }\n });\n\n updateTemplates();\n updatePreview();\n formulaInput.focus();\n};\n\n// Initialize double-click editing (only once globally)\nif (typeof window !== 'undefined' && !window.__mathPluginDoubleClickInitialized) {\n window.__mathPluginDoubleClickInitialized = true;\n \n const handleMathDoubleClick = (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n const mathEl = target.closest('.math-formula, .math-block') as HTMLElement;\n \n if (mathEl) {\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation();\n \n editingMathElement = mathEl;\n const formula = mathEl.getAttribute('data-math-formula') || '';\n const format = (mathEl.getAttribute('data-math-format') || 'latex') as 'latex' | 'mathml';\n const inline = mathEl.classList.contains('math-formula');\n showMathDialog({ formula, format, inline });\n }\n };\n\n const initDoubleClick = () => {\n document.addEventListener('dblclick', handleMathDoubleClick, { capture: true });\n };\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', initDoubleClick);\n } else {\n setTimeout(initDoubleClick, 100);\n }\n}\n\nexport const MathPlugin = (): Plugin => ({\n name: \"math\",\n\n toolbar: [\n {\n label: \"Insert Math\",\n command: \"insertMath\",\n icon: '<svg width=\"24\" height=\"24\" focusable=\"false\"><path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M9 4.8c.1-.5.5-.8 1-.8h10a1 1 0 1 1 0 2h-9.2L8.3 19.2a1 1 0 0 1-1.7.4l-3.4-4.2a1 1 0 0 1 1.6-1.2l2 2.5L9 4.8Zm9.7 5.5c.4.4.4 1 0 1.4L17 13.5l1.8 1.8a1 1 0 0 1-1.4 1.4L15.5 15l-1.8 1.8a1 1 0 0 1-1.4-1.4l1.8-1.8-1.8-1.8a1 1 0 0 1 1.4-1.4l1.8 1.8 1.8-1.8a1 1 0 0 1 1.4 0Z\"></path></svg>',\n },\n ],\n\n commands: {\n insertMath: () => {\n showMathDialog();\n return true;\n },\n },\n\n keymap: {\n \"Mod-Shift-m\": \"insertMath\",\n },\n});"],"names":["MATH_TEMPLATES","savedSelection","editingMathElement","katexLoaded","loadKaTeX","resolve","reject","checkInterval","link","script","showMathDialog","initialData","selection","overlay","dialog","currentFormat","currentFormula","currentInline","formulaInput","previewArea","templatesGrid","formatRadios","inlineCb","insertBtn","closeBtn","cancelBtn","updateTemplates","templates","btn","updatePreview","formula","katex","e","closeDialog","insertMath","mathData","mathEl","mathContent","radio","handleMathDoubleClick","format","inline","initDoubleClick","MathPlugin"],"mappings":"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"}
|