@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.
Files changed (119) hide show
  1. package/README.md +9 -0
  2. package/dist/A11yCheckerPlugin.native-CZKpi3uF.mjs +475 -0
  3. package/dist/A11yCheckerPlugin.native-CZKpi3uF.mjs.map +1 -0
  4. package/dist/AnchorPlugin.native-7es9PVZ9.mjs +340 -0
  5. package/dist/AnchorPlugin.native-7es9PVZ9.mjs.map +1 -0
  6. package/dist/BackgroundColorPlugin.native-Dip5uqTg.mjs +449 -0
  7. package/dist/BackgroundColorPlugin.native-Dip5uqTg.mjs.map +1 -0
  8. package/dist/BlockquotePlugin.native-JFmOLsxN.mjs +48 -0
  9. package/dist/BlockquotePlugin.native-JFmOLsxN.mjs.map +1 -0
  10. package/dist/BoldPlugin.native-BAzzoqU5.mjs +45 -0
  11. package/dist/BoldPlugin.native-BAzzoqU5.mjs.map +1 -0
  12. package/dist/CapitalizationPlugin.native-DOMsh5R7.mjs +79 -0
  13. package/dist/CapitalizationPlugin.native-DOMsh5R7.mjs.map +1 -0
  14. package/dist/ChecklistPlugin.native-Dccs3nLe.mjs +153 -0
  15. package/dist/ChecklistPlugin.native-Dccs3nLe.mjs.map +1 -0
  16. package/dist/ClearFormattingPlugin.native-BZPDHswo.mjs +27 -0
  17. package/dist/ClearFormattingPlugin.native-BZPDHswo.mjs.map +1 -0
  18. package/dist/CodePlugin.native-DD9xFIid.mjs +1679 -0
  19. package/dist/CodePlugin.native-DD9xFIid.mjs.map +1 -0
  20. package/dist/CodeSamplePlugin.native-DMbEdO9j.mjs +326 -0
  21. package/dist/CodeSamplePlugin.native-DMbEdO9j.mjs.map +1 -0
  22. package/dist/CommentsPlugin.native-2zQV8Ia4.mjs +473 -0
  23. package/dist/CommentsPlugin.native-2zQV8Ia4.mjs.map +1 -0
  24. package/dist/DirectionPlugin.native-Be7wCzkI.mjs +59 -0
  25. package/dist/DirectionPlugin.native-Be7wCzkI.mjs.map +1 -0
  26. package/dist/DocumentManagerPlugin.native-BvZL5CSG.mjs +116 -0
  27. package/dist/DocumentManagerPlugin.native-BvZL5CSG.mjs.map +1 -0
  28. package/dist/EmbedIframePlugin.native-ifr9KLdN.mjs +461 -0
  29. package/dist/EmbedIframePlugin.native-ifr9KLdN.mjs.map +1 -0
  30. package/dist/EmojisPlugin.native-D6mJSnSR.mjs +1033 -0
  31. package/dist/EmojisPlugin.native-D6mJSnSR.mjs.map +1 -0
  32. package/dist/FontFamilyPlugin.native-BzS_9qbM.mjs +106 -0
  33. package/dist/FontFamilyPlugin.native-BzS_9qbM.mjs.map +1 -0
  34. package/dist/FontSizePlugin.native-DkLMLPue.mjs +186 -0
  35. package/dist/FontSizePlugin.native-DkLMLPue.mjs.map +1 -0
  36. package/dist/FootnotePlugin.native-BciVc9W6.mjs +128 -0
  37. package/dist/FootnotePlugin.native-BciVc9W6.mjs.map +1 -0
  38. package/dist/FullscreenPlugin.native-ChXyxeNw.mjs +77 -0
  39. package/dist/FullscreenPlugin.native-ChXyxeNw.mjs.map +1 -0
  40. package/dist/HeadingPlugin.native-DrLYwQnQ.mjs +64 -0
  41. package/dist/HeadingPlugin.native-DrLYwQnQ.mjs.map +1 -0
  42. package/dist/HistoryPlugin.native-DoDRifCf.mjs +89 -0
  43. package/dist/HistoryPlugin.native-DoDRifCf.mjs.map +1 -0
  44. package/dist/IndentPlugin.native-CbFugPoi.mjs +133 -0
  45. package/dist/IndentPlugin.native-CbFugPoi.mjs.map +1 -0
  46. package/dist/ItalicPlugin.native-CQjjDyUL.mjs +43 -0
  47. package/dist/ItalicPlugin.native-CQjjDyUL.mjs.map +1 -0
  48. package/dist/LineHeightPlugin.native-CWQT2FIa.mjs +73 -0
  49. package/dist/LineHeightPlugin.native-CWQT2FIa.mjs.map +1 -0
  50. package/dist/LinkPlugin.native-BdAOV-iu.mjs +206 -0
  51. package/dist/LinkPlugin.native-BdAOV-iu.mjs.map +1 -0
  52. package/dist/ListPlugin.native-CLFU5AUQ.mjs +59 -0
  53. package/dist/ListPlugin.native-CLFU5AUQ.mjs.map +1 -0
  54. package/dist/MathPlugin.native-DE_ii-LA.mjs +182 -0
  55. package/dist/MathPlugin.native-DE_ii-LA.mjs.map +1 -0
  56. package/dist/MediaManagerPlugin.native-DaYFDzNM.mjs +533 -0
  57. package/dist/MediaManagerPlugin.native-DaYFDzNM.mjs.map +1 -0
  58. package/dist/MergeTagPlugin.native-CrxyThyn.mjs +178 -0
  59. package/dist/MergeTagPlugin.native-CrxyThyn.mjs.map +1 -0
  60. package/dist/PageBreakPlugin.native-DDjcDyRW.mjs +172 -0
  61. package/dist/PageBreakPlugin.native-DDjcDyRW.mjs.map +1 -0
  62. package/dist/PreviewPlugin.native-DBvfpmIv.mjs +322 -0
  63. package/dist/PreviewPlugin.native-DBvfpmIv.mjs.map +1 -0
  64. package/dist/PrintPlugin.native-BUpm52VJ.mjs +311 -0
  65. package/dist/PrintPlugin.native-BUpm52VJ.mjs.map +1 -0
  66. package/dist/SpecialCharactersPlugin.native-x7a2SWXc.mjs +731 -0
  67. package/dist/SpecialCharactersPlugin.native-x7a2SWXc.mjs.map +1 -0
  68. package/dist/SpellCheckPlugin.native-B7yTh0iE.mjs +465 -0
  69. package/dist/SpellCheckPlugin.native-B7yTh0iE.mjs.map +1 -0
  70. package/dist/StrikethroughPlugin.native-ChaZLaXw.mjs +43 -0
  71. package/dist/StrikethroughPlugin.native-ChaZLaXw.mjs.map +1 -0
  72. package/dist/TablePlugin.native-EEWXn1-s.mjs +491 -0
  73. package/dist/TablePlugin.native-EEWXn1-s.mjs.map +1 -0
  74. package/dist/TemplatePlugin.native-BlSn1c9h.mjs +564 -0
  75. package/dist/TemplatePlugin.native-BlSn1c9h.mjs.map +1 -0
  76. package/dist/TextAlignmentPlugin.native-CQIs1m7R.mjs +97 -0
  77. package/dist/TextAlignmentPlugin.native-CQIs1m7R.mjs.map +1 -0
  78. package/dist/TextColorPlugin.native-D6SmTglm.mjs +432 -0
  79. package/dist/TextColorPlugin.native-D6SmTglm.mjs.map +1 -0
  80. package/dist/UnderlinePlugin.native-QpIcK4L2.mjs +35 -0
  81. package/dist/UnderlinePlugin.native-QpIcK4L2.mjs.map +1 -0
  82. package/dist/core.css +1 -0
  83. package/dist/documentManager-irzj9n3V.mjs +37627 -0
  84. package/dist/documentManager-irzj9n3V.mjs.map +1 -0
  85. package/dist/editorContainerHelpers-C7kdWnS0.mjs +27 -0
  86. package/dist/editorContainerHelpers-C7kdWnS0.mjs.map +1 -0
  87. package/dist/editora.min.js +519 -4
  88. package/dist/editora.min.js.map +1 -0
  89. package/dist/editora.umd.js +519 -4
  90. package/dist/editora.umd.js.map +1 -0
  91. package/dist/index-BF5RBhL9.js +4 -0
  92. package/dist/index-BF5RBhL9.js.map +1 -0
  93. package/dist/index-BPsf460l.mjs +1243 -0
  94. package/dist/index-BPsf460l.mjs.map +1 -0
  95. package/dist/index.cjs.js +517 -4
  96. package/dist/index.cjs.js.map +1 -0
  97. package/dist/index.es-CuicffkQ.mjs +6665 -0
  98. package/dist/index.es-CuicffkQ.mjs.map +1 -0
  99. package/dist/index.esm.js +1403 -122
  100. package/dist/index.esm.js.map +1 -0
  101. package/dist/plugin-loader.js +55 -0
  102. package/dist/plugin-loader.js.map +1 -0
  103. package/dist/purify.es-CKpwg8Tk.mjs +471 -0
  104. package/dist/purify.es-CKpwg8Tk.mjs.map +1 -0
  105. package/dist/webcomponent-core.js +1243 -0
  106. package/dist/webcomponent-core.js.map +1 -0
  107. package/dist/webcomponent-core.min.css +1 -0
  108. package/dist/webcomponent-core.min.js +597 -0
  109. package/dist/webcomponent-core.min.js.map +1 -0
  110. package/dist/webcomponent.cjs.js +2 -0
  111. package/dist/webcomponent.cjs.js.map +1 -0
  112. package/dist/webcomponent.esm.js +6 -0
  113. package/dist/webcomponent.esm.js.map +1 -0
  114. package/dist/webcomponent.js +1286 -0
  115. package/dist/webcomponent.js.map +1 -0
  116. package/dist/webcomponent.min.css +1 -0
  117. package/dist/webcomponent.min.js +4076 -0
  118. package/dist/webcomponent.min.js.map +1 -0
  119. 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":"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"}
@@ -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, "&quot;")}" 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, '&quot;')}\" 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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"}