@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,77 @@
|
|
|
1
|
+
const o = /* @__PURE__ */ new WeakMap(), a = "rte-fullscreen-active", t = (s) => (o.has(s) || o.set(s, {
|
|
2
|
+
isFullscreen: !1,
|
|
3
|
+
fullscreenButton: null
|
|
4
|
+
}), o.get(s)), y = (s, e) => {
|
|
5
|
+
if (s.classList.add(a), s.style.position = "fixed", s.style.top = "0", s.style.left = "0", s.style.right = "0", s.style.bottom = "0", s.style.width = "100%", s.style.height = "100%", s.style.maxWidth = "100%", s.style.maxHeight = "100%", s.style.borderRadius = "0", s.style.zIndex = "9999", s.style.margin = "0", s.style.padding = "0", s.style.boxShadow = "none", s.style.display = "flex", s.style.flexDirection = "column", s.style.background = "white", document.body.style.overflow = "hidden", document.body.classList.add("fullscreen-active"), e.fullscreenButton) {
|
|
6
|
+
e.fullscreenButton.setAttribute("data-active", "true"), e.fullscreenButton.style.backgroundColor = "var(--rte-color-primary, #007bff)", e.fullscreenButton.style.color = "white";
|
|
7
|
+
const l = e.fullscreenButton.querySelector("svg");
|
|
8
|
+
l && (l.style.fill = "white", l.style.stroke = "white");
|
|
9
|
+
}
|
|
10
|
+
}, c = (s, e) => {
|
|
11
|
+
if (s.classList.remove(a), s.style.position = "", s.style.top = "", s.style.left = "", s.style.right = "", s.style.bottom = "", s.style.width = "", s.style.height = "", s.style.maxWidth = "", s.style.maxHeight = "", s.style.borderRadius = "", s.style.zIndex = "", s.style.margin = "", s.style.padding = "", s.style.boxShadow = "", s.style.display = "", s.style.flexDirection = "", s.style.background = "", document.body.style.overflow = "", document.body.classList.remove("fullscreen-active"), e.fullscreenButton) {
|
|
12
|
+
e.fullscreenButton.setAttribute("data-active", "false"), e.fullscreenButton.style.backgroundColor = "", e.fullscreenButton.style.color = "";
|
|
13
|
+
const l = e.fullscreenButton.querySelector("svg");
|
|
14
|
+
l && (l.style.fill = "", l.style.stroke = "");
|
|
15
|
+
}
|
|
16
|
+
}, i = (s) => {
|
|
17
|
+
try {
|
|
18
|
+
if (!s) {
|
|
19
|
+
const l = document.activeElement;
|
|
20
|
+
l && l.closest("[data-editora-editor]") && (s = l.closest("[data-editora-editor]"));
|
|
21
|
+
}
|
|
22
|
+
if (s || (s = document.querySelector("[data-editora-editor]")), !s)
|
|
23
|
+
return console.warn("Editor element not found"), !1;
|
|
24
|
+
const e = t(s);
|
|
25
|
+
return e.fullscreenButton || (e.fullscreenButton = s.querySelector('[data-command="toggleFullscreen"]')), e.isFullscreen = !e.isFullscreen, e.isFullscreen ? y(s, e) : c(s, e), !0;
|
|
26
|
+
} catch (e) {
|
|
27
|
+
return console.error("Fullscreen toggle failed:", e), !1;
|
|
28
|
+
}
|
|
29
|
+
}, f = (s) => {
|
|
30
|
+
if (!s) {
|
|
31
|
+
document.querySelectorAll("[data-editora-editor]").forEach((l) => {
|
|
32
|
+
const u = l, n = t(u);
|
|
33
|
+
n.isFullscreen && (n.isFullscreen = !1, c(u, n));
|
|
34
|
+
});
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const e = t(s);
|
|
38
|
+
e.isFullscreen && (e.isFullscreen = !1, c(s, e));
|
|
39
|
+
}, d = (s) => t(s).isFullscreen, r = () => {
|
|
40
|
+
const s = (e) => {
|
|
41
|
+
e.key === "Escape" && f();
|
|
42
|
+
};
|
|
43
|
+
return typeof window != "undefined" && window.addEventListener("keydown", s), () => {
|
|
44
|
+
typeof window != "undefined" && window.removeEventListener("keydown", s);
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
typeof window != "undefined" && (document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", r) : r());
|
|
48
|
+
const g = () => ({
|
|
49
|
+
name: "fullscreen",
|
|
50
|
+
toolbar: [
|
|
51
|
+
{
|
|
52
|
+
label: "Fullscreen",
|
|
53
|
+
command: "toggleFullscreen",
|
|
54
|
+
type: "button",
|
|
55
|
+
icon: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"></path></svg>'
|
|
56
|
+
}
|
|
57
|
+
],
|
|
58
|
+
commands: {
|
|
59
|
+
toggleFullscreen: i
|
|
60
|
+
},
|
|
61
|
+
keymap: {
|
|
62
|
+
Escape: () => {
|
|
63
|
+
const s = document.querySelectorAll("[data-editora-editor]");
|
|
64
|
+
for (const e of s)
|
|
65
|
+
if (d(e))
|
|
66
|
+
return f(e), !0;
|
|
67
|
+
return !1;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
export {
|
|
72
|
+
g as FullscreenPlugin,
|
|
73
|
+
f as exitFullscreen,
|
|
74
|
+
d as isFullscreenActive,
|
|
75
|
+
i as toggleFullscreen
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=FullscreenPlugin.native-ChXyxeNw.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FullscreenPlugin.native-ChXyxeNw.mjs","sources":["../../plugins/fullscreen/src/FullscreenPlugin.native.ts"],"sourcesContent":["import { Plugin } from '@editora/core';\n\n/**\n * Fullscreen Plugin - Native Implementation\n * Author: Ajay Kumar <ajaykr089@gmail.com>\n * \n * Provides fullscreen editing mode with:\n * - CSS-based fullscreen (no Fullscreen API dependency)\n * - Escape key to exit\n * - Button state tracking\n * - Smooth transitions\n * - Body scroll lock\n * - Multi-instance support\n */\n\n// Track fullscreen state per editor instance\nconst fullscreenStates = new WeakMap<HTMLElement, {\n isFullscreen: boolean;\n fullscreenButton: HTMLButtonElement | null;\n}>();\n\n// CSS classes and styles\nconst FULLSCREEN_CLASS = 'rte-fullscreen-active';\n\n/**\n * Get or create fullscreen state for an editor element\n */\nconst getFullscreenState = (editorElement: HTMLElement) => {\n if (!fullscreenStates.has(editorElement)) {\n fullscreenStates.set(editorElement, {\n isFullscreen: false,\n fullscreenButton: null\n });\n }\n return fullscreenStates.get(editorElement)!;\n};\n\n/**\n * Apply fullscreen styles to editor\n */\nconst applyFullscreenStyles = (editorElement: HTMLElement, state: { fullscreenButton: HTMLButtonElement | null }) => {\n // Add fullscreen class\n editorElement.classList.add(FULLSCREEN_CLASS);\n\n // Apply inline styles for maximum compatibility\n editorElement.style.position = 'fixed';\n editorElement.style.top = '0';\n editorElement.style.left = '0';\n editorElement.style.right = '0';\n editorElement.style.bottom = '0';\n editorElement.style.width = '100%';\n editorElement.style.height = '100%';\n editorElement.style.maxWidth = '100%';\n editorElement.style.maxHeight = '100%';\n editorElement.style.borderRadius = '0';\n editorElement.style.zIndex = '9999';\n editorElement.style.margin = '0';\n editorElement.style.padding = '0';\n editorElement.style.boxShadow = 'none';\n editorElement.style.display = 'flex';\n editorElement.style.flexDirection = 'column';\n editorElement.style.background = 'white';\n\n // Lock body scroll\n document.body.style.overflow = 'hidden';\n document.body.classList.add('fullscreen-active');\n\n // Update button state\n if (state.fullscreenButton) {\n state.fullscreenButton.setAttribute('data-active', 'true');\n state.fullscreenButton.style.backgroundColor = 'var(--rte-color-primary, #007bff)';\n state.fullscreenButton.style.color = 'white';\n \n const svg = state.fullscreenButton.querySelector('svg');\n if (svg) {\n svg.style.fill = 'white';\n svg.style.stroke = 'white';\n }\n }\n};\n\n/**\n * Remove fullscreen styles from editor\n */\nconst removeFullscreenStyles = (editorElement: HTMLElement, state: { fullscreenButton: HTMLButtonElement | null }) => {\n // Remove fullscreen class\n editorElement.classList.remove(FULLSCREEN_CLASS);\n\n // Clear inline styles\n editorElement.style.position = '';\n editorElement.style.top = '';\n editorElement.style.left = '';\n editorElement.style.right = '';\n editorElement.style.bottom = '';\n editorElement.style.width = '';\n editorElement.style.height = '';\n editorElement.style.maxWidth = '';\n editorElement.style.maxHeight = '';\n editorElement.style.borderRadius = '';\n editorElement.style.zIndex = '';\n editorElement.style.margin = '';\n editorElement.style.padding = '';\n editorElement.style.boxShadow = '';\n editorElement.style.display = '';\n editorElement.style.flexDirection = '';\n editorElement.style.background = '';\n\n // Unlock body scroll\n document.body.style.overflow = '';\n document.body.classList.remove('fullscreen-active');\n\n // Update button state\n if (state.fullscreenButton) {\n state.fullscreenButton.setAttribute('data-active', 'false');\n state.fullscreenButton.style.backgroundColor = '';\n state.fullscreenButton.style.color = '';\n \n const svg = state.fullscreenButton.querySelector('svg');\n if (svg) {\n svg.style.fill = '';\n svg.style.stroke = '';\n }\n }\n};\n\n/**\n * Toggle fullscreen mode for a specific editor\n */\nexport const toggleFullscreen = (editorElement?: HTMLElement): boolean => {\n try {\n // If no editor element provided, find the currently focused one\n if (!editorElement) {\n const focusedElement = document.activeElement;\n if (focusedElement && focusedElement.closest('[data-editora-editor]')) {\n editorElement = focusedElement.closest('[data-editora-editor]') as HTMLElement;\n }\n }\n\n // Fallback to any editor if none found\n if (!editorElement) {\n editorElement = document.querySelector('[data-editora-editor]') as HTMLElement;\n }\n\n if (!editorElement) {\n console.warn('Editor element not found');\n return false;\n }\n\n const state = getFullscreenState(editorElement);\n\n // Find button within this editor's toolbar\n if (!state.fullscreenButton) {\n state.fullscreenButton = editorElement.querySelector('[data-command=\"toggleFullscreen\"]') as HTMLButtonElement;\n }\n\n // Toggle state\n state.isFullscreen = !state.isFullscreen;\n\n if (state.isFullscreen) {\n applyFullscreenStyles(editorElement, state);\n } else {\n removeFullscreenStyles(editorElement, state);\n }\n\n return true;\n } catch (error) {\n console.error('Fullscreen toggle failed:', error);\n return false;\n }\n};\n\n/**\n * Exit fullscreen mode for a specific editor\n */\nexport const exitFullscreen = (editorElement?: HTMLElement): void => {\n if (!editorElement) {\n // Find any fullscreen editor\n document.querySelectorAll('[data-editora-editor]').forEach(el => {\n const element = el as HTMLElement;\n const state = getFullscreenState(element);\n if (state.isFullscreen) {\n state.isFullscreen = false;\n removeFullscreenStyles(element, state);\n }\n });\n return;\n }\n\n const state = getFullscreenState(editorElement);\n if (state.isFullscreen) {\n state.isFullscreen = false;\n removeFullscreenStyles(editorElement, state);\n }\n};\n\n/**\n * Check if a specific editor is in fullscreen mode\n */\nexport const isFullscreenActive = (editorElement: HTMLElement): boolean => {\n const state = getFullscreenState(editorElement);\n return state.isFullscreen;\n};\n\n/**\n * Setup fullscreen event listeners\n */\nconst setupFullscreenListeners = () => {\n // Handle Escape key to exit fullscreen\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n exitFullscreen();\n }\n };\n\n // Setup listeners\n if (typeof window !== 'undefined') {\n window.addEventListener('keydown', handleKeyDown);\n }\n\n // Cleanup function\n return () => {\n if (typeof window !== 'undefined') {\n window.removeEventListener('keydown', handleKeyDown);\n }\n };\n};\n\n// Initialize listeners on load\nif (typeof window !== 'undefined') {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', setupFullscreenListeners);\n } else {\n setupFullscreenListeners();\n }\n}\n\nexport const FullscreenPlugin = (): Plugin => ({\n name: 'fullscreen',\n \n toolbar: [\n {\n label: 'Fullscreen',\n command: 'toggleFullscreen',\n type: 'button',\n icon: '<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3\"></path></svg>'\n }\n ],\n \n commands: {\n toggleFullscreen\n },\n \n keymap: {\n 'Escape': () => {\n // Check if any editor is in fullscreen mode\n const fullscreenEditors = document.querySelectorAll('[data-editora-editor]');\n for (const el of fullscreenEditors) {\n if (isFullscreenActive(el as HTMLElement)) {\n exitFullscreen(el as HTMLElement);\n return true;\n }\n }\n return false;\n }\n }\n});\n"],"names":["fullscreenStates","FULLSCREEN_CLASS","getFullscreenState","editorElement","applyFullscreenStyles","state","svg","removeFullscreenStyles","toggleFullscreen","focusedElement","error","exitFullscreen","el","element","isFullscreenActive","setupFullscreenListeners","handleKeyDown","FullscreenPlugin","fullscreenEditors"],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const t = () => {
|
|
2
|
+
const e = (a) => {
|
|
3
|
+
try {
|
|
4
|
+
return document.execCommand("formatBlock", !1, a), !0;
|
|
5
|
+
} catch (l) {
|
|
6
|
+
return console.error(`Failed to set block type to ${a}:`, l), !1;
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
return {
|
|
10
|
+
name: "heading",
|
|
11
|
+
// Toolbar button configuration with dropdown
|
|
12
|
+
toolbar: [
|
|
13
|
+
{
|
|
14
|
+
label: "Heading",
|
|
15
|
+
command: "setBlockType",
|
|
16
|
+
type: "dropdown",
|
|
17
|
+
options: [
|
|
18
|
+
{ value: "p", label: "Paragraph" },
|
|
19
|
+
{ value: "h1", label: "Heading 1" },
|
|
20
|
+
{ value: "h2", label: "Heading 2" },
|
|
21
|
+
{ value: "h3", label: "Heading 3" },
|
|
22
|
+
{ value: "h4", label: "Heading 4" },
|
|
23
|
+
{ value: "h5", label: "Heading 5" },
|
|
24
|
+
{ value: "h6", label: "Heading 6" }
|
|
25
|
+
],
|
|
26
|
+
icon: '<svg width="24" height="24" focusable="false"><path d="M16.1 8.6 14.2 4l-1.4.5 2.8 7.4c.1.4.5.6.9.6h.1c.4-.1.6-.5.6-.9l1.8-4.8-1.4-.5-1.5 2.3ZM4 11.5h6V10H4v1.5ZM18.5 3v1L17 7l.9.9L20.7 3h-2.2ZM5.5 12h1v7h1v-7h1v-.5h-3V12Zm4 0h1v7h1v-7h1v-.5h-3V12Zm10 1.5a2 2 0 0 0-2-2h-1v7.5h1v-2.7h1a2 2 0 0 0 2-2v-.8Zm-2 1.3h-1v-2.3h1a.8.8 0 1 1 0 1.6v.7Z" fill-rule="evenodd"></path></svg>'
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
// Native command implementations
|
|
30
|
+
commands: {
|
|
31
|
+
/**
|
|
32
|
+
* Set block type to specific heading level or paragraph
|
|
33
|
+
*/
|
|
34
|
+
setBlockType: (a) => a ? e(a) : !1,
|
|
35
|
+
/**
|
|
36
|
+
* Set heading level 1
|
|
37
|
+
*/
|
|
38
|
+
setHeading1: () => e("h1"),
|
|
39
|
+
/**
|
|
40
|
+
* Set heading level 2
|
|
41
|
+
*/
|
|
42
|
+
setHeading2: () => e("h2"),
|
|
43
|
+
/**
|
|
44
|
+
* Set heading level 3
|
|
45
|
+
*/
|
|
46
|
+
setHeading3: () => e("h3"),
|
|
47
|
+
/**
|
|
48
|
+
* Set to paragraph
|
|
49
|
+
*/
|
|
50
|
+
setParagraph: () => e("p")
|
|
51
|
+
},
|
|
52
|
+
// Keyboard shortcuts
|
|
53
|
+
keymap: {
|
|
54
|
+
"Mod-Alt-1": "setHeading1",
|
|
55
|
+
"Mod-Alt-2": "setHeading2",
|
|
56
|
+
"Mod-Alt-3": "setHeading3",
|
|
57
|
+
"Mod-Alt-0": "setParagraph"
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
export {
|
|
62
|
+
t as HeadingPlugin
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=HeadingPlugin.native-DrLYwQnQ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HeadingPlugin.native-DrLYwQnQ.mjs","sources":["../../plugins/heading/src/HeadingPlugin.native.ts"],"sourcesContent":["import { Plugin } from '@editora/core';\n\n/**\n * Heading Plugin - Framework Agnostic\n * \n * Adds heading support (H1-H6) with native command implementation.\n * No React dependency required.\n */\nexport const HeadingPlugin = (): Plugin => {\n const setBlockTypeImpl = (level: string) => {\n try {\n document.execCommand('formatBlock', false, level);\n return true;\n } catch (error) {\n console.error(`Failed to set block type to ${level}:`, error);\n return false;\n }\n };\n\n return {\n name: 'heading',\n \n // Toolbar button configuration with dropdown\n toolbar: [\n {\n label: 'Heading',\n command: 'setBlockType',\n type: 'dropdown',\n options: [\n { value: 'p', label: 'Paragraph' },\n { value: 'h1', label: 'Heading 1' },\n { value: 'h2', label: 'Heading 2' },\n { value: 'h3', label: 'Heading 3' },\n { value: 'h4', label: 'Heading 4' },\n { value: 'h5', label: 'Heading 5' },\n { value: 'h6', label: 'Heading 6' }\n ],\n icon: '<svg width=\"24\" height=\"24\" focusable=\"false\"><path d=\"M16.1 8.6 14.2 4l-1.4.5 2.8 7.4c.1.4.5.6.9.6h.1c.4-.1.6-.5.6-.9l1.8-4.8-1.4-.5-1.5 2.3ZM4 11.5h6V10H4v1.5ZM18.5 3v1L17 7l.9.9L20.7 3h-2.2ZM5.5 12h1v7h1v-7h1v-.5h-3V12Zm4 0h1v7h1v-7h1v-.5h-3V12Zm10 1.5a2 2 0 0 0-2-2h-1v7.5h1v-2.7h1a2 2 0 0 0 2-2v-.8Zm-2 1.3h-1v-2.3h1a.8.8 0 1 1 0 1.6v.7Z\" fill-rule=\"evenodd\"></path></svg>'\n }\n ],\n \n // Native command implementations\n commands: {\n /**\n * Set block type to specific heading level or paragraph\n */\n setBlockType: (level?: string) => {\n if (!level) return false;\n return setBlockTypeImpl(level);\n },\n \n /**\n * Set heading level 1\n */\n setHeading1: () => setBlockTypeImpl('h1'),\n \n /**\n * Set heading level 2\n */\n setHeading2: () => setBlockTypeImpl('h2'),\n \n /**\n * Set heading level 3\n */\n setHeading3: () => setBlockTypeImpl('h3'),\n \n /**\n * Set to paragraph\n */\n setParagraph: () => setBlockTypeImpl('p')\n },\n \n // Keyboard shortcuts\n keymap: {\n 'Mod-Alt-1': 'setHeading1',\n 'Mod-Alt-2': 'setHeading2',\n 'Mod-Alt-3': 'setHeading3',\n 'Mod-Alt-0': 'setParagraph'\n }\n };\n};\n"],"names":["HeadingPlugin","setBlockTypeImpl","level","error"],"mappings":"AAQO,MAAMA,IAAgB,MAAc;AACzC,QAAMC,IAAmB,CAACC,MAAkB;AAC1C,QAAI;AACF,sBAAS,YAAY,eAAe,IAAOA,CAAK,GACzC;AAAA,IACT,SAASC,GAAO;AACd,qBAAQ,MAAM,+BAA+BD,CAAK,KAAKC,CAAK,GACrD;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA;AAAA,IAGN,SAAS;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP,SAAS;AAAA,QACT,MAAM;AAAA,QACN,SAAS;AAAA,UACP,EAAE,OAAO,KAAK,OAAO,YAAA;AAAA,UACrB,EAAE,OAAO,MAAM,OAAO,YAAA;AAAA,UACtB,EAAE,OAAO,MAAM,OAAO,YAAA;AAAA,UACtB,EAAE,OAAO,MAAM,OAAO,YAAA;AAAA,UACtB,EAAE,OAAO,MAAM,OAAO,YAAA;AAAA,UACtB,EAAE,OAAO,MAAM,OAAO,YAAA;AAAA,UACtB,EAAE,OAAO,MAAM,OAAO,YAAA;AAAA,QAAY;AAAA,QAEpC,MAAM;AAAA,MAAA;AAAA,IACR;AAAA;AAAA,IAIF,UAAU;AAAA;AAAA;AAAA;AAAA,MAIR,cAAc,CAACD,MACRA,IACED,EAAiBC,CAAK,IADV;AAAA;AAAA;AAAA;AAAA,MAOrB,aAAa,MAAMD,EAAiB,IAAI;AAAA;AAAA;AAAA;AAAA,MAKxC,aAAa,MAAMA,EAAiB,IAAI;AAAA;AAAA;AAAA;AAAA,MAKxC,aAAa,MAAMA,EAAiB,IAAI;AAAA;AAAA;AAAA;AAAA,MAKxC,cAAc,MAAMA,EAAiB,GAAG;AAAA,IAAA;AAAA;AAAA,IAI1C,QAAQ;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,MACb,aAAa;AAAA,MACb,aAAa;AAAA,IAAA;AAAA,EACf;AAEJ;"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
const s = [], u = [], a = {}, i = (t, o) => {
|
|
2
|
+
a[t] = o, typeof window != "undefined" && (window.registerEditorCommand || (window.registerEditorCommand = (e, n) => {
|
|
3
|
+
a[e] = n;
|
|
4
|
+
}), window.registerEditorCommand(t, o));
|
|
5
|
+
}, y = (t, ...o) => {
|
|
6
|
+
a[t] && a[t](...o);
|
|
7
|
+
}, l = () => (document.execCommand("undo", !1), !0), f = () => (document.execCommand("redo", !1), !0), h = (t, o, e) => {
|
|
8
|
+
const n = t.getAttribute(o);
|
|
9
|
+
t.setAttribute(o, e), s.push(() => {
|
|
10
|
+
n == null ? t.removeAttribute(o) : t.setAttribute(o, n);
|
|
11
|
+
}), u.length = 0;
|
|
12
|
+
}, p = (t, o) => {
|
|
13
|
+
const e = t.textContent;
|
|
14
|
+
t.textContent = o, s.push(() => {
|
|
15
|
+
t.textContent = e != null ? e : "";
|
|
16
|
+
}), u.length = 0;
|
|
17
|
+
}, w = (t) => {
|
|
18
|
+
var c;
|
|
19
|
+
const o = t.element;
|
|
20
|
+
if (!o) return;
|
|
21
|
+
const e = (c = window.a11yRuleRegistry) == null ? void 0 : c.find((r) => r.id === t.rule);
|
|
22
|
+
let n = null;
|
|
23
|
+
if (e && e.fix) {
|
|
24
|
+
const r = {};
|
|
25
|
+
for (const d of o.getAttributeNames())
|
|
26
|
+
r[d] = o.getAttribute(d);
|
|
27
|
+
e.fix(t), n = () => {
|
|
28
|
+
for (const d of Object.keys(r))
|
|
29
|
+
r[d] == null ? o.removeAttribute(d) : o.setAttribute(d, r[d]);
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
n && s.push(n), u.length = 0;
|
|
33
|
+
}, g = () => {
|
|
34
|
+
const t = s.pop();
|
|
35
|
+
t && (t(), u.push(t));
|
|
36
|
+
}, b = () => {
|
|
37
|
+
const t = u.pop();
|
|
38
|
+
t && (t(), s.push(t));
|
|
39
|
+
}, m = () => {
|
|
40
|
+
typeof window != "undefined" && (window.execEditorCommand || (window.execEditorCommand = y), i("undo", l), i("redo", f), i("setAttribute", h), i("setText", p), i("autoFixA11y", w), i("undoDom", g), i("redoDom", b));
|
|
41
|
+
};
|
|
42
|
+
typeof window != "undefined" && (document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", m) : m());
|
|
43
|
+
const x = () => ({
|
|
44
|
+
name: "history",
|
|
45
|
+
toolbar: [
|
|
46
|
+
{
|
|
47
|
+
label: "Undo",
|
|
48
|
+
command: "undo",
|
|
49
|
+
type: "button",
|
|
50
|
+
icon: '<svg width="24" height="24" focusable="false"><path d="M6.4 8H12c3.7 0 6.2 2 6.8 5.1.6 2.7-.4 5.6-2.3 6.8a1 1 0 0 1-1-1.8c1.1-.6 1.8-2.7 1.4-4.6-.5-2.1-2.1-3.5-4.9-3.5H6.4l3.3 3.3a1 1 0 1 1-1.4 1.4l-5-5a1 1 0 0 1 0-1.4l5-5a1 1 0 0 1 1.4 1.4L6.4 8Z" fill-rule="nonzero"></path></svg>',
|
|
51
|
+
shortcut: "Mod-z"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
label: "Redo",
|
|
55
|
+
command: "redo",
|
|
56
|
+
type: "button",
|
|
57
|
+
icon: '<svg width="24" height="24" focusable="false"><path d="M17.6 10H12c-2.8 0-4.4 1.4-4.9 3.5-.4 2 .3 4 1.4 4.6a1 1 0 1 1-1 1.8c-2-1.2-2.9-4.1-2.3-6.8.6-3 3-5.1 6.8-5.1h5.6l-3.3-3.3a1 1 0 1 1 1.4-1.4l5 5a1 1 0 0 1 0 1.4l-5 5a1 1 0 0 1-1.4-1.4l3.3-3.3Z" fill-rule="nonzero"></path></svg>',
|
|
58
|
+
shortcut: "Mod-y"
|
|
59
|
+
}
|
|
60
|
+
],
|
|
61
|
+
commands: {
|
|
62
|
+
undo: l,
|
|
63
|
+
redo: f,
|
|
64
|
+
setAttribute: h,
|
|
65
|
+
setText: p,
|
|
66
|
+
autoFixA11y: w,
|
|
67
|
+
undoDom: g,
|
|
68
|
+
redoDom: b
|
|
69
|
+
},
|
|
70
|
+
keymap: {
|
|
71
|
+
"Mod-z": "undo",
|
|
72
|
+
"Mod-Z": "undo",
|
|
73
|
+
"Mod-y": "redo",
|
|
74
|
+
"Mod-Y": "redo",
|
|
75
|
+
"Mod-Shift-z": "redo",
|
|
76
|
+
"Mod-Shift-Z": "redo"
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
export {
|
|
80
|
+
x as HistoryPlugin,
|
|
81
|
+
w as autoFixA11y,
|
|
82
|
+
f as redo,
|
|
83
|
+
b as redoDom,
|
|
84
|
+
h as setAttribute,
|
|
85
|
+
p as setText,
|
|
86
|
+
l as undo,
|
|
87
|
+
g as undoDom
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=HistoryPlugin.native-DoDRifCf.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HistoryPlugin.native-DoDRifCf.mjs","sources":["../../plugins/history/src/HistoryPlugin.native.ts"],"sourcesContent":["import { Plugin } from '@editora/core';\n\n/**\n * History Plugin - Native Implementation\n * Author: Ajay Kumar <ajaykr089@gmail.com>\n * \n * Provides comprehensive undo/redo functionality:\n * - ContentEditable native undo/redo (Ctrl/Cmd+Z, Ctrl/Cmd+Y)\n * - DOM-level undo/redo stack for A11y auto-fixes\n * - Global command registration system\n * - Attribute and text change tracking\n */\n\n// DOM undo/redo stacks for A11y and other DOM manipulations\nconst domUndoStack: Array<() => void> = [];\nconst domRedoStack: Array<() => void> = [];\n\n// Command registry for global access\nconst commandHandlers: Record<string, (...args: any[]) => void> = {};\n\n/**\n * Register a command globally\n */\nconst registerCommand = (command: string, handler: (...args: any[]) => void): void => {\n commandHandlers[command] = handler;\n \n // Expose to global window object for external access\n if (typeof window !== 'undefined') {\n if (!(window as any).registerEditorCommand) {\n (window as any).registerEditorCommand = (cmd: string, fn: (...args: any[]) => void) => {\n commandHandlers[cmd] = fn;\n };\n }\n (window as any).registerEditorCommand(command, handler);\n }\n};\n\n/**\n * Execute a registered command\n */\nconst execEditorCommand = (cmd: string, ...args: any[]): void => {\n if (commandHandlers[cmd]) {\n commandHandlers[cmd](...args);\n }\n};\n\n/**\n * Undo the last action (ContentEditable)\n */\nexport const undo = (): boolean => {\n document.execCommand('undo', false);\n return true;\n};\n\n/**\n * Redo the last undone action (ContentEditable)\n */\nexport const redo = (): boolean => {\n document.execCommand('redo', false);\n return true;\n};\n\n/**\n * Set an attribute on an element with undo support\n */\nexport const setAttribute = (el: HTMLElement, attr: string, value: string): void => {\n const prev = el.getAttribute(attr);\n el.setAttribute(attr, value);\n \n // Push undo action to stack\n domUndoStack.push(() => {\n if (prev == null) {\n el.removeAttribute(attr);\n } else {\n el.setAttribute(attr, prev);\n }\n });\n \n // Clear redo stack when new action is performed\n domRedoStack.length = 0;\n};\n\n/**\n * Set text content on an element with undo support\n */\nexport const setText = (el: HTMLElement, value: string): void => {\n const prev = el.textContent;\n el.textContent = value;\n \n // Push undo action to stack\n domUndoStack.push(() => {\n el.textContent = prev ?? '';\n });\n \n // Clear redo stack when new action is performed\n domRedoStack.length = 0;\n};\n\n/**\n * Auto-fix an A11y issue with undo support\n */\nexport const autoFixA11y = (issue: any): void => {\n const el = issue.element;\n if (!el) return;\n \n // Find the A11y rule\n const rule = (window as any).a11yRuleRegistry?.find((r: any) => r.id === issue.rule);\n \n let undoFn: (() => void) | null = null;\n \n if (rule && rule.fix) {\n // Capture current state of all attributes\n const prevAttrs: Record<string, string | null> = {};\n for (const attr of el.getAttributeNames()) {\n prevAttrs[attr] = el.getAttribute(attr);\n }\n \n // Apply the fix\n rule.fix(issue);\n \n // Create undo function\n undoFn = () => {\n for (const attr of Object.keys(prevAttrs)) {\n if (prevAttrs[attr] == null) {\n el.removeAttribute(attr);\n } else {\n el.setAttribute(attr, prevAttrs[attr]!);\n }\n }\n };\n }\n \n if (undoFn) {\n domUndoStack.push(undoFn);\n }\n \n // Clear redo stack when new action is performed\n domRedoStack.length = 0;\n};\n\n/**\n * Undo the last DOM change\n */\nexport const undoDom = (): void => {\n const fn = domUndoStack.pop();\n if (fn) {\n fn();\n domRedoStack.push(fn);\n }\n};\n\n/**\n * Redo the last undone DOM change\n */\nexport const redoDom = (): void => {\n const fn = domRedoStack.pop();\n if (fn) {\n fn();\n domUndoStack.push(fn);\n }\n};\n\n/**\n * Initialize global command system\n */\nconst initializeCommandSystem = (): void => {\n if (typeof window === 'undefined') return;\n \n // Set up global command executor if not already present\n if (!(window as any).execEditorCommand) {\n (window as any).execEditorCommand = execEditorCommand;\n }\n \n // Register all commands\n registerCommand('undo', undo);\n registerCommand('redo', redo);\n registerCommand('setAttribute', setAttribute);\n registerCommand('setText', setText);\n registerCommand('autoFixA11y', autoFixA11y);\n registerCommand('undoDom', undoDom);\n registerCommand('redoDom', redoDom);\n};\n\n// Initialize on load\nif (typeof window !== 'undefined') {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', initializeCommandSystem);\n } else {\n initializeCommandSystem();\n }\n}\n\nexport const HistoryPlugin = (): Plugin => ({\n name: 'history',\n \n toolbar: [\n {\n label: 'Undo',\n command: 'undo',\n type: 'button',\n icon: '<svg width=\"24\" height=\"24\" focusable=\"false\"><path d=\"M6.4 8H12c3.7 0 6.2 2 6.8 5.1.6 2.7-.4 5.6-2.3 6.8a1 1 0 0 1-1-1.8c1.1-.6 1.8-2.7 1.4-4.6-.5-2.1-2.1-3.5-4.9-3.5H6.4l3.3 3.3a1 1 0 1 1-1.4 1.4l-5-5a1 1 0 0 1 0-1.4l5-5a1 1 0 0 1 1.4 1.4L6.4 8Z\" fill-rule=\"nonzero\"></path></svg>',\n shortcut: 'Mod-z'\n },\n {\n label: 'Redo',\n command: 'redo',\n type: 'button',\n icon: '<svg width=\"24\" height=\"24\" focusable=\"false\"><path d=\"M17.6 10H12c-2.8 0-4.4 1.4-4.9 3.5-.4 2 .3 4 1.4 4.6a1 1 0 1 1-1 1.8c-2-1.2-2.9-4.1-2.3-6.8.6-3 3-5.1 6.8-5.1h5.6l-3.3-3.3a1 1 0 1 1 1.4-1.4l5 5a1 1 0 0 1 0 1.4l-5 5a1 1 0 0 1-1.4-1.4l3.3-3.3Z\" fill-rule=\"nonzero\"></path></svg>',\n shortcut: 'Mod-y'\n }\n ],\n \n commands: {\n undo,\n redo,\n setAttribute,\n setText,\n autoFixA11y,\n undoDom,\n redoDom\n },\n \n keymap: {\n 'Mod-z': 'undo',\n 'Mod-Z': 'undo',\n 'Mod-y': 'redo',\n 'Mod-Y': 'redo',\n 'Mod-Shift-z': 'redo',\n 'Mod-Shift-Z': 'redo'\n }\n});\n"],"names":["domUndoStack","domRedoStack","commandHandlers","registerCommand","command","handler","cmd","fn","execEditorCommand","args","undo","redo","setAttribute","el","attr","value","prev","setText","autoFixA11y","issue","_a","rule","undoFn","prevAttrs","undoDom","redoDom","initializeCommandSystem","HistoryPlugin"],"mappings":"AAcA,MAAMA,IAAkC,CAAA,GAClCC,IAAkC,CAAA,GAGlCC,IAA4D,CAAA,GAK5DC,IAAkB,CAACC,GAAiBC,MAA4C;AACpF,EAAAH,EAAgBE,CAAO,IAAIC,GAGvB,OAAO,UAAW,gBACd,OAAe,0BAClB,OAAe,wBAAwB,CAACC,GAAaC,MAAiC;AACrF,IAAAL,EAAgBI,CAAG,IAAIC;AAAA,EACzB,IAED,OAAe,sBAAsBH,GAASC,CAAO;AAE1D,GAKMG,IAAoB,CAACF,MAAgBG,MAAsB;AAC/D,EAAIP,EAAgBI,CAAG,KACrBJ,EAAgBI,CAAG,EAAE,GAAGG,CAAI;AAEhC,GAKaC,IAAO,OAClB,SAAS,YAAY,QAAQ,EAAK,GAC3B,KAMIC,IAAO,OAClB,SAAS,YAAY,QAAQ,EAAK,GAC3B,KAMIC,IAAe,CAACC,GAAiBC,GAAcC,MAAwB;AAClF,QAAMC,IAAOH,EAAG,aAAaC,CAAI;AACjC,EAAAD,EAAG,aAAaC,GAAMC,CAAK,GAG3Bf,EAAa,KAAK,MAAM;AACtB,IAAIgB,KAAQ,OACVH,EAAG,gBAAgBC,CAAI,IAEvBD,EAAG,aAAaC,GAAME,CAAI;AAAA,EAE9B,CAAC,GAGDf,EAAa,SAAS;AACxB,GAKagB,IAAU,CAACJ,GAAiBE,MAAwB;AAC/D,QAAMC,IAAOH,EAAG;AAChB,EAAAA,EAAG,cAAcE,GAGjBf,EAAa,KAAK,MAAM;AACtB,IAAAa,EAAG,cAAcG,KAAA,OAAAA,IAAQ;AAAA,EAC3B,CAAC,GAGDf,EAAa,SAAS;AACxB,GAKaiB,IAAc,CAACC,MAAqB;AAvFjD,MAAAC;AAwFE,QAAMP,IAAKM,EAAM;AACjB,MAAI,CAACN,EAAI;AAGT,QAAMQ,KAAQD,IAAA,OAAe,qBAAf,gBAAAA,EAAiC,KAAK,CAAC,MAAW,EAAE,OAAOD,EAAM;AAE/E,MAAIG,IAA8B;AAElC,MAAID,KAAQA,EAAK,KAAK;AAEpB,UAAME,IAA2C,CAAA;AACjD,eAAWT,KAAQD,EAAG;AACpB,MAAAU,EAAUT,CAAI,IAAID,EAAG,aAAaC,CAAI;AAIxC,IAAAO,EAAK,IAAIF,CAAK,GAGdG,IAAS,MAAM;AACb,iBAAWR,KAAQ,OAAO,KAAKS,CAAS;AACtC,QAAIA,EAAUT,CAAI,KAAK,OACrBD,EAAG,gBAAgBC,CAAI,IAEvBD,EAAG,aAAaC,GAAMS,EAAUT,CAAI,CAAE;AAAA,IAG5C;AAAA,EACF;AAEA,EAAIQ,KACFtB,EAAa,KAAKsB,CAAM,GAI1BrB,EAAa,SAAS;AACxB,GAKauB,IAAU,MAAY;AACjC,QAAMjB,IAAKP,EAAa,IAAA;AACxB,EAAIO,MACFA,EAAA,GACAN,EAAa,KAAKM,CAAE;AAExB,GAKakB,IAAU,MAAY;AACjC,QAAMlB,IAAKN,EAAa,IAAA;AACxB,EAAIM,MACFA,EAAA,GACAP,EAAa,KAAKO,CAAE;AAExB,GAKMmB,IAA0B,MAAY;AAC1C,EAAI,OAAO,UAAW,gBAGhB,OAAe,sBAClB,OAAe,oBAAoBlB,IAItCL,EAAgB,QAAQO,CAAI,GAC5BP,EAAgB,QAAQQ,CAAI,GAC5BR,EAAgB,gBAAgBS,CAAY,GAC5CT,EAAgB,WAAWc,CAAO,GAClCd,EAAgB,eAAee,CAAW,GAC1Cf,EAAgB,WAAWqB,CAAO,GAClCrB,EAAgB,WAAWsB,CAAO;AACpC;AAGI,OAAO,UAAW,gBAChB,SAAS,eAAe,YAC1B,SAAS,iBAAiB,oBAAoBC,CAAuB,IAErEA,EAAA;AAIG,MAAMC,IAAgB,OAAe;AAAA,EAC1C,MAAM;AAAA,EAEN,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,MAAAjB;AAAA,IACA,MAAAC;AAAA,IACA,cAAAC;AAAA,IACA,SAAAK;AAAA,IACA,aAAAC;AAAA,IACA,SAAAM;AAAA,IACA,SAAAC;AAAA,EAAA;AAAA,EAGF,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,eAAe;AAAA,IACf,eAAe;AAAA,EAAA;AAEnB;"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
const d = (n) => ["P", "DIV", "H1", "H2", "H3", "H4", "H5", "H6", "LI", "BLOCKQUOTE", "PRE"].includes(n.tagName), u = () => {
|
|
2
|
+
const n = window.getSelection();
|
|
3
|
+
if (n && n.rangeCount > 0) {
|
|
4
|
+
let e = n.getRangeAt(0).startContainer;
|
|
5
|
+
for (; e && e !== document.body; ) {
|
|
6
|
+
if (e.nodeType === Node.ELEMENT_NODE) {
|
|
7
|
+
const o = e;
|
|
8
|
+
if (o.getAttribute("contenteditable") === "true")
|
|
9
|
+
return o;
|
|
10
|
+
}
|
|
11
|
+
e = e.parentNode;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
const t = document.activeElement;
|
|
15
|
+
if (t) {
|
|
16
|
+
if (t.getAttribute("contenteditable") === "true")
|
|
17
|
+
return t;
|
|
18
|
+
const e = t.closest('[contenteditable="true"]');
|
|
19
|
+
if (e) return e;
|
|
20
|
+
}
|
|
21
|
+
return document.querySelector('[contenteditable="true"]');
|
|
22
|
+
}, s = (n) => {
|
|
23
|
+
let t = n;
|
|
24
|
+
if (t.nodeType === Node.ELEMENT_NODE) {
|
|
25
|
+
const e = t;
|
|
26
|
+
if (d(e))
|
|
27
|
+
return e;
|
|
28
|
+
}
|
|
29
|
+
for (; t; ) {
|
|
30
|
+
if (t.nodeType === Node.ELEMENT_NODE) {
|
|
31
|
+
const e = t;
|
|
32
|
+
if (d(e))
|
|
33
|
+
return e;
|
|
34
|
+
if (e.getAttribute("contenteditable") === "true")
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
t = t.parentNode;
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}, f = (n) => {
|
|
41
|
+
const t = [], e = s(n.startContainer), o = s(n.endContainer);
|
|
42
|
+
if (!e && !o) return t;
|
|
43
|
+
if (n.collapsed)
|
|
44
|
+
return e && t.push(e), t;
|
|
45
|
+
if (e === o)
|
|
46
|
+
e && t.push(e);
|
|
47
|
+
else {
|
|
48
|
+
let r = e;
|
|
49
|
+
for (; r && r !== o; ) {
|
|
50
|
+
t.push(r);
|
|
51
|
+
let i = r.nextElementSibling;
|
|
52
|
+
for (; i && !d(i); )
|
|
53
|
+
i = i.nextElementSibling;
|
|
54
|
+
r = i;
|
|
55
|
+
}
|
|
56
|
+
o && o !== e && t.push(o);
|
|
57
|
+
}
|
|
58
|
+
return t;
|
|
59
|
+
}, g = (n) => {
|
|
60
|
+
const t = window.getComputedStyle(n), e = t.paddingLeft;
|
|
61
|
+
if (e.endsWith("px"))
|
|
62
|
+
return parseFloat(e);
|
|
63
|
+
if (e.endsWith("em")) {
|
|
64
|
+
const o = parseFloat(t.fontSize);
|
|
65
|
+
return parseFloat(e) * o;
|
|
66
|
+
}
|
|
67
|
+
return 0;
|
|
68
|
+
}, m = () => {
|
|
69
|
+
const n = u();
|
|
70
|
+
if (!n) return !1;
|
|
71
|
+
const t = window.getSelection();
|
|
72
|
+
if (!t || t.rangeCount === 0) return !1;
|
|
73
|
+
const e = t.getRangeAt(0);
|
|
74
|
+
if (!n.contains(e.commonAncestorContainer)) return !1;
|
|
75
|
+
const o = f(e);
|
|
76
|
+
return o.length === 0 ? !1 : (o.forEach((r) => {
|
|
77
|
+
const a = g(r) + 40;
|
|
78
|
+
r.style.paddingLeft = `${a}px`;
|
|
79
|
+
}), !0);
|
|
80
|
+
}, h = () => {
|
|
81
|
+
const n = u();
|
|
82
|
+
if (!n) return !1;
|
|
83
|
+
const t = window.getSelection();
|
|
84
|
+
if (!t || t.rangeCount === 0) return !1;
|
|
85
|
+
const e = t.getRangeAt(0);
|
|
86
|
+
if (!n.contains(e.commonAncestorContainer)) return !1;
|
|
87
|
+
const o = f(e);
|
|
88
|
+
return o.length === 0 ? !1 : (o.forEach((r) => {
|
|
89
|
+
const i = g(r), a = Math.max(0, i - 40);
|
|
90
|
+
r.style.paddingLeft = `${a}px`;
|
|
91
|
+
}), !0);
|
|
92
|
+
}, c = (n, t) => {
|
|
93
|
+
var e;
|
|
94
|
+
typeof window != "undefined" && ((e = window.registerEditorCommand) == null || e.call(window, n, t));
|
|
95
|
+
}, l = () => {
|
|
96
|
+
c("increaseIndent", m), c("decreaseIndent", h);
|
|
97
|
+
};
|
|
98
|
+
typeof window != "undefined" && (document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", l) : l());
|
|
99
|
+
const p = () => ({
|
|
100
|
+
name: "indent",
|
|
101
|
+
toolbar: [
|
|
102
|
+
{
|
|
103
|
+
label: "Increase Indent",
|
|
104
|
+
command: "increaseIndent",
|
|
105
|
+
type: "button",
|
|
106
|
+
icon: '<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M3 4h18v2H3V4zm0 14h18v2H3v-2zm8-7h10v2H11v-2zm0 4h10v2H11v-2zM3 8l4 4-4 4V8z"/></svg>',
|
|
107
|
+
shortcut: "Mod-]"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
label: "Decrease Indent",
|
|
111
|
+
command: "decreaseIndent",
|
|
112
|
+
type: "button",
|
|
113
|
+
icon: '<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M3 4h18v2H3V4zm0 14h18v2H3v-2zm8-7h10v2H11v-2zm0 4h10v2H11v-2zM7 8v8l-4-4 4-4z"/></svg>',
|
|
114
|
+
shortcut: "Mod-["
|
|
115
|
+
}
|
|
116
|
+
],
|
|
117
|
+
commands: {
|
|
118
|
+
increaseIndent: m,
|
|
119
|
+
decreaseIndent: h
|
|
120
|
+
},
|
|
121
|
+
keymap: {
|
|
122
|
+
"Mod-]": "increaseIndent",
|
|
123
|
+
"Mod-[": "decreaseIndent",
|
|
124
|
+
Tab: "increaseIndent",
|
|
125
|
+
"Shift-Tab": "decreaseIndent"
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
export {
|
|
129
|
+
p as IndentPlugin,
|
|
130
|
+
h as decreaseIndent,
|
|
131
|
+
m as increaseIndent
|
|
132
|
+
};
|
|
133
|
+
//# sourceMappingURL=IndentPlugin.native-CbFugPoi.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IndentPlugin.native-CbFugPoi.mjs","sources":["../../plugins/indent/src/IndentPlugin.native.ts"],"sourcesContent":["import { Plugin } from '@editora/core';\n\n/**\n * Indent Plugin - Native Implementation\n * Author: Ajay Kumar <ajaykr089@gmail.com>\n * \n * Provides advanced indentation with:\n * - Custom padding-based indentation (40px increments)\n * - Multi-paragraph selection support\n * - Smart paragraph detection\n * - Unit conversion (px, em)\n * - Keyboard shortcuts (Tab, Shift-Tab, Cmd-[, Cmd-])\n */\n\nconst INDENT_AMOUNT = 40; // pixels\n\n/**\n * Check if an element is a block-level element that can be indented\n */\nconst isBlockElement = (element: HTMLElement): boolean => {\n const blockTags = ['P', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'LI', 'BLOCKQUOTE', 'PRE'];\n return blockTags.includes(element.tagName);\n};\n\n/**\n * Find the active editor element\n */\nconst findActiveEditor = (): HTMLElement | null => {\n // Try to find editor from current selection\n const selection = window.getSelection();\n if (selection && selection.rangeCount > 0) {\n let node: Node | null = selection.getRangeAt(0).startContainer;\n while (node && node !== document.body) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const element = node as HTMLElement;\n if (element.getAttribute('contenteditable') === 'true') {\n return element;\n }\n }\n node = node.parentNode;\n }\n }\n \n // Try active element\n const activeElement = document.activeElement;\n if (activeElement) {\n if (activeElement.getAttribute('contenteditable') === 'true') {\n return activeElement as HTMLElement;\n }\n const editor = activeElement.closest('[contenteditable=\"true\"]');\n if (editor) return editor as HTMLElement;\n }\n \n // Fallback to first editor\n return document.querySelector('[contenteditable=\"true\"]');\n};\n\n/**\n * Find the containing block element (paragraph, div, heading, etc.)\n */\nconst findContainingParagraph = (node: Node): HTMLElement | null => {\n let current: Node | null = node;\n\n // If the node itself is a block element, return it\n if (current.nodeType === Node.ELEMENT_NODE) {\n const element = current as HTMLElement;\n if (isBlockElement(element)) {\n return element;\n }\n }\n\n // Traverse up the DOM tree to find the nearest block element\n while (current) {\n if (current.nodeType === Node.ELEMENT_NODE) {\n const element = current as HTMLElement;\n if (isBlockElement(element)) {\n return element;\n }\n // Stop if we hit the contenteditable boundary\n if (element.getAttribute('contenteditable') === 'true') {\n break;\n }\n }\n current = current.parentNode;\n }\n\n return null;\n};\n\n/**\n * Find all paragraphs that intersect with the range\n */\nconst getParagraphsInRange = (range: Range): HTMLElement[] => {\n const paragraphs: HTMLElement[] = [];\n const startParagraph = findContainingParagraph(range.startContainer);\n const endParagraph = findContainingParagraph(range.endContainer);\n\n if (!startParagraph && !endParagraph) return paragraphs;\n\n // If range is collapsed (just cursor), return the paragraph containing the cursor\n if (range.collapsed) {\n if (startParagraph) paragraphs.push(startParagraph);\n return paragraphs;\n }\n\n // For actual selections, find all paragraphs between start and end\n if (startParagraph === endParagraph) {\n // Selection is within a single paragraph\n if (startParagraph) paragraphs.push(startParagraph);\n } else {\n // Selection spans multiple block elements - find all blocks in between\n let current: HTMLElement | null = startParagraph;\n while (current && current !== endParagraph) {\n paragraphs.push(current);\n let nextSibling = current.nextElementSibling as HTMLElement | null;\n // If we hit a non-block element, continue until we find the next block element\n while (nextSibling && !isBlockElement(nextSibling)) {\n nextSibling = nextSibling.nextElementSibling as HTMLElement | null;\n }\n current = nextSibling;\n }\n // Add the end paragraph if it's different\n if (endParagraph && endParagraph !== startParagraph) {\n paragraphs.push(endParagraph);\n }\n }\n\n return paragraphs;\n};\n\n/**\n * Get current padding-left value in pixels\n */\nconst getCurrentPadding = (element: HTMLElement): number => {\n const computedStyle = window.getComputedStyle(element);\n const paddingLeft = computedStyle.paddingLeft;\n \n // Convert to pixels (assuming px or em units)\n if (paddingLeft.endsWith('px')) {\n return parseFloat(paddingLeft);\n } else if (paddingLeft.endsWith('em')) {\n const fontSize = parseFloat(computedStyle.fontSize);\n return parseFloat(paddingLeft) * fontSize;\n }\n \n return 0;\n};\n\n/**\n * Increase indentation level\n */\nexport const increaseIndent = (): boolean => {\n const editor = findActiveEditor();\n if (!editor) return false;\n\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return false;\n\n const range = selection.getRangeAt(0);\n \n // Verify selection is within the active editor\n if (!editor.contains(range.commonAncestorContainer)) return false;\n\n const paragraphs = getParagraphsInRange(range);\n\n if (paragraphs.length === 0) return false;\n\n // Apply indentation to all selected paragraphs\n paragraphs.forEach(paragraph => {\n const currentPadding = getCurrentPadding(paragraph);\n const newPadding = currentPadding + INDENT_AMOUNT;\n paragraph.style.paddingLeft = `${newPadding}px`;\n });\n\n return true;\n};\n\n/**\n * Decrease indentation level\n */\nexport const decreaseIndent = (): boolean => {\n const editor = findActiveEditor();\n if (!editor) return false;\n\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return false;\n\n const range = selection.getRangeAt(0);\n \n // Verify selection is within the active editor\n if (!editor.contains(range.commonAncestorContainer)) return false;\n\n const paragraphs = getParagraphsInRange(range);\n\n if (paragraphs.length === 0) return false;\n\n // Apply indentation to all selected paragraphs\n paragraphs.forEach(paragraph => {\n const currentPadding = getCurrentPadding(paragraph);\n const newPadding = Math.max(0, currentPadding - INDENT_AMOUNT); // Minimum 0\n paragraph.style.paddingLeft = `${newPadding}px`;\n });\n\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('increaseIndent', increaseIndent);\n registerCommand('decreaseIndent', decreaseIndent);\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 IndentPlugin = (): Plugin => ({\n name: 'indent',\n \n toolbar: [\n {\n label: 'Increase Indent',\n command: 'increaseIndent',\n type: 'button',\n icon: '<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M3 4h18v2H3V4zm0 14h18v2H3v-2zm8-7h10v2H11v-2zm0 4h10v2H11v-2zM3 8l4 4-4 4V8z\"/></svg>',\n shortcut: 'Mod-]'\n },\n {\n label: 'Decrease Indent',\n command: 'decreaseIndent',\n type: 'button',\n icon: '<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M3 4h18v2H3V4zm0 14h18v2H3v-2zm8-7h10v2H11v-2zm0 4h10v2H11v-2zM7 8v8l-4-4 4-4z\"/></svg>',\n shortcut: 'Mod-['\n }\n ],\n \n commands: {\n increaseIndent,\n decreaseIndent\n },\n \n keymap: {\n 'Mod-]': 'increaseIndent',\n 'Mod-[': 'decreaseIndent',\n 'Tab': 'increaseIndent',\n 'Shift-Tab': 'decreaseIndent'\n }\n});\n"],"names":["isBlockElement","element","findActiveEditor","selection","node","activeElement","editor","findContainingParagraph","current","getParagraphsInRange","range","paragraphs","startParagraph","endParagraph","nextSibling","getCurrentPadding","computedStyle","paddingLeft","fontSize","increaseIndent","paragraph","newPadding","decreaseIndent","currentPadding","registerCommand","command","handler","_a","initializeCommands","IndentPlugin"],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const i = () => (document.execCommand("italic", !1), !0), a = (o, l) => {
|
|
2
|
+
var t;
|
|
3
|
+
typeof window != "undefined" && ((t = window.registerEditorCommand) == null || t.call(window, o, l));
|
|
4
|
+
}, e = () => {
|
|
5
|
+
a("toggleItalic", i);
|
|
6
|
+
};
|
|
7
|
+
typeof window != "undefined" && (document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", e) : e());
|
|
8
|
+
const n = () => ({
|
|
9
|
+
name: "italic",
|
|
10
|
+
marks: {
|
|
11
|
+
italic: {
|
|
12
|
+
parseDOM: [
|
|
13
|
+
{ tag: "i" },
|
|
14
|
+
{ tag: "em" },
|
|
15
|
+
{
|
|
16
|
+
style: "font-style=italic"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
toDOM: () => ["em", 0]
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
toolbar: [
|
|
23
|
+
{
|
|
24
|
+
label: "Italic",
|
|
25
|
+
command: "toggleItalic",
|
|
26
|
+
type: "button",
|
|
27
|
+
icon: '<svg width="24" height="24" focusable="false"><path d="M16.7 4.7l-.1.9h-.3c-.6 0-1 0-1.4.3-.3.3-.4.6-.5 1.1l-2.1 9.8v.6c0 .5.4.8 1.4.8h.2l-.2.8H8l.2-.8h.2c1.1 0 1.8-.5 2-1.5l2-9.8.1-.5c0-.6-.4-.8-1.4-.8h-.3l.2-.9h5.8Z" fill-rule="evenodd"></path></svg>',
|
|
28
|
+
shortcut: "Mod-i"
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
commands: {
|
|
32
|
+
toggleItalic: i
|
|
33
|
+
},
|
|
34
|
+
keymap: {
|
|
35
|
+
"Mod-i": "toggleItalic",
|
|
36
|
+
"Mod-I": "toggleItalic"
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
export {
|
|
40
|
+
n as ItalicPlugin,
|
|
41
|
+
i as toggleItalic
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=ItalicPlugin.native-CQjjDyUL.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ItalicPlugin.native-CQjjDyUL.mjs","sources":["../../plugins/italic/src/ItalicPlugin.native.ts"],"sourcesContent":["import { Plugin } from '@editora/core';\n\n/**\n * Italic Plugin - Native Implementation\n * Author: Ajay Kumar <ajaykr089@gmail.com>\n * \n * Provides italic text formatting with:\n * - Semantic <em> tag output\n * - Support for <i>, <em>, and inline font-style\n * - Keyboard shortcut (Cmd/Ctrl+I)\n * - Global command registration\n */\n\n/**\n * Toggle italic formatting on current selection\n */\nexport const toggleItalic = (): boolean => {\n document.execCommand('italic', 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('toggleItalic', toggleItalic);\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 ItalicPlugin = (): Plugin => ({\n name: 'italic',\n \n marks: {\n italic: {\n parseDOM: [\n { tag: 'i' },\n { tag: 'em' },\n {\n style: 'font-style=italic'\n }\n ],\n toDOM: () => ['em', 0]\n }\n },\n \n toolbar: [\n {\n label: 'Italic',\n command: 'toggleItalic',\n type: 'button',\n icon: '<svg width=\"24\" height=\"24\" focusable=\"false\"><path d=\"M16.7 4.7l-.1.9h-.3c-.6 0-1 0-1.4.3-.3.3-.4.6-.5 1.1l-2.1 9.8v.6c0 .5.4.8 1.4.8h.2l-.2.8H8l.2-.8h.2c1.1 0 1.8-.5 2-1.5l2-9.8.1-.5c0-.6-.4-.8-1.4-.8h-.3l.2-.9h5.8Z\" fill-rule=\"evenodd\"></path></svg>',\n shortcut: 'Mod-i'\n }\n ],\n \n commands: {\n toggleItalic\n },\n \n keymap: {\n 'Mod-i': 'toggleItalic',\n 'Mod-I': 'toggleItalic'\n }\n});\n"],"names":["toggleItalic","registerCommand","command","handler","_a","initializeCommands","ItalicPlugin"],"mappings":"AAgBO,MAAMA,IAAe,OAC1B,SAAS,YAAY,UAAU,EAAK,GAC7B,KAMHC,IAAkB,CAACC,GAAiBC,MAA8B;AARjE,MAAAC;AASL,EAAI,OAAO,UAAW,iBACnBA,IAAA,OAAe,0BAAf,QAAAA,EAAA,aAAuCF,GAASC;AAErD,GAKME,IAAqB,MAAY;AACrC,EAAAJ,EAAgB,gBAAgBD,CAAY;AAC9C;AAGI,OAAO,UAAW,gBAChB,SAAS,eAAe,YAC1B,SAAS,iBAAiB,oBAAoBK,CAAkB,IAEhEA,EAAA;AAIG,MAAMC,IAAe,OAAe;AAAA,EACzC,MAAM;AAAA,EAEN,OAAO;AAAA,IACL,QAAQ;AAAA,MACN,UAAU;AAAA,QACR,EAAE,KAAK,IAAA;AAAA,QACP,EAAE,KAAK,KAAA;AAAA,QACP;AAAA,UACE,OAAO;AAAA,QAAA;AAAA,MACT;AAAA,MAEF,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,EACZ;AAAA,EAGF,UAAU;AAAA,IACR,cAAAN;AAAA,EAAA;AAAA,EAGF,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,EAAA;AAEb;"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
const o = [
|
|
2
|
+
{ label: "1.0", value: "1.0" },
|
|
3
|
+
{ label: "1.15", value: "1.15" },
|
|
4
|
+
{ label: "1.5", value: "1.5" },
|
|
5
|
+
{ label: "2.0", value: "2.0" },
|
|
6
|
+
{ label: "2.5", value: "2.5" },
|
|
7
|
+
{ label: "3.0", value: "3.0" }
|
|
8
|
+
], s = (t) => {
|
|
9
|
+
let e = t;
|
|
10
|
+
const n = ["P", "DIV", "H1", "H2", "H3", "H4", "H5", "H6", "LI", "BLOCKQUOTE", "PRE"];
|
|
11
|
+
for (; e; ) {
|
|
12
|
+
if (e.nodeType === Node.ELEMENT_NODE) {
|
|
13
|
+
const l = e;
|
|
14
|
+
if (n.includes(l.tagName))
|
|
15
|
+
return l;
|
|
16
|
+
}
|
|
17
|
+
e = e.parentNode;
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}, i = (t) => {
|
|
21
|
+
if (!t) return !1;
|
|
22
|
+
try {
|
|
23
|
+
const e = window.getSelection();
|
|
24
|
+
if (!e || e.rangeCount === 0) return !1;
|
|
25
|
+
const n = e.getRangeAt(0), l = s(n.commonAncestorContainer);
|
|
26
|
+
return l ? (l.style.lineHeight = t, !0) : !1;
|
|
27
|
+
} catch (e) {
|
|
28
|
+
return console.error("Failed to set line height:", e), !1;
|
|
29
|
+
}
|
|
30
|
+
}, r = (t, e) => {
|
|
31
|
+
var n;
|
|
32
|
+
typeof window != "undefined" && ((n = window.registerEditorCommand) == null || n.call(window, t, e));
|
|
33
|
+
}, a = () => {
|
|
34
|
+
r("setLineHeight", i);
|
|
35
|
+
};
|
|
36
|
+
typeof window != "undefined" && (document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", a) : a());
|
|
37
|
+
const c = () => ({
|
|
38
|
+
name: "lineHeight",
|
|
39
|
+
marks: {
|
|
40
|
+
lineHeight: {
|
|
41
|
+
attrs: {
|
|
42
|
+
height: { default: null }
|
|
43
|
+
},
|
|
44
|
+
parseDOM: [
|
|
45
|
+
{
|
|
46
|
+
tag: 'span[style*="line-height"]',
|
|
47
|
+
getAttrs: (t) => {
|
|
48
|
+
const n = t.style.lineHeight;
|
|
49
|
+
return n ? { height: n } : !1;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
toDOM: (t) => ["span", { style: `line-height: ${t.attrs.height}` }, 0]
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
toolbar: [
|
|
57
|
+
{
|
|
58
|
+
label: "Line Height",
|
|
59
|
+
command: "setLineHeight",
|
|
60
|
+
type: "inline-menu",
|
|
61
|
+
options: o,
|
|
62
|
+
icon: '<svg width="24" height="24" focusable="false"><path d="M21 5a1 1 0 0 1 .1 2H13a1 1 0 0 1-.1-2H21zm0 4a1 1 0 0 1 .1 2H13a1 1 0 0 1-.1-2H21zm0 4a1 1 0 0 1 .1 2H13a1 1 0 0 1-.1-2H21zm0 4a1 1 0 0 1 .1 2H13a1 1 0 0 1-.1-2H21zM7 3.6l3.7 3.7a1 1 0 0 1-1.3 1.5h-.1L8 7.3v9.2l1.3-1.3a1 1 0 0 1 1.3 0h.1c.4.4.4 1 0 1.3v.1L7 20.4l-3.7-3.7a1 1 0 0 1 1.3-1.5h.1L6 16.7V7.4L4.7 8.7a1 1 0 0 1-1.3 0h-.1a1 1 0 0 1 0-1.3v-.1L7 3.6z"></path></svg>'
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
commands: {
|
|
66
|
+
setLineHeight: i
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
export {
|
|
70
|
+
c as LineHeightPlugin,
|
|
71
|
+
i as setLineHeight
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=LineHeightPlugin.native-CWQT2FIa.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LineHeightPlugin.native-CWQT2FIa.mjs","sources":["../../plugins/line-height/src/LineHeightPlugin.native.ts"],"sourcesContent":["import type { Plugin } from '@editora/core';\n\n/**\n * LineHeight Plugin - Native Implementation\n * Author: Ajay Kumar <ajaykr089@gmail.com>\n * \n * Provides line height formatting with:\n * - Inline menu dropdown with predefined values\n * - Applies to entire paragraph or selected block\n * - Smart unit handling (numeric values)\n * - Current value detection and display\n */\n\n/**\n * Predefined line height options\n */\nconst lineHeights = [\n { label: '1.0', value: '1.0' },\n { label: '1.15', value: '1.15' },\n { label: '1.5', value: '1.5' },\n { label: '2.0', value: '2.0' },\n { label: '2.5', value: '2.5' },\n { label: '3.0', value: '3.0' }\n];\n\n/**\n * Find the containing block element for line height\n */\nconst findBlockElement = (node: Node): HTMLElement | null => {\n let current: Node | null = node;\n\n // Block-level elements that can have line-height\n const blockElements = ['P', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'LI', 'BLOCKQUOTE', 'PRE'];\n\n while (current) {\n if (current.nodeType === Node.ELEMENT_NODE) {\n const element = current as HTMLElement;\n if (blockElements.includes(element.tagName)) {\n return element;\n }\n }\n current = current.parentNode;\n }\n\n return null;\n};\n\n/**\n * Get current line height value\n */\nconst getCurrentLineHeight = (): string => {\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return '1.5';\n\n const range = selection.getRangeAt(0);\n const element = findBlockElement(range.commonAncestorContainer);\n\n if (element) {\n const lineHeight = window.getComputedStyle(element).lineHeight;\n if (lineHeight && lineHeight !== 'normal') {\n // Convert px to numeric if needed\n const fontSize = window.getComputedStyle(element).fontSize;\n if (fontSize && lineHeight.endsWith('px')) {\n const lh = parseFloat(lineHeight);\n const fs = parseFloat(fontSize);\n return (lh / fs).toFixed(2);\n }\n return lineHeight;\n }\n }\n\n return '1.5';\n};\n\n/**\n * Set line height on selected block element\n */\nexport const setLineHeight = (height?: string): boolean => {\n if (!height) return false;\n\n try {\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return false;\n\n const range = selection.getRangeAt(0);\n const element = findBlockElement(range.commonAncestorContainer);\n\n if (element) {\n element.style.lineHeight = height;\n return true;\n }\n\n return false;\n } catch (error) {\n console.error('Failed to set line height:', error);\n return false;\n }\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('setLineHeight', setLineHeight);\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 LineHeightPlugin = (): Plugin => ({\n name: 'lineHeight',\n\n marks: {\n lineHeight: {\n attrs: {\n height: { default: null }\n },\n parseDOM: [\n {\n tag: 'span[style*=\"line-height\"]',\n getAttrs: (dom) => {\n const element = dom as HTMLElement;\n const height = element.style.lineHeight;\n return height ? { height } : false;\n }\n }\n ],\n toDOM: (mark) => {\n return ['span', { style: `line-height: ${mark.attrs.height}` }, 0];\n }\n }\n },\n\n toolbar: [\n {\n label: 'Line Height',\n command: 'setLineHeight',\n type: 'inline-menu',\n options: lineHeights,\n icon: '<svg width=\"24\" height=\"24\" focusable=\"false\"><path d=\"M21 5a1 1 0 0 1 .1 2H13a1 1 0 0 1-.1-2H21zm0 4a1 1 0 0 1 .1 2H13a1 1 0 0 1-.1-2H21zm0 4a1 1 0 0 1 .1 2H13a1 1 0 0 1-.1-2H21zm0 4a1 1 0 0 1 .1 2H13a1 1 0 0 1-.1-2H21zM7 3.6l3.7 3.7a1 1 0 0 1-1.3 1.5h-.1L8 7.3v9.2l1.3-1.3a1 1 0 0 1 1.3 0h.1c.4.4.4 1 0 1.3v.1L7 20.4l-3.7-3.7a1 1 0 0 1 1.3-1.5h.1L6 16.7V7.4L4.7 8.7a1 1 0 0 1-1.3 0h-.1a1 1 0 0 1 0-1.3v-.1L7 3.6z\"></path></svg>'\n }\n ],\n\n commands: {\n setLineHeight\n }\n});\n"],"names":["lineHeights","findBlockElement","node","current","blockElements","element","setLineHeight","height","selection","range","error","registerCommand","command","handler","_a","initializeCommands","LineHeightPlugin","dom","mark"],"mappings":"AAgBA,MAAMA,IAAc;AAAA,EAClB,EAAE,OAAO,OAAO,OAAO,MAAA;AAAA,EACvB,EAAE,OAAO,QAAQ,OAAO,OAAA;AAAA,EACxB,EAAE,OAAO,OAAO,OAAO,MAAA;AAAA,EACvB,EAAE,OAAO,OAAO,OAAO,MAAA;AAAA,EACvB,EAAE,OAAO,OAAO,OAAO,MAAA;AAAA,EACvB,EAAE,OAAO,OAAO,OAAO,MAAA;AACzB,GAKMC,IAAmB,CAACC,MAAmC;AAC3D,MAAIC,IAAuBD;AAG3B,QAAME,IAAgB,CAAC,KAAK,OAAO,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,cAAc,KAAK;AAEhG,SAAOD,KAAS;AACd,QAAIA,EAAQ,aAAa,KAAK,cAAc;AAC1C,YAAME,IAAUF;AAChB,UAAIC,EAAc,SAASC,EAAQ,OAAO;AACxC,eAAOA;AAAA,IAEX;AACA,IAAAF,IAAUA,EAAQ;AAAA,EACpB;AAEA,SAAO;AACT,GAgCaG,IAAgB,CAACC,MAA6B;AACzD,MAAI,CAACA,EAAQ,QAAO;AAEpB,MAAI;AACF,UAAMC,IAAY,OAAO,aAAA;AACzB,QAAI,CAACA,KAAaA,EAAU,eAAe,EAAG,QAAO;AAErD,UAAMC,IAAQD,EAAU,WAAW,CAAC,GAC9BH,IAAUJ,EAAiBQ,EAAM,uBAAuB;AAE9D,WAAIJ,KACFA,EAAQ,MAAM,aAAaE,GACpB,MAGF;AAAA,EACT,SAASG,GAAO;AACd,mBAAQ,MAAM,8BAA8BA,CAAK,GAC1C;AAAA,EACT;AACF,GAKMC,IAAkB,CAACC,GAAiBC,MAA4C;AAtFtF,MAAAC;AAuFE,EAAI,OAAO,UAAW,iBACnBA,IAAA,OAAe,0BAAf,QAAAA,EAAA,aAAuCF,GAASC;AAErD,GAKME,IAAqB,MAAY;AACrC,EAAAJ,EAAgB,iBAAiBL,CAAa;AAChD;AAGI,OAAO,UAAW,gBAChB,SAAS,eAAe,YAC1B,SAAS,iBAAiB,oBAAoBS,CAAkB,IAEhEA,EAAA;AAIG,MAAMC,IAAmB,OAAe;AAAA,EAC7C,MAAM;AAAA,EAEN,OAAO;AAAA,IACL,YAAY;AAAA,MACV,OAAO;AAAA,QACL,QAAQ,EAAE,SAAS,KAAA;AAAA,MAAK;AAAA,MAE1B,UAAU;AAAA,QACR;AAAA,UACE,KAAK;AAAA,UACL,UAAU,CAACC,MAAQ;AAEjB,kBAAMV,IADUU,EACO,MAAM;AAC7B,mBAAOV,IAAS,EAAE,QAAAA,EAAA,IAAW;AAAA,UAC/B;AAAA,QAAA;AAAA,MACF;AAAA,MAEF,OAAO,CAACW,MACC,CAAC,QAAQ,EAAE,OAAO,gBAAgBA,EAAK,MAAM,MAAM,GAAA,GAAM,CAAC;AAAA,IACnE;AAAA,EACF;AAAA,EAGF,SAAS;AAAA,IACP;AAAA,MACE,OAAO;AAAA,MACP,SAAS;AAAA,MACT,MAAM;AAAA,MACN,SAASlB;AAAA,MACT,MAAM;AAAA,IAAA;AAAA,EACR;AAAA,EAGF,UAAU;AAAA,IACR,eAAAM;AAAA,EAAA;AAEJ;"}
|