@editora/code
Advanced tools
| "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const s=require("@editora/light-code-editor"),x='[data-theme="dark"], .dark, .editora-theme-dark',z=`/* Source Editor Dialog Styles */ | ||
| .rte-source-editor-overlay { | ||
| position: fixed !important; | ||
| top: 0 !important; | ||
| left: 0 !important; | ||
| right: 0 !important; | ||
| bottom: 0 !important; | ||
| width: 100vw !important; | ||
| height: 100vh !important; | ||
| background-color: rgba(0, 0, 0, 0.6) !important; | ||
| display: flex !important; | ||
| align-items: center !important; | ||
| justify-content: center !important; | ||
| z-index: 10000 !important; | ||
| padding: 20px !important; | ||
| box-sizing: border-box !important; | ||
| margin: 0 !important; | ||
| } | ||
| .rte-source-editor-overlay.fullscreen { | ||
| padding: 0 !important; | ||
| } | ||
| .rte-source-editor-modal { | ||
| background: white; | ||
| border-radius: 8px; | ||
| box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); | ||
| width: 100%; | ||
| max-width: 1200px; | ||
| max-height: 90vh; | ||
| display: flex; | ||
| flex-direction: column; | ||
| overflow: hidden; | ||
| position: relative; | ||
| } | ||
| .rte-source-editor-overlay.fullscreen .rte-source-editor-modal { | ||
| border-radius: 0; | ||
| max-width: 100%; | ||
| max-height: 100vh; | ||
| width: 100%; | ||
| height: 100vh; | ||
| } | ||
| .rte-source-editor-header { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| padding: 16px 20px; | ||
| border-bottom: 1px solid #e1e5e9; | ||
| background: #f8f9fa; | ||
| border-radius: 8px 8px 0 0; | ||
| } | ||
| .rte-source-editor-overlay.fullscreen .rte-source-editor-header { | ||
| border-radius: 0; | ||
| } | ||
| .rte-source-editor-header h2 { | ||
| margin: 0; | ||
| font-size: 18px; | ||
| font-weight: 600; | ||
| color: #1a1a1a; | ||
| } | ||
| .rte-source-editor-header-toolbar { | ||
| display: flex; | ||
| gap: 8px; | ||
| margin-left: auto; | ||
| margin-right: 16px; | ||
| } | ||
| .rte-source-editor-toolbar-btn { | ||
| background: none; | ||
| border: none; | ||
| cursor: pointer; | ||
| padding: 6px; | ||
| border-radius: 4px; | ||
| font-size: 16px; | ||
| line-height: 1; | ||
| transition: all 0.2s ease; | ||
| color: #666; | ||
| } | ||
| .rte-source-editor-toolbar-btn:hover:not(:disabled) { | ||
| background: #e1e5e9; | ||
| color: #1a1a1a; | ||
| } | ||
| .rte-source-editor-toolbar-btn:disabled { | ||
| opacity: 0.5; | ||
| cursor: not-allowed; | ||
| } | ||
| .rte-source-editor-toolbar-btn.active { | ||
| background: #007acc; | ||
| color: white; | ||
| } | ||
| .rte-source-editor-toolbar-btn.active:hover { | ||
| background: #0056b3; | ||
| } | ||
| .rte-source-editor-header-actions { | ||
| display: flex; | ||
| gap: 8px; | ||
| } | ||
| .rte-source-editor-fullscreen-btn, | ||
| .rte-source-editor-close-btn { | ||
| background: none; | ||
| border: none; | ||
| cursor: pointer; | ||
| padding: 4px; | ||
| border-radius: 4px; | ||
| color: #666; | ||
| font-size: 16px; | ||
| line-height: 1; | ||
| transition: all 0.2s ease; | ||
| } | ||
| .rte-source-editor-fullscreen-btn:hover, | ||
| .rte-source-editor-close-btn:hover { | ||
| background: #e1e5e9; | ||
| color: #1a1a1a; | ||
| } | ||
| .rte-source-editor-body { | ||
| flex: 1; | ||
| overflow: hidden; | ||
| display: flex; | ||
| flex-direction: column; | ||
| } | ||
| .rte-source-editor-loading { | ||
| display: flex; | ||
| flex-direction: column; | ||
| align-items: center; | ||
| justify-content: center; | ||
| padding: 40px; | ||
| color: #666; | ||
| position: absolute; | ||
| z-index: 9; | ||
| margin: 0 auto; | ||
| width: 100%; | ||
| top: 44%; | ||
| } | ||
| .rte-source-editor-spinner { | ||
| width: 32px; | ||
| height: 32px; | ||
| border: 3px solid #e1e5e9; | ||
| border-top: 3px solid #007acc; | ||
| border-radius: 50%; | ||
| animation: spin 1s linear infinite; | ||
| margin-bottom: 16px; | ||
| } | ||
| @keyframes spin { | ||
| 0% { transform: rotate(0deg); } | ||
| 100% { transform: rotate(360deg); } | ||
| } | ||
| .rte-source-editor-error { | ||
| background: #fee; | ||
| color: #c53030; | ||
| padding: 12px 16px; | ||
| border-left: 4px solid #c53030; | ||
| margin: 16px; | ||
| border-radius: 4px; | ||
| font-size: 14px; | ||
| } | ||
| .rte-source-editor-content { | ||
| flex: 1; | ||
| display: flex; | ||
| flex-direction: column; | ||
| overflow: hidden; | ||
| } | ||
| .rte-source-editor-warning { | ||
| background: #fefcbf; | ||
| color: #744210; | ||
| padding: 8px 16px; | ||
| font-size: 12px; | ||
| font-weight: 500; | ||
| border-bottom: 1px solid #f6e05e; | ||
| } | ||
| .rte-source-editor-codemirror { | ||
| flex: 1; | ||
| overflow: auto; | ||
| font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; | ||
| font-size: 14px; | ||
| line-height: 1.5; | ||
| } | ||
| .rte-source-editor-codemirror .cm-editor { | ||
| height: 100%; | ||
| } | ||
| .rte-source-editor-codemirror .cm-focused { | ||
| outline: none; | ||
| } | ||
| .rte-source-editor-footer { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| padding: 16px 20px; | ||
| border-top: 1px solid #e1e5e9; | ||
| background: #f8f9fa; | ||
| border-radius: 0 0 8px 8px; | ||
| } | ||
| .rte-source-editor-overlay.fullscreen .rte-source-editor-footer { | ||
| border-radius: 0; | ||
| } | ||
| .rte-source-editor-footer-info { | ||
| font-size: 12px; | ||
| color: #666; | ||
| } | ||
| .unsaved-changes { | ||
| color: #d69e2e; | ||
| font-weight: 500; | ||
| } | ||
| .rte-source-editor-footer-actions { | ||
| display: flex; | ||
| gap: 12px; | ||
| } | ||
| .rte-source-editor-btn { | ||
| padding: 8px 16px; | ||
| border-radius: 4px; | ||
| font-size: 14px; | ||
| font-weight: 500; | ||
| cursor: pointer; | ||
| border: 1px solid transparent; | ||
| transition: all 0.2s ease; | ||
| } | ||
| .rte-source-editor-btn:disabled { | ||
| opacity: 0.6; | ||
| cursor: not-allowed; | ||
| } | ||
| .rte-source-editor-btn-cancel { | ||
| background: white; | ||
| border-color: #d1d5db; | ||
| color: #374151; | ||
| } | ||
| .rte-source-editor-btn-cancel:hover:not(:disabled) { | ||
| background: #f9fafb; | ||
| border-color: #9ca3af; | ||
| } | ||
| .rte-source-editor-btn-save { | ||
| background: #007acc; | ||
| color: white; | ||
| } | ||
| .rte-source-editor-btn-save:hover:not(:disabled) { | ||
| background: #0056b3; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-modal { | ||
| background: #1e1e1e; | ||
| color: #f8f9fa; | ||
| border: 1px solid #434d5f; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-header, | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-footer { | ||
| background: #2a3442; | ||
| border-color: #434d5f; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-header h2 { | ||
| color: #f8f9fa; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-toolbar-btn, | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-fullscreen-btn, | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-close-btn { | ||
| color: #c1cede; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-toolbar-btn:hover:not(:disabled), | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-fullscreen-btn:hover, | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-close-btn:hover { | ||
| background: #404a5a; | ||
| color: #f8fafc; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-toolbar-btn.active { | ||
| background: #3b82f6; | ||
| color: #ffffff; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-toolbar-btn.active:hover { | ||
| background: #2563eb; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-loading, | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-footer-info { | ||
| color: #cbd5e1; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-spinner { | ||
| border-color: #3f4b60; | ||
| border-top-color: #58a6ff; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-error { | ||
| background: #3f2124; | ||
| color: #fecaca; | ||
| border-color: #ef4444; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-warning { | ||
| background: #3b3220; | ||
| color: #fde68a; | ||
| border-color: #f59e0b; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-btn-cancel { | ||
| background: #334155; | ||
| border-color: #475569; | ||
| color: #f1f5f9; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-btn-cancel:hover:not(:disabled) { | ||
| background: #475569; | ||
| border-color: #64748b; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-btn-save { | ||
| background: #3b82f6; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-btn-save:hover:not(:disabled) { | ||
| background: #2563eb; | ||
| } | ||
| /* Responsive design */ | ||
| @media (max-width: 768px) { | ||
| .rte-source-editor-overlay { | ||
| padding: 10px; | ||
| } | ||
| .rte-source-editor-modal { | ||
| max-height: 95vh; | ||
| } | ||
| .rte-source-editor-header { | ||
| padding: 12px 16px; | ||
| } | ||
| .rte-source-editor-footer { | ||
| padding: 12px 16px; | ||
| flex-direction: column; | ||
| gap: 12px; | ||
| align-items: stretch; | ||
| } | ||
| .rte-source-editor-footer-actions { | ||
| justify-content: stretch; | ||
| } | ||
| .rte-source-editor-btn { | ||
| flex: 1; | ||
| text-align: center; | ||
| } | ||
| }`,q=()=>({name:"code",toolbar:[{label:"Source",command:"toggleSourceView",icon:'<svg width="24" height="24" focusable="false"><g fill-rule="nonzero"><path d="M9.8 15.7c.3.3.3.8 0 1-.3.4-.9.4-1.2 0l-4.4-4.1a.8.8 0 0 1 0-1.2l4.4-4.2c.3-.3.9-.3 1.2 0 .3.3.3.8 0 1.1L6 12l3.8 3.7ZM14.2 15.7c-.3.3-.3.8 0 1 .4.4.9.4 1.2 0l4.4-4.1c.3-.3.3-.9 0-1.2l-4.4-4.2a.8.8 0 0 0-1.2 0c-.3.3-.3.8 0 1.1L18 12l-3.8 3.7Z"></path></g></svg>',shortcut:"Mod-Shift-S"}],commands:{toggleSourceView:()=>{const l=(()=>{const r=window.getSelection();if(r&&r.anchorNode){let e=r.anchorNode instanceof HTMLElement?r.anchorNode:r.anchorNode.parentElement;for(;e;){if(e.classList?.contains("rte-content"))return e;e=e.parentElement}}if(document.activeElement){let e=document.activeElement;if(e.classList?.contains("rte-content"))return e;for(;e&&e!==document.body;){if(e.classList?.contains("rte-content"))return e;const n=e.querySelector(".rte-content");if(n)return n;e=e.parentElement}}const o=document.querySelector("[data-editora-editor]");if(o){const e=o.querySelector(".rte-content");if(e)return e}return document.querySelector(".rte-content")})();if(!l)return console.error("[CodePlugin] Editor content area not found"),alert("Editor content area not found. Please click inside the editor first."),!1;const y=l.innerHTML,k=r=>{let o="",e=0;const n=2,u=r.split(/(<\/?[a-zA-Z][^>]*>)/);for(const i of u)i.trim()&&(i.match(/^<\/[a-zA-Z]/)?(e=Math.max(0,e-1),o+=` | ||
| `+" ".repeat(e*n)+i):i.match(/^<[a-zA-Z]/)&&!i.match(/\/>$/)?(o+=` | ||
| `+" ".repeat(e*n)+i,e++):i.match(/^<[a-zA-Z].*\/>$/)?o+=` | ||
| `+" ".repeat(e*n)+i:o+=i.trim());return o.trim()};return(()=>{let r=null,o="dark",e=!1,n=!1,u=!1;const i=y,E=!!l.closest(x)||document.body.matches(x)||document.documentElement.matches(x),a=document.createElement("div");a.className="rte-source-editor-overlay",E&&a.classList.add("rte-theme-dark");const c=document.createElement("div");c.className="rte-source-editor-modal",c.setAttribute("role","dialog"),c.setAttribute("aria-modal","true"),c.setAttribute("aria-labelledby","source-editor-title");const d=document.createElement("div");d.className="rte-source-editor-header",d.innerHTML=` | ||
| <h2 id="source-editor-title">Source Editor</h2> | ||
| <div class="rte-source-editor-header-toolbar"> | ||
| <button class="rte-source-editor-toolbar-btn theme-toggle-btn" title="Switch theme"> | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <circle cx="12" cy="12" r="5"/> | ||
| <line x1="12" y1="1" x2="12" y2="3"/> | ||
| <line x1="12" y1="21" x2="12" y2="23"/> | ||
| <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/> | ||
| <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/> | ||
| <line x1="1" y1="12" x2="3" y2="12"/> | ||
| <line x1="21" y1="12" x2="23" y2="12"/> | ||
| <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/> | ||
| <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/> | ||
| </svg> | ||
| </button> | ||
| <button class="rte-source-editor-toolbar-btn readonly-toggle-btn" title="Toggle read-only"> | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/> | ||
| <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/> | ||
| </svg> | ||
| </button> | ||
| </div> | ||
| <div class="rte-source-editor-header-actions"> | ||
| <button class="rte-source-editor-fullscreen-btn" title="Toggle fullscreen"> | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"/> | ||
| </svg> | ||
| </button> | ||
| <button class="rte-source-editor-close-btn" aria-label="Close source editor"> | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <line x1="18" y1="6" x2="6" y2="18"/> | ||
| <line x1="6" y1="6" x2="18" y2="18"/> | ||
| </svg> | ||
| </button> | ||
| </div> | ||
| `;const p=document.createElement("div");p.className="rte-source-editor-body";const m=document.createElement("div");m.className="rte-source-editor-content";const v=document.createElement("div");v.className="rte-source-editor-warning",v.textContent="⚠️ Advanced users only. Invalid HTML may break the editor.";const h=document.createElement("div");h.className="rte-source-editor-light-editor",h.style.height="400px",m.appendChild(v),m.appendChild(h),p.appendChild(m);const b=document.createElement("div");if(b.className="rte-source-editor-footer",b.innerHTML=` | ||
| <div class="rte-source-editor-footer-info"> | ||
| <span class="unsaved-changes" style="display: none;">• Unsaved changes</span> | ||
| </div> | ||
| <div class="rte-source-editor-footer-actions"> | ||
| <button class="rte-source-editor-btn rte-source-editor-btn-cancel">Cancel</button> | ||
| <button class="rte-source-editor-btn rte-source-editor-btn-save">Save</button> | ||
| </div> | ||
| `,c.appendChild(d),c.appendChild(p),c.appendChild(b),a.appendChild(c),!document.getElementById("rte-source-editor-styles")){const t=document.createElement("style");t.id="rte-source-editor-styles",t.textContent=z,document.head.appendChild(t)}document.body.appendChild(a);try{r=s.createEditor(h,{value:k(y),theme:"dark",readOnly:!1,extensions:[new s.LineNumbersExtension,new s.ThemeExtension,new s.ReadOnlyExtension,new s.BracketMatchingExtension,new s.SearchExtension,new s.CodeFoldingExtension,new s.SyntaxHighlightingExtension]}),r.on("change",()=>{u=(r?.getValue()||"")!==k(i);const f=b.querySelector(".unsaved-changes");f&&(f.style.display=u?"inline":"none")}),setTimeout(()=>r?.focus(),100)}catch(t){console.error("Failed to initialize code editor:",t)}const M=()=>{o=o==="dark"?"light":"dark",r?.setTheme(o);const t=d.querySelector(".theme-toggle-btn");t&&o==="light"&&(t.innerHTML=` | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/> | ||
| </svg> | ||
| `)},S=()=>{e=!e,r?.setReadOnly(e);const t=d.querySelector(".readonly-toggle-btn");t&&(e?(t.classList.add("active"),t.innerHTML=` | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <rect x="3" y="11" width="18" height="11" rx="2" ry="2"/> | ||
| <circle cx="12" cy="16" r="1"/> | ||
| <path d="M7 11V7a5 5 0 0 1 10 0v4"/> | ||
| </svg> | ||
| `):(t.classList.remove("active"),t.innerHTML=` | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/> | ||
| <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/> | ||
| </svg> | ||
| `))},C=()=>{n=!n,n?(a.classList.add("fullscreen"),h.style.height="calc(100vh - 200px)"):(a.classList.remove("fullscreen"),h.style.height="400px");const t=d.querySelector(".rte-source-editor-fullscreen-btn");t&&(t.innerHTML=n?` | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 0 2-2h3M3 16h3a2 2 0 0 0 2 2v3"/> | ||
| </svg> | ||
| `:` | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"/> | ||
| </svg> | ||
| `)},g=()=>{r&&(r.destroy(),r=null),document.body.removeChild(a)},L=()=>{u&&!confirm("You have unsaved changes. Are you sure you want to cancel?")||g()},T=()=>{try{const t=r?.getValue()||"",f=document.createElement("div");f.innerHTML=t,f.querySelectorAll('script, iframe[src^="javascript:"], object, embed').forEach(H=>H.remove()),l.innerHTML=f.innerHTML;try{l.dispatchEvent(new InputEvent("input",{bubbles:!0,cancelable:!1,inputType:"insertReplacementText"}))}catch{l.dispatchEvent(new Event("input",{bubbles:!0}))}l.dispatchEvent(new Event("change",{bubbles:!0})),u=!1,g()}catch(t){alert("Failed to update HTML. Please check your syntax."),console.error("HTML update error:",t)}};d.querySelector(".theme-toggle-btn")?.addEventListener("click",M),d.querySelector(".readonly-toggle-btn")?.addEventListener("click",S),d.querySelector(".rte-source-editor-fullscreen-btn")?.addEventListener("click",C),d.querySelector(".rte-source-editor-close-btn")?.addEventListener("click",g),b.querySelector(".rte-source-editor-btn-cancel")?.addEventListener("click",L),b.querySelector(".rte-source-editor-btn-save")?.addEventListener("click",T),a.addEventListener("click",t=>{t.target===a&&g()});const w=t=>{t.key==="Escape"&&(g(),document.removeEventListener("keydown",w))};document.addEventListener("keydown",w)})(),!0}},keymap:{"Mod-Shift-s":"toggleSourceView","Mod-Shift-S":"toggleSourceView"}});exports.CodePlugin=q; |
| import { createEditor as H, LineNumbersExtension as z, ThemeExtension as q, ReadOnlyExtension as B, BracketMatchingExtension as N, SearchExtension as A, CodeFoldingExtension as R, SyntaxHighlightingExtension as D } from "@editora/light-code-editor"; | ||
| const v = '[data-theme="dark"], .dark, .editora-theme-dark', O = `/* Source Editor Dialog Styles */ | ||
| .rte-source-editor-overlay { | ||
| position: fixed !important; | ||
| top: 0 !important; | ||
| left: 0 !important; | ||
| right: 0 !important; | ||
| bottom: 0 !important; | ||
| width: 100vw !important; | ||
| height: 100vh !important; | ||
| background-color: rgba(0, 0, 0, 0.6) !important; | ||
| display: flex !important; | ||
| align-items: center !important; | ||
| justify-content: center !important; | ||
| z-index: 10000 !important; | ||
| padding: 20px !important; | ||
| box-sizing: border-box !important; | ||
| margin: 0 !important; | ||
| } | ||
| .rte-source-editor-overlay.fullscreen { | ||
| padding: 0 !important; | ||
| } | ||
| .rte-source-editor-modal { | ||
| background: white; | ||
| border-radius: 8px; | ||
| box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); | ||
| width: 100%; | ||
| max-width: 1200px; | ||
| max-height: 90vh; | ||
| display: flex; | ||
| flex-direction: column; | ||
| overflow: hidden; | ||
| position: relative; | ||
| } | ||
| .rte-source-editor-overlay.fullscreen .rte-source-editor-modal { | ||
| border-radius: 0; | ||
| max-width: 100%; | ||
| max-height: 100vh; | ||
| width: 100%; | ||
| height: 100vh; | ||
| } | ||
| .rte-source-editor-header { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| padding: 16px 20px; | ||
| border-bottom: 1px solid #e1e5e9; | ||
| background: #f8f9fa; | ||
| border-radius: 8px 8px 0 0; | ||
| } | ||
| .rte-source-editor-overlay.fullscreen .rte-source-editor-header { | ||
| border-radius: 0; | ||
| } | ||
| .rte-source-editor-header h2 { | ||
| margin: 0; | ||
| font-size: 18px; | ||
| font-weight: 600; | ||
| color: #1a1a1a; | ||
| } | ||
| .rte-source-editor-header-toolbar { | ||
| display: flex; | ||
| gap: 8px; | ||
| margin-left: auto; | ||
| margin-right: 16px; | ||
| } | ||
| .rte-source-editor-toolbar-btn { | ||
| background: none; | ||
| border: none; | ||
| cursor: pointer; | ||
| padding: 6px; | ||
| border-radius: 4px; | ||
| font-size: 16px; | ||
| line-height: 1; | ||
| transition: all 0.2s ease; | ||
| color: #666; | ||
| } | ||
| .rte-source-editor-toolbar-btn:hover:not(:disabled) { | ||
| background: #e1e5e9; | ||
| color: #1a1a1a; | ||
| } | ||
| .rte-source-editor-toolbar-btn:disabled { | ||
| opacity: 0.5; | ||
| cursor: not-allowed; | ||
| } | ||
| .rte-source-editor-toolbar-btn.active { | ||
| background: #007acc; | ||
| color: white; | ||
| } | ||
| .rte-source-editor-toolbar-btn.active:hover { | ||
| background: #0056b3; | ||
| } | ||
| .rte-source-editor-header-actions { | ||
| display: flex; | ||
| gap: 8px; | ||
| } | ||
| .rte-source-editor-fullscreen-btn, | ||
| .rte-source-editor-close-btn { | ||
| background: none; | ||
| border: none; | ||
| cursor: pointer; | ||
| padding: 4px; | ||
| border-radius: 4px; | ||
| color: #666; | ||
| font-size: 16px; | ||
| line-height: 1; | ||
| transition: all 0.2s ease; | ||
| } | ||
| .rte-source-editor-fullscreen-btn:hover, | ||
| .rte-source-editor-close-btn:hover { | ||
| background: #e1e5e9; | ||
| color: #1a1a1a; | ||
| } | ||
| .rte-source-editor-body { | ||
| flex: 1; | ||
| overflow: hidden; | ||
| display: flex; | ||
| flex-direction: column; | ||
| } | ||
| .rte-source-editor-loading { | ||
| display: flex; | ||
| flex-direction: column; | ||
| align-items: center; | ||
| justify-content: center; | ||
| padding: 40px; | ||
| color: #666; | ||
| position: absolute; | ||
| z-index: 9; | ||
| margin: 0 auto; | ||
| width: 100%; | ||
| top: 44%; | ||
| } | ||
| .rte-source-editor-spinner { | ||
| width: 32px; | ||
| height: 32px; | ||
| border: 3px solid #e1e5e9; | ||
| border-top: 3px solid #007acc; | ||
| border-radius: 50%; | ||
| animation: spin 1s linear infinite; | ||
| margin-bottom: 16px; | ||
| } | ||
| @keyframes spin { | ||
| 0% { transform: rotate(0deg); } | ||
| 100% { transform: rotate(360deg); } | ||
| } | ||
| .rte-source-editor-error { | ||
| background: #fee; | ||
| color: #c53030; | ||
| padding: 12px 16px; | ||
| border-left: 4px solid #c53030; | ||
| margin: 16px; | ||
| border-radius: 4px; | ||
| font-size: 14px; | ||
| } | ||
| .rte-source-editor-content { | ||
| flex: 1; | ||
| display: flex; | ||
| flex-direction: column; | ||
| overflow: hidden; | ||
| } | ||
| .rte-source-editor-warning { | ||
| background: #fefcbf; | ||
| color: #744210; | ||
| padding: 8px 16px; | ||
| font-size: 12px; | ||
| font-weight: 500; | ||
| border-bottom: 1px solid #f6e05e; | ||
| } | ||
| .rte-source-editor-codemirror { | ||
| flex: 1; | ||
| overflow: auto; | ||
| font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; | ||
| font-size: 14px; | ||
| line-height: 1.5; | ||
| } | ||
| .rte-source-editor-codemirror .cm-editor { | ||
| height: 100%; | ||
| } | ||
| .rte-source-editor-codemirror .cm-focused { | ||
| outline: none; | ||
| } | ||
| .rte-source-editor-footer { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| padding: 16px 20px; | ||
| border-top: 1px solid #e1e5e9; | ||
| background: #f8f9fa; | ||
| border-radius: 0 0 8px 8px; | ||
| } | ||
| .rte-source-editor-overlay.fullscreen .rte-source-editor-footer { | ||
| border-radius: 0; | ||
| } | ||
| .rte-source-editor-footer-info { | ||
| font-size: 12px; | ||
| color: #666; | ||
| } | ||
| .unsaved-changes { | ||
| color: #d69e2e; | ||
| font-weight: 500; | ||
| } | ||
| .rte-source-editor-footer-actions { | ||
| display: flex; | ||
| gap: 12px; | ||
| } | ||
| .rte-source-editor-btn { | ||
| padding: 8px 16px; | ||
| border-radius: 4px; | ||
| font-size: 14px; | ||
| font-weight: 500; | ||
| cursor: pointer; | ||
| border: 1px solid transparent; | ||
| transition: all 0.2s ease; | ||
| } | ||
| .rte-source-editor-btn:disabled { | ||
| opacity: 0.6; | ||
| cursor: not-allowed; | ||
| } | ||
| .rte-source-editor-btn-cancel { | ||
| background: white; | ||
| border-color: #d1d5db; | ||
| color: #374151; | ||
| } | ||
| .rte-source-editor-btn-cancel:hover:not(:disabled) { | ||
| background: #f9fafb; | ||
| border-color: #9ca3af; | ||
| } | ||
| .rte-source-editor-btn-save { | ||
| background: #007acc; | ||
| color: white; | ||
| } | ||
| .rte-source-editor-btn-save:hover:not(:disabled) { | ||
| background: #0056b3; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-modal { | ||
| background: #1e1e1e; | ||
| color: #f8f9fa; | ||
| border: 1px solid #434d5f; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-header, | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-footer { | ||
| background: #2a3442; | ||
| border-color: #434d5f; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-header h2 { | ||
| color: #f8f9fa; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-toolbar-btn, | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-fullscreen-btn, | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-close-btn { | ||
| color: #c1cede; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-toolbar-btn:hover:not(:disabled), | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-fullscreen-btn:hover, | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-close-btn:hover { | ||
| background: #404a5a; | ||
| color: #f8fafc; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-toolbar-btn.active { | ||
| background: #3b82f6; | ||
| color: #ffffff; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-toolbar-btn.active:hover { | ||
| background: #2563eb; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-loading, | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-footer-info { | ||
| color: #cbd5e1; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-spinner { | ||
| border-color: #3f4b60; | ||
| border-top-color: #58a6ff; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-error { | ||
| background: #3f2124; | ||
| color: #fecaca; | ||
| border-color: #ef4444; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-warning { | ||
| background: #3b3220; | ||
| color: #fde68a; | ||
| border-color: #f59e0b; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-btn-cancel { | ||
| background: #334155; | ||
| border-color: #475569; | ||
| color: #f1f5f9; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-btn-cancel:hover:not(:disabled) { | ||
| background: #475569; | ||
| border-color: #64748b; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-btn-save { | ||
| background: #3b82f6; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-btn-save:hover:not(:disabled) { | ||
| background: #2563eb; | ||
| } | ||
| /* Responsive design */ | ||
| @media (max-width: 768px) { | ||
| .rte-source-editor-overlay { | ||
| padding: 10px; | ||
| } | ||
| .rte-source-editor-modal { | ||
| max-height: 95vh; | ||
| } | ||
| .rte-source-editor-header { | ||
| padding: 12px 16px; | ||
| } | ||
| .rte-source-editor-footer { | ||
| padding: 12px 16px; | ||
| flex-direction: column; | ||
| gap: 12px; | ||
| align-items: stretch; | ||
| } | ||
| .rte-source-editor-footer-actions { | ||
| justify-content: stretch; | ||
| } | ||
| .rte-source-editor-btn { | ||
| flex: 1; | ||
| text-align: center; | ||
| } | ||
| }`, I = () => ({ | ||
| name: "code", | ||
| // Toolbar button configuration | ||
| toolbar: [ | ||
| { | ||
| label: "Source", | ||
| command: "toggleSourceView", | ||
| // type: "button", | ||
| icon: '<svg width="24" height="24" focusable="false"><g fill-rule="nonzero"><path d="M9.8 15.7c.3.3.3.8 0 1-.3.4-.9.4-1.2 0l-4.4-4.1a.8.8 0 0 1 0-1.2l4.4-4.2c.3-.3.9-.3 1.2 0 .3.3.3.8 0 1.1L6 12l3.8 3.7ZM14.2 15.7c-.3.3-.3.8 0 1 .4.4.9.4 1.2 0l4.4-4.1c.3-.3.3-.9 0-1.2l-4.4-4.2a.8.8 0 0 0-1.2 0c-.3.3-.3.8 0 1.1L18 12l-3.8 3.7Z"></path></g></svg>', | ||
| shortcut: "Mod-Shift-S" | ||
| } | ||
| ], | ||
| // Native command implementations | ||
| commands: { | ||
| /** | ||
| * Toggle HTML source view | ||
| * Opens a dialog to edit raw HTML | ||
| */ | ||
| toggleSourceView: () => { | ||
| const s = (() => { | ||
| const r = window.getSelection(); | ||
| if (r && r.anchorNode) { | ||
| let e = r.anchorNode instanceof HTMLElement ? r.anchorNode : r.anchorNode.parentElement; | ||
| for (; e; ) { | ||
| if (e.classList?.contains("rte-content")) | ||
| return e; | ||
| e = e.parentElement; | ||
| } | ||
| } | ||
| if (document.activeElement) { | ||
| let e = document.activeElement; | ||
| if (e.classList?.contains("rte-content")) | ||
| return e; | ||
| for (; e && e !== document.body; ) { | ||
| if (e.classList?.contains("rte-content")) | ||
| return e; | ||
| const n = e.querySelector( | ||
| ".rte-content" | ||
| ); | ||
| if (n) return n; | ||
| e = e.parentElement; | ||
| } | ||
| } | ||
| const o = document.querySelector("[data-editora-editor]"); | ||
| if (o) { | ||
| const e = o.querySelector( | ||
| ".rte-content" | ||
| ); | ||
| if (e) return e; | ||
| } | ||
| return document.querySelector(".rte-content"); | ||
| })(); | ||
| if (!s) | ||
| return console.error("[CodePlugin] Editor content area not found"), alert( | ||
| "Editor content area not found. Please click inside the editor first." | ||
| ), !1; | ||
| const x = s.innerHTML, y = (r) => { | ||
| let o = "", e = 0; | ||
| const n = 2, l = r.split(/(<\/?[a-zA-Z][^>]*>)/); | ||
| for (const i of l) | ||
| i.trim() && (i.match(/^<\/[a-zA-Z]/) ? (e = Math.max(0, e - 1), o += ` | ||
| ` + " ".repeat(e * n) + i) : i.match(/^<[a-zA-Z]/) && !i.match(/\/>$/) ? (o += ` | ||
| ` + " ".repeat(e * n) + i, e++) : i.match(/^<[a-zA-Z].*\/>$/) ? o += ` | ||
| ` + " ".repeat(e * n) + i : o += i.trim()); | ||
| return o.trim(); | ||
| }; | ||
| return (() => { | ||
| let r = null, o = "dark", e = !1, n = !1, l = !1; | ||
| const i = x, w = !!s.closest(v) || document.body.matches(v) || document.documentElement.matches(v), a = document.createElement("div"); | ||
| a.className = "rte-source-editor-overlay", w && a.classList.add("rte-theme-dark"); | ||
| const c = document.createElement("div"); | ||
| c.className = "rte-source-editor-modal", c.setAttribute("role", "dialog"), c.setAttribute("aria-modal", "true"), c.setAttribute("aria-labelledby", "source-editor-title"); | ||
| const d = document.createElement("div"); | ||
| d.className = "rte-source-editor-header", d.innerHTML = ` | ||
| <h2 id="source-editor-title">Source Editor</h2> | ||
| <div class="rte-source-editor-header-toolbar"> | ||
| <button class="rte-source-editor-toolbar-btn theme-toggle-btn" title="Switch theme"> | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <circle cx="12" cy="12" r="5"/> | ||
| <line x1="12" y1="1" x2="12" y2="3"/> | ||
| <line x1="12" y1="21" x2="12" y2="23"/> | ||
| <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/> | ||
| <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/> | ||
| <line x1="1" y1="12" x2="3" y2="12"/> | ||
| <line x1="21" y1="12" x2="23" y2="12"/> | ||
| <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/> | ||
| <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/> | ||
| </svg> | ||
| </button> | ||
| <button class="rte-source-editor-toolbar-btn readonly-toggle-btn" title="Toggle read-only"> | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/> | ||
| <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/> | ||
| </svg> | ||
| </button> | ||
| </div> | ||
| <div class="rte-source-editor-header-actions"> | ||
| <button class="rte-source-editor-fullscreen-btn" title="Toggle fullscreen"> | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"/> | ||
| </svg> | ||
| </button> | ||
| <button class="rte-source-editor-close-btn" aria-label="Close source editor"> | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <line x1="18" y1="6" x2="6" y2="18"/> | ||
| <line x1="6" y1="6" x2="18" y2="18"/> | ||
| </svg> | ||
| </button> | ||
| </div> | ||
| `; | ||
| const g = document.createElement("div"); | ||
| g.className = "rte-source-editor-body"; | ||
| const m = document.createElement("div"); | ||
| m.className = "rte-source-editor-content"; | ||
| const p = document.createElement("div"); | ||
| p.className = "rte-source-editor-warning", p.textContent = "⚠️ Advanced users only. Invalid HTML may break the editor."; | ||
| const u = document.createElement("div"); | ||
| u.className = "rte-source-editor-light-editor", u.style.height = "400px", m.appendChild(p), m.appendChild(u), g.appendChild(m); | ||
| const h = document.createElement("div"); | ||
| if (h.className = "rte-source-editor-footer", h.innerHTML = ` | ||
| <div class="rte-source-editor-footer-info"> | ||
| <span class="unsaved-changes" style="display: none;">• Unsaved changes</span> | ||
| </div> | ||
| <div class="rte-source-editor-footer-actions"> | ||
| <button class="rte-source-editor-btn rte-source-editor-btn-cancel">Cancel</button> | ||
| <button class="rte-source-editor-btn rte-source-editor-btn-save">Save</button> | ||
| </div> | ||
| `, c.appendChild(d), c.appendChild(g), c.appendChild(h), a.appendChild(c), !document.getElementById("rte-source-editor-styles")) { | ||
| const t = document.createElement("style"); | ||
| t.id = "rte-source-editor-styles", t.textContent = O, document.head.appendChild(t); | ||
| } | ||
| document.body.appendChild(a); | ||
| try { | ||
| r = H(u, { | ||
| value: y(x), | ||
| theme: "dark", | ||
| readOnly: !1, | ||
| extensions: [ | ||
| new z(), | ||
| new q(), | ||
| new B(), | ||
| new N(), | ||
| new A(), | ||
| new R(), | ||
| new D() | ||
| ] | ||
| }), r.on("change", () => { | ||
| l = (r?.getValue() || "") !== y(i); | ||
| const b = h.querySelector( | ||
| ".unsaved-changes" | ||
| ); | ||
| b && (b.style.display = l ? "inline" : "none"); | ||
| }), setTimeout(() => r?.focus(), 100); | ||
| } catch (t) { | ||
| console.error("Failed to initialize code editor:", t); | ||
| } | ||
| const E = () => { | ||
| o = o === "dark" ? "light" : "dark", r?.setTheme(o); | ||
| const t = d.querySelector(".theme-toggle-btn"); | ||
| t && o === "light" && (t.innerHTML = ` | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/> | ||
| </svg> | ||
| `); | ||
| }, M = () => { | ||
| e = !e, r?.setReadOnly(e); | ||
| const t = d.querySelector(".readonly-toggle-btn"); | ||
| t && (e ? (t.classList.add("active"), t.innerHTML = ` | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <rect x="3" y="11" width="18" height="11" rx="2" ry="2"/> | ||
| <circle cx="12" cy="16" r="1"/> | ||
| <path d="M7 11V7a5 5 0 0 1 10 0v4"/> | ||
| </svg> | ||
| `) : (t.classList.remove("active"), t.innerHTML = ` | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/> | ||
| <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/> | ||
| </svg> | ||
| `)); | ||
| }, S = () => { | ||
| n = !n, n ? (a.classList.add("fullscreen"), u.style.height = "calc(100vh - 200px)") : (a.classList.remove("fullscreen"), u.style.height = "400px"); | ||
| const t = d.querySelector( | ||
| ".rte-source-editor-fullscreen-btn" | ||
| ); | ||
| t && (t.innerHTML = n ? ` | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 0 2-2h3M3 16h3a2 2 0 0 0 2 2v3"/> | ||
| </svg> | ||
| ` : ` | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"/> | ||
| </svg> | ||
| `); | ||
| }, f = () => { | ||
| r && (r.destroy(), r = null), document.body.removeChild(a); | ||
| }, L = () => { | ||
| l && !confirm( | ||
| "You have unsaved changes. Are you sure you want to cancel?" | ||
| ) || f(); | ||
| }, C = () => { | ||
| try { | ||
| const t = r?.getValue() || "", b = document.createElement("div"); | ||
| b.innerHTML = t, b.querySelectorAll( | ||
| 'script, iframe[src^="javascript:"], object, embed' | ||
| ).forEach((T) => T.remove()), s.innerHTML = b.innerHTML; | ||
| try { | ||
| s.dispatchEvent( | ||
| new InputEvent("input", { | ||
| bubbles: !0, | ||
| cancelable: !1, | ||
| inputType: "insertReplacementText" | ||
| }) | ||
| ); | ||
| } catch { | ||
| s.dispatchEvent( | ||
| new Event("input", { bubbles: !0 }) | ||
| ); | ||
| } | ||
| s.dispatchEvent( | ||
| new Event("change", { bubbles: !0 }) | ||
| ), l = !1, f(); | ||
| } catch (t) { | ||
| alert("Failed to update HTML. Please check your syntax."), console.error("HTML update error:", t); | ||
| } | ||
| }; | ||
| d.querySelector(".theme-toggle-btn")?.addEventListener("click", E), d.querySelector(".readonly-toggle-btn")?.addEventListener("click", M), d.querySelector(".rte-source-editor-fullscreen-btn")?.addEventListener("click", S), d.querySelector(".rte-source-editor-close-btn")?.addEventListener("click", f), h.querySelector(".rte-source-editor-btn-cancel")?.addEventListener("click", L), h.querySelector(".rte-source-editor-btn-save")?.addEventListener("click", C), a.addEventListener("click", (t) => { | ||
| t.target === a && f(); | ||
| }); | ||
| const k = (t) => { | ||
| t.key === "Escape" && (f(), document.removeEventListener("keydown", k)); | ||
| }; | ||
| document.addEventListener("keydown", k); | ||
| })(), !0; | ||
| } | ||
| }, | ||
| // Keyboard shortcuts | ||
| keymap: { | ||
| "Mod-Shift-s": "toggleSourceView", | ||
| "Mod-Shift-S": "toggleSourceView" | ||
| } | ||
| }); | ||
| export { | ||
| I as CodePlugin | ||
| }; |
+11
-3
| { | ||
| "name": "@editora/code", | ||
| "version": "1.0.1", | ||
| "version": "1.0.2", | ||
| "description": "Source Code Editor plugin for Rich Text Editor", | ||
@@ -24,3 +24,3 @@ "authors": [ | ||
| "peerDependencies": { | ||
| "@editora/core": "^1.0.5" | ||
| "@editora/core": "^1.0.6" | ||
| }, | ||
@@ -41,3 +41,11 @@ "devDependencies": { | ||
| "author": "", | ||
| "license": "MIT" | ||
| "license": "MIT", | ||
| "exports": { | ||
| ".": { | ||
| "types": "./dist/index.d.ts", | ||
| "import": "./dist/index.esm.js", | ||
| "require": "./dist/index.cjs.js", | ||
| "default": "./dist/index.esm.js" | ||
| } | ||
| } | ||
| } |
-592
| import { createEditor as H, LineNumbersExtension as z, ThemeExtension as q, ReadOnlyExtension as B, BracketMatchingExtension as N, SearchExtension as A, CodeFoldingExtension as R, SyntaxHighlightingExtension as D } from "@editora/light-code-editor"; | ||
| const v = '[data-theme="dark"], .dark, .editora-theme-dark', O = `/* Source Editor Dialog Styles */ | ||
| .rte-source-editor-overlay { | ||
| position: fixed !important; | ||
| top: 0 !important; | ||
| left: 0 !important; | ||
| right: 0 !important; | ||
| bottom: 0 !important; | ||
| width: 100vw !important; | ||
| height: 100vh !important; | ||
| background-color: rgba(0, 0, 0, 0.6) !important; | ||
| display: flex !important; | ||
| align-items: center !important; | ||
| justify-content: center !important; | ||
| z-index: 10000 !important; | ||
| padding: 20px !important; | ||
| box-sizing: border-box !important; | ||
| margin: 0 !important; | ||
| } | ||
| .rte-source-editor-overlay.fullscreen { | ||
| padding: 0 !important; | ||
| } | ||
| .rte-source-editor-modal { | ||
| background: white; | ||
| border-radius: 8px; | ||
| box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); | ||
| width: 100%; | ||
| max-width: 1200px; | ||
| max-height: 90vh; | ||
| display: flex; | ||
| flex-direction: column; | ||
| overflow: hidden; | ||
| position: relative; | ||
| } | ||
| .rte-source-editor-overlay.fullscreen .rte-source-editor-modal { | ||
| border-radius: 0; | ||
| max-width: 100%; | ||
| max-height: 100vh; | ||
| width: 100%; | ||
| height: 100vh; | ||
| } | ||
| .rte-source-editor-header { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| padding: 16px 20px; | ||
| border-bottom: 1px solid #e1e5e9; | ||
| background: #f8f9fa; | ||
| border-radius: 8px 8px 0 0; | ||
| } | ||
| .rte-source-editor-overlay.fullscreen .rte-source-editor-header { | ||
| border-radius: 0; | ||
| } | ||
| .rte-source-editor-header h2 { | ||
| margin: 0; | ||
| font-size: 18px; | ||
| font-weight: 600; | ||
| color: #1a1a1a; | ||
| } | ||
| .rte-source-editor-header-toolbar { | ||
| display: flex; | ||
| gap: 8px; | ||
| margin-left: auto; | ||
| margin-right: 16px; | ||
| } | ||
| .rte-source-editor-toolbar-btn { | ||
| background: none; | ||
| border: none; | ||
| cursor: pointer; | ||
| padding: 6px; | ||
| border-radius: 4px; | ||
| font-size: 16px; | ||
| line-height: 1; | ||
| transition: all 0.2s ease; | ||
| color: #666; | ||
| } | ||
| .rte-source-editor-toolbar-btn:hover:not(:disabled) { | ||
| background: #e1e5e9; | ||
| color: #1a1a1a; | ||
| } | ||
| .rte-source-editor-toolbar-btn:disabled { | ||
| opacity: 0.5; | ||
| cursor: not-allowed; | ||
| } | ||
| .rte-source-editor-toolbar-btn.active { | ||
| background: #007acc; | ||
| color: white; | ||
| } | ||
| .rte-source-editor-toolbar-btn.active:hover { | ||
| background: #0056b3; | ||
| } | ||
| .rte-source-editor-header-actions { | ||
| display: flex; | ||
| gap: 8px; | ||
| } | ||
| .rte-source-editor-fullscreen-btn, | ||
| .rte-source-editor-close-btn { | ||
| background: none; | ||
| border: none; | ||
| cursor: pointer; | ||
| padding: 4px; | ||
| border-radius: 4px; | ||
| color: #666; | ||
| font-size: 16px; | ||
| line-height: 1; | ||
| transition: all 0.2s ease; | ||
| } | ||
| .rte-source-editor-fullscreen-btn:hover, | ||
| .rte-source-editor-close-btn:hover { | ||
| background: #e1e5e9; | ||
| color: #1a1a1a; | ||
| } | ||
| .rte-source-editor-body { | ||
| flex: 1; | ||
| overflow: hidden; | ||
| display: flex; | ||
| flex-direction: column; | ||
| } | ||
| .rte-source-editor-loading { | ||
| display: flex; | ||
| flex-direction: column; | ||
| align-items: center; | ||
| justify-content: center; | ||
| padding: 40px; | ||
| color: #666; | ||
| position: absolute; | ||
| z-index: 9; | ||
| margin: 0 auto; | ||
| width: 100%; | ||
| top: 44%; | ||
| } | ||
| .rte-source-editor-spinner { | ||
| width: 32px; | ||
| height: 32px; | ||
| border: 3px solid #e1e5e9; | ||
| border-top: 3px solid #007acc; | ||
| border-radius: 50%; | ||
| animation: spin 1s linear infinite; | ||
| margin-bottom: 16px; | ||
| } | ||
| @keyframes spin { | ||
| 0% { transform: rotate(0deg); } | ||
| 100% { transform: rotate(360deg); } | ||
| } | ||
| .rte-source-editor-error { | ||
| background: #fee; | ||
| color: #c53030; | ||
| padding: 12px 16px; | ||
| border-left: 4px solid #c53030; | ||
| margin: 16px; | ||
| border-radius: 4px; | ||
| font-size: 14px; | ||
| } | ||
| .rte-source-editor-content { | ||
| flex: 1; | ||
| display: flex; | ||
| flex-direction: column; | ||
| overflow: hidden; | ||
| } | ||
| .rte-source-editor-warning { | ||
| background: #fefcbf; | ||
| color: #744210; | ||
| padding: 8px 16px; | ||
| font-size: 12px; | ||
| font-weight: 500; | ||
| border-bottom: 1px solid #f6e05e; | ||
| } | ||
| .rte-source-editor-codemirror { | ||
| flex: 1; | ||
| overflow: auto; | ||
| font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; | ||
| font-size: 14px; | ||
| line-height: 1.5; | ||
| } | ||
| .rte-source-editor-codemirror .cm-editor { | ||
| height: 100%; | ||
| } | ||
| .rte-source-editor-codemirror .cm-focused { | ||
| outline: none; | ||
| } | ||
| .rte-source-editor-footer { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| padding: 16px 20px; | ||
| border-top: 1px solid #e1e5e9; | ||
| background: #f8f9fa; | ||
| border-radius: 0 0 8px 8px; | ||
| } | ||
| .rte-source-editor-overlay.fullscreen .rte-source-editor-footer { | ||
| border-radius: 0; | ||
| } | ||
| .rte-source-editor-footer-info { | ||
| font-size: 12px; | ||
| color: #666; | ||
| } | ||
| .unsaved-changes { | ||
| color: #d69e2e; | ||
| font-weight: 500; | ||
| } | ||
| .rte-source-editor-footer-actions { | ||
| display: flex; | ||
| gap: 12px; | ||
| } | ||
| .rte-source-editor-btn { | ||
| padding: 8px 16px; | ||
| border-radius: 4px; | ||
| font-size: 14px; | ||
| font-weight: 500; | ||
| cursor: pointer; | ||
| border: 1px solid transparent; | ||
| transition: all 0.2s ease; | ||
| } | ||
| .rte-source-editor-btn:disabled { | ||
| opacity: 0.6; | ||
| cursor: not-allowed; | ||
| } | ||
| .rte-source-editor-btn-cancel { | ||
| background: white; | ||
| border-color: #d1d5db; | ||
| color: #374151; | ||
| } | ||
| .rte-source-editor-btn-cancel:hover:not(:disabled) { | ||
| background: #f9fafb; | ||
| border-color: #9ca3af; | ||
| } | ||
| .rte-source-editor-btn-save { | ||
| background: #007acc; | ||
| color: white; | ||
| } | ||
| .rte-source-editor-btn-save:hover:not(:disabled) { | ||
| background: #0056b3; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-modal { | ||
| background: #1e1e1e; | ||
| color: #f8f9fa; | ||
| border: 1px solid #434d5f; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-header, | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-footer { | ||
| background: #2a3442; | ||
| border-color: #434d5f; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-header h2 { | ||
| color: #f8f9fa; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-toolbar-btn, | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-fullscreen-btn, | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-close-btn { | ||
| color: #c1cede; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-toolbar-btn:hover:not(:disabled), | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-fullscreen-btn:hover, | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-close-btn:hover { | ||
| background: #404a5a; | ||
| color: #f8fafc; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-toolbar-btn.active { | ||
| background: #3b82f6; | ||
| color: #ffffff; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-toolbar-btn.active:hover { | ||
| background: #2563eb; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-loading, | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-footer-info { | ||
| color: #cbd5e1; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-spinner { | ||
| border-color: #3f4b60; | ||
| border-top-color: #58a6ff; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-error { | ||
| background: #3f2124; | ||
| color: #fecaca; | ||
| border-color: #ef4444; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-warning { | ||
| background: #3b3220; | ||
| color: #fde68a; | ||
| border-color: #f59e0b; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-btn-cancel { | ||
| background: #334155; | ||
| border-color: #475569; | ||
| color: #f1f5f9; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-btn-cancel:hover:not(:disabled) { | ||
| background: #475569; | ||
| border-color: #64748b; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-btn-save { | ||
| background: #3b82f6; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-btn-save:hover:not(:disabled) { | ||
| background: #2563eb; | ||
| } | ||
| /* Responsive design */ | ||
| @media (max-width: 768px) { | ||
| .rte-source-editor-overlay { | ||
| padding: 10px; | ||
| } | ||
| .rte-source-editor-modal { | ||
| max-height: 95vh; | ||
| } | ||
| .rte-source-editor-header { | ||
| padding: 12px 16px; | ||
| } | ||
| .rte-source-editor-footer { | ||
| padding: 12px 16px; | ||
| flex-direction: column; | ||
| gap: 12px; | ||
| align-items: stretch; | ||
| } | ||
| .rte-source-editor-footer-actions { | ||
| justify-content: stretch; | ||
| } | ||
| .rte-source-editor-btn { | ||
| flex: 1; | ||
| text-align: center; | ||
| } | ||
| }`, P = () => ({ | ||
| name: "code", | ||
| // Toolbar button configuration | ||
| toolbar: [ | ||
| { | ||
| label: "Source", | ||
| command: "toggleSourceView", | ||
| type: "button", | ||
| icon: "<>", | ||
| shortcut: "Mod-Shift-S" | ||
| } | ||
| ], | ||
| // Native command implementations | ||
| commands: { | ||
| /** | ||
| * Toggle HTML source view | ||
| * Opens a dialog to edit raw HTML | ||
| */ | ||
| toggleSourceView: () => { | ||
| const f = (() => { | ||
| const r = window.getSelection(); | ||
| if (r && r.anchorNode) { | ||
| let e = r.anchorNode instanceof HTMLElement ? r.anchorNode : r.anchorNode.parentElement; | ||
| for (; e; ) { | ||
| if (e.classList?.contains("rte-content")) | ||
| return e; | ||
| e = e.parentElement; | ||
| } | ||
| } | ||
| if (document.activeElement) { | ||
| let e = document.activeElement; | ||
| if (e.classList?.contains("rte-content")) | ||
| return e; | ||
| for (; e && e !== document.body; ) { | ||
| if (e.classList?.contains("rte-content")) | ||
| return e; | ||
| const n = e.querySelector(".rte-content"); | ||
| if (n) return n; | ||
| e = e.parentElement; | ||
| } | ||
| } | ||
| const o = document.querySelector("[data-editora-editor]"); | ||
| if (o) { | ||
| const e = o.querySelector(".rte-content"); | ||
| if (e) return e; | ||
| } | ||
| return document.querySelector(".rte-content"); | ||
| })(); | ||
| if (!f) | ||
| return console.error("[CodePlugin] Editor content area not found"), alert("Editor content area not found. Please click inside the editor first."), !1; | ||
| const x = f.innerHTML, y = (r) => { | ||
| let o = "", e = 0; | ||
| const n = 2, s = r.split(/(<\/?[a-zA-Z][^>]*>)/); | ||
| for (const i of s) | ||
| i.trim() && (i.match(/^<\/[a-zA-Z]/) ? (e = Math.max(0, e - 1), o += ` | ||
| ` + " ".repeat(e * n) + i) : i.match(/^<[a-zA-Z]/) && !i.match(/\/>$/) ? (o += ` | ||
| ` + " ".repeat(e * n) + i, e++) : i.match(/^<[a-zA-Z].*\/>$/) ? o += ` | ||
| ` + " ".repeat(e * n) + i : o += i.trim()); | ||
| return o.trim(); | ||
| }; | ||
| return (() => { | ||
| let r = null, o = "dark", e = !1, n = !1, s = !1; | ||
| const i = x, w = !!f.closest(v) || document.body.matches(v) || document.documentElement.matches(v), a = document.createElement("div"); | ||
| a.className = "rte-source-editor-overlay", w && a.classList.add("rte-theme-dark"); | ||
| const c = document.createElement("div"); | ||
| c.className = "rte-source-editor-modal", c.setAttribute("role", "dialog"), c.setAttribute("aria-modal", "true"), c.setAttribute("aria-labelledby", "source-editor-title"); | ||
| const d = document.createElement("div"); | ||
| d.className = "rte-source-editor-header", d.innerHTML = ` | ||
| <h2 id="source-editor-title">Source Editor</h2> | ||
| <div class="rte-source-editor-header-toolbar"> | ||
| <button class="rte-source-editor-toolbar-btn theme-toggle-btn" title="Switch theme"> | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <circle cx="12" cy="12" r="5"/> | ||
| <line x1="12" y1="1" x2="12" y2="3"/> | ||
| <line x1="12" y1="21" x2="12" y2="23"/> | ||
| <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/> | ||
| <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/> | ||
| <line x1="1" y1="12" x2="3" y2="12"/> | ||
| <line x1="21" y1="12" x2="23" y2="12"/> | ||
| <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/> | ||
| <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/> | ||
| </svg> | ||
| </button> | ||
| <button class="rte-source-editor-toolbar-btn readonly-toggle-btn" title="Toggle read-only"> | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/> | ||
| <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/> | ||
| </svg> | ||
| </button> | ||
| </div> | ||
| <div class="rte-source-editor-header-actions"> | ||
| <button class="rte-source-editor-fullscreen-btn" title="Toggle fullscreen"> | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"/> | ||
| </svg> | ||
| </button> | ||
| <button class="rte-source-editor-close-btn" aria-label="Close source editor"> | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <line x1="18" y1="6" x2="6" y2="18"/> | ||
| <line x1="6" y1="6" x2="18" y2="18"/> | ||
| </svg> | ||
| </button> | ||
| </div> | ||
| `; | ||
| const g = document.createElement("div"); | ||
| g.className = "rte-source-editor-body"; | ||
| const m = document.createElement("div"); | ||
| m.className = "rte-source-editor-content"; | ||
| const p = document.createElement("div"); | ||
| p.className = "rte-source-editor-warning", p.textContent = "⚠️ Advanced users only. Invalid HTML may break the editor."; | ||
| const l = document.createElement("div"); | ||
| l.className = "rte-source-editor-light-editor", l.style.height = "400px", m.appendChild(p), m.appendChild(l), g.appendChild(m); | ||
| const u = document.createElement("div"); | ||
| if (u.className = "rte-source-editor-footer", u.innerHTML = ` | ||
| <div class="rte-source-editor-footer-info"> | ||
| <span class="unsaved-changes" style="display: none;">• Unsaved changes</span> | ||
| </div> | ||
| <div class="rte-source-editor-footer-actions"> | ||
| <button class="rte-source-editor-btn rte-source-editor-btn-cancel">Cancel</button> | ||
| <button class="rte-source-editor-btn rte-source-editor-btn-save">Save</button> | ||
| </div> | ||
| `, c.appendChild(d), c.appendChild(g), c.appendChild(u), a.appendChild(c), !document.getElementById("rte-source-editor-styles")) { | ||
| const t = document.createElement("style"); | ||
| t.id = "rte-source-editor-styles", t.textContent = O, document.head.appendChild(t); | ||
| } | ||
| document.body.appendChild(a); | ||
| try { | ||
| r = H(l, { | ||
| value: y(x), | ||
| theme: "dark", | ||
| readOnly: !1, | ||
| extensions: [ | ||
| new z(), | ||
| new q(), | ||
| new B(), | ||
| new N(), | ||
| new A(), | ||
| new R(), | ||
| new D() | ||
| ] | ||
| }), r.on("change", () => { | ||
| s = (r?.getValue() || "") !== y(i); | ||
| const h = u.querySelector(".unsaved-changes"); | ||
| h && (h.style.display = s ? "inline" : "none"); | ||
| }), setTimeout(() => r?.focus(), 100); | ||
| } catch (t) { | ||
| console.error("Failed to initialize code editor:", t); | ||
| } | ||
| const E = () => { | ||
| o = o === "dark" ? "light" : "dark", r?.setTheme(o); | ||
| const t = d.querySelector(".theme-toggle-btn"); | ||
| t && o === "light" && (t.innerHTML = ` | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/> | ||
| </svg> | ||
| `); | ||
| }, S = () => { | ||
| e = !e, r?.setReadOnly(e); | ||
| const t = d.querySelector(".readonly-toggle-btn"); | ||
| t && (e ? (t.classList.add("active"), t.innerHTML = ` | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <rect x="3" y="11" width="18" height="11" rx="2" ry="2"/> | ||
| <circle cx="12" cy="16" r="1"/> | ||
| <path d="M7 11V7a5 5 0 0 1 10 0v4"/> | ||
| </svg> | ||
| `) : (t.classList.remove("active"), t.innerHTML = ` | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/> | ||
| <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/> | ||
| </svg> | ||
| `)); | ||
| }, M = () => { | ||
| n = !n, n ? (a.classList.add("fullscreen"), l.style.height = "calc(100vh - 200px)") : (a.classList.remove("fullscreen"), l.style.height = "400px"); | ||
| const t = d.querySelector(".rte-source-editor-fullscreen-btn"); | ||
| t && (t.innerHTML = n ? ` | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 0 2-2h3M3 16h3a2 2 0 0 0 2 2v3"/> | ||
| </svg> | ||
| ` : ` | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"/> | ||
| </svg> | ||
| `); | ||
| }, b = () => { | ||
| r && (r.destroy(), r = null), document.body.removeChild(a); | ||
| }, C = () => { | ||
| s && !confirm("You have unsaved changes. Are you sure you want to cancel?") || b(); | ||
| }, L = () => { | ||
| try { | ||
| const t = r?.getValue() || "", h = document.createElement("div"); | ||
| h.innerHTML = t, h.querySelectorAll('script, iframe[src^="javascript:"], object, embed').forEach((T) => T.remove()), f.innerHTML = h.innerHTML, s = !1, b(); | ||
| } catch (t) { | ||
| alert("Failed to update HTML. Please check your syntax."), console.error("HTML update error:", t); | ||
| } | ||
| }; | ||
| d.querySelector(".theme-toggle-btn")?.addEventListener("click", E), d.querySelector(".readonly-toggle-btn")?.addEventListener("click", S), d.querySelector(".rte-source-editor-fullscreen-btn")?.addEventListener("click", M), d.querySelector(".rte-source-editor-close-btn")?.addEventListener("click", b), u.querySelector(".rte-source-editor-btn-cancel")?.addEventListener("click", C), u.querySelector(".rte-source-editor-btn-save")?.addEventListener("click", L), a.addEventListener("click", (t) => { | ||
| t.target === a && b(); | ||
| }); | ||
| const k = (t) => { | ||
| t.key === "Escape" && (b(), document.removeEventListener("keydown", k)); | ||
| }; | ||
| document.addEventListener("keydown", k); | ||
| })(), !0; | ||
| } | ||
| }, | ||
| // Keyboard shortcuts | ||
| keymap: { | ||
| "Mod-Shift-s": "toggleSourceView", | ||
| "Mod-Shift-S": "toggleSourceView" | ||
| } | ||
| }); | ||
| export { | ||
| P as CodePlugin | ||
| }; |
| (function(l,n){typeof exports=="object"&&typeof module<"u"?n(exports,require("@editora/light-code-editor")):typeof define=="function"&&define.amd?define(["exports","@editora/light-code-editor"],n):(l=typeof globalThis<"u"?globalThis:l||self,n(l.line_heightPlugin={},l.LightCodeEditor))})(this,(function(l,n){"use strict";const v='[data-theme="dark"], .dark, .editora-theme-dark',S=`/* Source Editor Dialog Styles */ | ||
| .rte-source-editor-overlay { | ||
| position: fixed !important; | ||
| top: 0 !important; | ||
| left: 0 !important; | ||
| right: 0 !important; | ||
| bottom: 0 !important; | ||
| width: 100vw !important; | ||
| height: 100vh !important; | ||
| background-color: rgba(0, 0, 0, 0.6) !important; | ||
| display: flex !important; | ||
| align-items: center !important; | ||
| justify-content: center !important; | ||
| z-index: 10000 !important; | ||
| padding: 20px !important; | ||
| box-sizing: border-box !important; | ||
| margin: 0 !important; | ||
| } | ||
| .rte-source-editor-overlay.fullscreen { | ||
| padding: 0 !important; | ||
| } | ||
| .rte-source-editor-modal { | ||
| background: white; | ||
| border-radius: 8px; | ||
| box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); | ||
| width: 100%; | ||
| max-width: 1200px; | ||
| max-height: 90vh; | ||
| display: flex; | ||
| flex-direction: column; | ||
| overflow: hidden; | ||
| position: relative; | ||
| } | ||
| .rte-source-editor-overlay.fullscreen .rte-source-editor-modal { | ||
| border-radius: 0; | ||
| max-width: 100%; | ||
| max-height: 100vh; | ||
| width: 100%; | ||
| height: 100vh; | ||
| } | ||
| .rte-source-editor-header { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| padding: 16px 20px; | ||
| border-bottom: 1px solid #e1e5e9; | ||
| background: #f8f9fa; | ||
| border-radius: 8px 8px 0 0; | ||
| } | ||
| .rte-source-editor-overlay.fullscreen .rte-source-editor-header { | ||
| border-radius: 0; | ||
| } | ||
| .rte-source-editor-header h2 { | ||
| margin: 0; | ||
| font-size: 18px; | ||
| font-weight: 600; | ||
| color: #1a1a1a; | ||
| } | ||
| .rte-source-editor-header-toolbar { | ||
| display: flex; | ||
| gap: 8px; | ||
| margin-left: auto; | ||
| margin-right: 16px; | ||
| } | ||
| .rte-source-editor-toolbar-btn { | ||
| background: none; | ||
| border: none; | ||
| cursor: pointer; | ||
| padding: 6px; | ||
| border-radius: 4px; | ||
| font-size: 16px; | ||
| line-height: 1; | ||
| transition: all 0.2s ease; | ||
| color: #666; | ||
| } | ||
| .rte-source-editor-toolbar-btn:hover:not(:disabled) { | ||
| background: #e1e5e9; | ||
| color: #1a1a1a; | ||
| } | ||
| .rte-source-editor-toolbar-btn:disabled { | ||
| opacity: 0.5; | ||
| cursor: not-allowed; | ||
| } | ||
| .rte-source-editor-toolbar-btn.active { | ||
| background: #007acc; | ||
| color: white; | ||
| } | ||
| .rte-source-editor-toolbar-btn.active:hover { | ||
| background: #0056b3; | ||
| } | ||
| .rte-source-editor-header-actions { | ||
| display: flex; | ||
| gap: 8px; | ||
| } | ||
| .rte-source-editor-fullscreen-btn, | ||
| .rte-source-editor-close-btn { | ||
| background: none; | ||
| border: none; | ||
| cursor: pointer; | ||
| padding: 4px; | ||
| border-radius: 4px; | ||
| color: #666; | ||
| font-size: 16px; | ||
| line-height: 1; | ||
| transition: all 0.2s ease; | ||
| } | ||
| .rte-source-editor-fullscreen-btn:hover, | ||
| .rte-source-editor-close-btn:hover { | ||
| background: #e1e5e9; | ||
| color: #1a1a1a; | ||
| } | ||
| .rte-source-editor-body { | ||
| flex: 1; | ||
| overflow: hidden; | ||
| display: flex; | ||
| flex-direction: column; | ||
| } | ||
| .rte-source-editor-loading { | ||
| display: flex; | ||
| flex-direction: column; | ||
| align-items: center; | ||
| justify-content: center; | ||
| padding: 40px; | ||
| color: #666; | ||
| position: absolute; | ||
| z-index: 9; | ||
| margin: 0 auto; | ||
| width: 100%; | ||
| top: 44%; | ||
| } | ||
| .rte-source-editor-spinner { | ||
| width: 32px; | ||
| height: 32px; | ||
| border: 3px solid #e1e5e9; | ||
| border-top: 3px solid #007acc; | ||
| border-radius: 50%; | ||
| animation: spin 1s linear infinite; | ||
| margin-bottom: 16px; | ||
| } | ||
| @keyframes spin { | ||
| 0% { transform: rotate(0deg); } | ||
| 100% { transform: rotate(360deg); } | ||
| } | ||
| .rte-source-editor-error { | ||
| background: #fee; | ||
| color: #c53030; | ||
| padding: 12px 16px; | ||
| border-left: 4px solid #c53030; | ||
| margin: 16px; | ||
| border-radius: 4px; | ||
| font-size: 14px; | ||
| } | ||
| .rte-source-editor-content { | ||
| flex: 1; | ||
| display: flex; | ||
| flex-direction: column; | ||
| overflow: hidden; | ||
| } | ||
| .rte-source-editor-warning { | ||
| background: #fefcbf; | ||
| color: #744210; | ||
| padding: 8px 16px; | ||
| font-size: 12px; | ||
| font-weight: 500; | ||
| border-bottom: 1px solid #f6e05e; | ||
| } | ||
| .rte-source-editor-codemirror { | ||
| flex: 1; | ||
| overflow: auto; | ||
| font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; | ||
| font-size: 14px; | ||
| line-height: 1.5; | ||
| } | ||
| .rte-source-editor-codemirror .cm-editor { | ||
| height: 100%; | ||
| } | ||
| .rte-source-editor-codemirror .cm-focused { | ||
| outline: none; | ||
| } | ||
| .rte-source-editor-footer { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| padding: 16px 20px; | ||
| border-top: 1px solid #e1e5e9; | ||
| background: #f8f9fa; | ||
| border-radius: 0 0 8px 8px; | ||
| } | ||
| .rte-source-editor-overlay.fullscreen .rte-source-editor-footer { | ||
| border-radius: 0; | ||
| } | ||
| .rte-source-editor-footer-info { | ||
| font-size: 12px; | ||
| color: #666; | ||
| } | ||
| .unsaved-changes { | ||
| color: #d69e2e; | ||
| font-weight: 500; | ||
| } | ||
| .rte-source-editor-footer-actions { | ||
| display: flex; | ||
| gap: 12px; | ||
| } | ||
| .rte-source-editor-btn { | ||
| padding: 8px 16px; | ||
| border-radius: 4px; | ||
| font-size: 14px; | ||
| font-weight: 500; | ||
| cursor: pointer; | ||
| border: 1px solid transparent; | ||
| transition: all 0.2s ease; | ||
| } | ||
| .rte-source-editor-btn:disabled { | ||
| opacity: 0.6; | ||
| cursor: not-allowed; | ||
| } | ||
| .rte-source-editor-btn-cancel { | ||
| background: white; | ||
| border-color: #d1d5db; | ||
| color: #374151; | ||
| } | ||
| .rte-source-editor-btn-cancel:hover:not(:disabled) { | ||
| background: #f9fafb; | ||
| border-color: #9ca3af; | ||
| } | ||
| .rte-source-editor-btn-save { | ||
| background: #007acc; | ||
| color: white; | ||
| } | ||
| .rte-source-editor-btn-save:hover:not(:disabled) { | ||
| background: #0056b3; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-modal { | ||
| background: #1e1e1e; | ||
| color: #f8f9fa; | ||
| border: 1px solid #434d5f; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-header, | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-footer { | ||
| background: #2a3442; | ||
| border-color: #434d5f; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-header h2 { | ||
| color: #f8f9fa; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-toolbar-btn, | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-fullscreen-btn, | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-close-btn { | ||
| color: #c1cede; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-toolbar-btn:hover:not(:disabled), | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-fullscreen-btn:hover, | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-close-btn:hover { | ||
| background: #404a5a; | ||
| color: #f8fafc; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-toolbar-btn.active { | ||
| background: #3b82f6; | ||
| color: #ffffff; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-toolbar-btn.active:hover { | ||
| background: #2563eb; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-loading, | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-footer-info { | ||
| color: #cbd5e1; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-spinner { | ||
| border-color: #3f4b60; | ||
| border-top-color: #58a6ff; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-error { | ||
| background: #3f2124; | ||
| color: #fecaca; | ||
| border-color: #ef4444; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-warning { | ||
| background: #3b3220; | ||
| color: #fde68a; | ||
| border-color: #f59e0b; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-btn-cancel { | ||
| background: #334155; | ||
| border-color: #475569; | ||
| color: #f1f5f9; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-btn-cancel:hover:not(:disabled) { | ||
| background: #475569; | ||
| border-color: #64748b; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-btn-save { | ||
| background: #3b82f6; | ||
| } | ||
| .rte-source-editor-overlay.rte-theme-dark .rte-source-editor-btn-save:hover:not(:disabled) { | ||
| background: #2563eb; | ||
| } | ||
| /* Responsive design */ | ||
| @media (max-width: 768px) { | ||
| .rte-source-editor-overlay { | ||
| padding: 10px; | ||
| } | ||
| .rte-source-editor-modal { | ||
| max-height: 95vh; | ||
| } | ||
| .rte-source-editor-header { | ||
| padding: 12px 16px; | ||
| } | ||
| .rte-source-editor-footer { | ||
| padding: 12px 16px; | ||
| flex-direction: column; | ||
| gap: 12px; | ||
| align-items: stretch; | ||
| } | ||
| .rte-source-editor-footer-actions { | ||
| justify-content: stretch; | ||
| } | ||
| .rte-source-editor-btn { | ||
| flex: 1; | ||
| text-align: center; | ||
| } | ||
| }`,M=()=>({name:"code",toolbar:[{label:"Source",command:"toggleSourceView",type:"button",icon:"<>",shortcut:"Mod-Shift-S"}],commands:{toggleSourceView:()=>{const p=(()=>{const r=window.getSelection();if(r&&r.anchorNode){let e=r.anchorNode instanceof HTMLElement?r.anchorNode:r.anchorNode.parentElement;for(;e;){if(e.classList?.contains("rte-content"))return e;e=e.parentElement}}if(document.activeElement){let e=document.activeElement;if(e.classList?.contains("rte-content"))return e;for(;e&&e!==document.body;){if(e.classList?.contains("rte-content"))return e;const i=e.querySelector(".rte-content");if(i)return i;e=e.parentElement}}const o=document.querySelector("[data-editora-editor]");if(o){const e=o.querySelector(".rte-content");if(e)return e}return document.querySelector(".rte-content")})();if(!p)return console.error("[CodePlugin] Editor content area not found"),alert("Editor content area not found. Please click inside the editor first."),!1;const k=p.innerHTML,w=r=>{let o="",e=0;const i=2,u=r.split(/(<\/?[a-zA-Z][^>]*>)/);for(const d of u)d.trim()&&(d.match(/^<\/[a-zA-Z]/)?(e=Math.max(0,e-1),o+=` | ||
| `+" ".repeat(e*i)+d):d.match(/^<[a-zA-Z]/)&&!d.match(/\/>$/)?(o+=` | ||
| `+" ".repeat(e*i)+d,e++):d.match(/^<[a-zA-Z].*\/>$/)?o+=` | ||
| `+" ".repeat(e*i)+d:o+=d.trim());return o.trim()};return(()=>{let r=null,o="dark",e=!1,i=!1,u=!1;const d=k,L=!!p.closest(v)||document.body.matches(v)||document.documentElement.matches(v),a=document.createElement("div");a.className="rte-source-editor-overlay",L&&a.classList.add("rte-theme-dark");const s=document.createElement("div");s.className="rte-source-editor-modal",s.setAttribute("role","dialog"),s.setAttribute("aria-modal","true"),s.setAttribute("aria-labelledby","source-editor-title");const c=document.createElement("div");c.className="rte-source-editor-header",c.innerHTML=` | ||
| <h2 id="source-editor-title">Source Editor</h2> | ||
| <div class="rte-source-editor-header-toolbar"> | ||
| <button class="rte-source-editor-toolbar-btn theme-toggle-btn" title="Switch theme"> | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <circle cx="12" cy="12" r="5"/> | ||
| <line x1="12" y1="1" x2="12" y2="3"/> | ||
| <line x1="12" y1="21" x2="12" y2="23"/> | ||
| <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/> | ||
| <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/> | ||
| <line x1="1" y1="12" x2="3" y2="12"/> | ||
| <line x1="21" y1="12" x2="23" y2="12"/> | ||
| <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/> | ||
| <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/> | ||
| </svg> | ||
| </button> | ||
| <button class="rte-source-editor-toolbar-btn readonly-toggle-btn" title="Toggle read-only"> | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/> | ||
| <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/> | ||
| </svg> | ||
| </button> | ||
| </div> | ||
| <div class="rte-source-editor-header-actions"> | ||
| <button class="rte-source-editor-fullscreen-btn" title="Toggle fullscreen"> | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"/> | ||
| </svg> | ||
| </button> | ||
| <button class="rte-source-editor-close-btn" aria-label="Close source editor"> | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <line x1="18" y1="6" x2="6" y2="18"/> | ||
| <line x1="6" y1="6" x2="18" y2="18"/> | ||
| </svg> | ||
| </button> | ||
| </div> | ||
| `;const x=document.createElement("div");x.className="rte-source-editor-body";const g=document.createElement("div");g.className="rte-source-editor-content";const y=document.createElement("div");y.className="rte-source-editor-warning",y.textContent="⚠️ Advanced users only. Invalid HTML may break the editor.";const h=document.createElement("div");h.className="rte-source-editor-light-editor",h.style.height="400px",g.appendChild(y),g.appendChild(h),x.appendChild(g);const f=document.createElement("div");if(f.className="rte-source-editor-footer",f.innerHTML=` | ||
| <div class="rte-source-editor-footer-info"> | ||
| <span class="unsaved-changes" style="display: none;">• Unsaved changes</span> | ||
| </div> | ||
| <div class="rte-source-editor-footer-actions"> | ||
| <button class="rte-source-editor-btn rte-source-editor-btn-cancel">Cancel</button> | ||
| <button class="rte-source-editor-btn rte-source-editor-btn-save">Save</button> | ||
| </div> | ||
| `,s.appendChild(c),s.appendChild(x),s.appendChild(f),a.appendChild(s),!document.getElementById("rte-source-editor-styles")){const t=document.createElement("style");t.id="rte-source-editor-styles",t.textContent=S,document.head.appendChild(t)}document.body.appendChild(a);try{r=n.createEditor(h,{value:w(k),theme:"dark",readOnly:!1,extensions:[new n.LineNumbersExtension,new n.ThemeExtension,new n.ReadOnlyExtension,new n.BracketMatchingExtension,new n.SearchExtension,new n.CodeFoldingExtension,new n.SyntaxHighlightingExtension]}),r.on("change",()=>{u=(r?.getValue()||"")!==w(d);const b=f.querySelector(".unsaved-changes");b&&(b.style.display=u?"inline":"none")}),setTimeout(()=>r?.focus(),100)}catch(t){console.error("Failed to initialize code editor:",t)}const C=()=>{o=o==="dark"?"light":"dark",r?.setTheme(o);const t=c.querySelector(".theme-toggle-btn");t&&o==="light"&&(t.innerHTML=` | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/> | ||
| </svg> | ||
| `)},T=()=>{e=!e,r?.setReadOnly(e);const t=c.querySelector(".readonly-toggle-btn");t&&(e?(t.classList.add("active"),t.innerHTML=` | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <rect x="3" y="11" width="18" height="11" rx="2" ry="2"/> | ||
| <circle cx="12" cy="16" r="1"/> | ||
| <path d="M7 11V7a5 5 0 0 1 10 0v4"/> | ||
| </svg> | ||
| `):(t.classList.remove("active"),t.innerHTML=` | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/> | ||
| <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/> | ||
| </svg> | ||
| `))},H=()=>{i=!i,i?(a.classList.add("fullscreen"),h.style.height="calc(100vh - 200px)"):(a.classList.remove("fullscreen"),h.style.height="400px");const t=c.querySelector(".rte-source-editor-fullscreen-btn");t&&(t.innerHTML=i?` | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 0 2-2h3M3 16h3a2 2 0 0 0 2 2v3"/> | ||
| </svg> | ||
| `:` | ||
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | ||
| <path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"/> | ||
| </svg> | ||
| `)},m=()=>{r&&(r.destroy(),r=null),document.body.removeChild(a)},z=()=>{u&&!confirm("You have unsaved changes. Are you sure you want to cancel?")||m()},q=()=>{try{const t=r?.getValue()||"",b=document.createElement("div");b.innerHTML=t,b.querySelectorAll('script, iframe[src^="javascript:"], object, embed').forEach(B=>B.remove()),p.innerHTML=b.innerHTML,u=!1,m()}catch(t){alert("Failed to update HTML. Please check your syntax."),console.error("HTML update error:",t)}};c.querySelector(".theme-toggle-btn")?.addEventListener("click",C),c.querySelector(".readonly-toggle-btn")?.addEventListener("click",T),c.querySelector(".rte-source-editor-fullscreen-btn")?.addEventListener("click",H),c.querySelector(".rte-source-editor-close-btn")?.addEventListener("click",m),f.querySelector(".rte-source-editor-btn-cancel")?.addEventListener("click",z),f.querySelector(".rte-source-editor-btn-save")?.addEventListener("click",q),a.addEventListener("click",t=>{t.target===a&&m()});const E=t=>{t.key==="Escape"&&(m(),document.removeEventListener("keydown",E))};document.addEventListener("keydown",E)})(),!0}},keymap:{"Mod-Shift-s":"toggleSourceView","Mod-Shift-S":"toggleSourceView"}});l.CodePlugin=M,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})})); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
37974
4.07%975
3.39%1
Infinity%