domma-cms 1.6.28 → 1.6.30
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/admin/js/lib/markdown-toolbar.js +2 -2
- package/admin/js/lib/shortcode-context-menu.js +2 -2
- package/admin/js/lib/shortcode-form.js +3 -3
- package/admin/js/lib/shortcode-modal.js +1 -1
- package/admin/js/lib/shortcode-registry.js +2 -2
- package/admin/js/views/page-editor.js +9 -17
- package/package.json +1 -1
|
@@ -5,6 +5,6 @@ function L(){I.register("bold",{viewBox:"0 0 24 24",path:"M7 5H14a3 3 0 0 1 0 6H
|
|
|
5
5
|
`,i-1)+1,r=e.value.indexOf(`
|
|
6
6
|
`,i),a=r===-1?e.value.length:r+1;e.setSelectionRange(n,a),document.execCommand("copy"),e.setSelectionRange(i,i),E.toast("Line copied",{type:"info",duration:1200})}})}export function insertLine(e,t){const s=e.selectionStart,i=e.value,n=i.lastIndexOf(`
|
|
7
7
|
`,s-1)+1,r=i.indexOf(`
|
|
8
|
-
`,n);i.substring(n,r===-1?i.length:r).startsWith(t)?(replaceRange(e,n,n+t.length,""),e.setSelectionRange(Math.max(n,s-t.length),Math.max(n,s-t.length))):(replaceRange(e,n,n,t),e.setSelectionRange(s+t.length,s+t.length))}function k(e,t,s,i){const n=document.querySelector(".editor-toolbar-dropdown");if(n){n.remove();return}const r=document.createElement("div");r.className="editor-toolbar-dropdown",s.forEach(function(o){if(o.heading){const d=document.createElement("div");d.className="editor-toolbar-dropdown-heading",d.textContent=o.heading,r.appendChild(d);return}const l=document.createElement("button");if(l.type="button",l.className="editor-toolbar-dropdown-item",o.icon){const d=document.createElement("span");d.setAttribute("data-icon",o.icon),l.appendChild(d)}const c=document.createElement("span");c.textContent=o.label,l.appendChild(c),l.addEventListener("click",function(){r.remove(),document.removeEventListener("click",f,!0),m(o.action,e,t,i)}),r.appendChild(l)});const a=t.getBoundingClientRect(),p=t.closest(".editor-toolbar").getBoundingClientRect();r.style.top=a.bottom-p.top+4+"px";const h=a.left-p.left;r.style.left=Math.min(h,p.width-180-8)+"px",t.closest(".editor-toolbar").appendChild(r),Domma.icons.scan(r);function f(o){!r.contains(o.target)&&o.target!==t&&(r.remove(),document.removeEventListener("click",f,!0))}setTimeout(function(){document.addEventListener("click",f,!0)},0)}function b(){return import("./shortcode-insert.js").then(e=>e.insertMenuGroups().flatMap(t=>[{heading:t.category},...t.items.map(s=>({label:s.label,icon:s.icon,action:`insert:${s.name}`}))]))}function m(e,t,s,i){const{handlers:n}=i;typeof e=="function"?e(t):typeof e=="string"&&e.startsWith("insert:")?
|
|
8
|
+
`,n);i.substring(n,r===-1?i.length:r).startsWith(t)?(replaceRange(e,n,n+t.length,""),e.setSelectionRange(Math.max(n,s-t.length),Math.max(n,s-t.length))):(replaceRange(e,n,n,t),e.setSelectionRange(s+t.length,s+t.length))}function k(e,t,s,i){const n=document.querySelector(".editor-toolbar-dropdown");if(n){n.remove();return}const r=document.createElement("div");r.className="editor-toolbar-dropdown",s.forEach(function(o){if(o.heading){const d=document.createElement("div");d.className="editor-toolbar-dropdown-heading",d.textContent=o.heading,r.appendChild(d);return}const l=document.createElement("button");if(l.type="button",l.className="editor-toolbar-dropdown-item",o.icon){const d=document.createElement("span");d.setAttribute("data-icon",o.icon),l.appendChild(d)}const c=document.createElement("span");c.textContent=o.label,l.appendChild(c),l.addEventListener("click",function(){r.remove(),document.removeEventListener("click",f,!0),m(o.action,e,t,i)}),r.appendChild(l)});const a=t.getBoundingClientRect(),p=t.closest(".editor-toolbar").getBoundingClientRect();r.style.top=a.bottom-p.top+4+"px";const h=a.left-p.left;r.style.left=Math.min(h,p.width-180-8)+"px",t.closest(".editor-toolbar").appendChild(r),Domma.icons.scan(r);function f(o){!r.contains(o.target)&&o.target!==t&&(r.remove(),document.removeEventListener("click",f,!0))}setTimeout(function(){document.addEventListener("click",f,!0)},0)}function b(){return import("./shortcode-insert.js").then(e=>e.insertMenuGroups().flatMap(t=>[{heading:t.category},...t.items.map(s=>({label:s.label,icon:s.icon,action:`insert:${s.name}`}))]))}function m(e,t,s,i){const{handlers:n}=i;typeof e=="function"?e(t):typeof e=="string"&&e.startsWith("insert:")?g(e.slice(7),t):e==="effects"?n.effects&&n.effects(t):e==="help"?n.help&&n.help(t):e==="tutorial"&&n.tutorial&&n.tutorial(t)}function g(e,t){import("./shortcode-insert.js").then(s=>s.insertShortcodeByName(e,t)).catch(s=>console.error("Insert router failed to load",s))}const v=[{icon:"bold",title:"Bold (Ctrl+B)",action:e=>wrapSelection(e,"**","**")},{icon:"italic",title:"Italic (Ctrl+I)",action:e=>wrapSelection(e,"_","_")},{icon:"strikethrough",title:"Strikethrough",action:e=>wrapSelection(e,"~~","~~")},"|",{type:"dropdown",icon:"heading-1",title:"Headings",items:[{label:"Heading 1",icon:"heading-1",action:e=>insertLine(e,"# ")},{label:"Heading 2",icon:"heading-2",action:e=>insertLine(e,"## ")},{label:"Heading 3",icon:"heading-3",action:e=>insertLine(e,"### ")}]},"|",{icon:"list-bullet",title:"Bullet list",action:e=>insertLine(e,"- ")},{icon:"list-numbered",title:"Numbered list",action:e=>insertLine(e,"1. ")},"|",{type:"dropdown",icon:"quote",title:"Paragraph",items:[{label:"Blockquote",icon:"quote",action:e=>insertLine(e,"> ")},{label:"Horizontal rule",icon:"minus-circle",action:e=>insertAtCursor(e,`
|
|
9
9
|
---
|
|
10
|
-
`)}]},"|",{type:"dropdown",icon:"code-inline",title:"Code",items:[{label:"Inline code",icon:"code-inline",action:e=>wrapSelection(e,"`","`")},{label:"Code block",icon:"code-block",action:e=>wrapSelection(e,"\n```\n","\n```\n")}]},"|",{type:"dropdown",icon:"plus-circle",title:"Insert",insertMenu:!0,items:[]},"|",{icon:"sparkles",title:"Effects",action:"effects"},{icon:"book-open",title:"CRUD tutorial",action:"tutorial"},{icon:"help-circle",title:"Editor help",action:"help"}];export function createToolbar(e,t,s={}){L();const i={help:null,tutorial:null,effects:null};s.spacerDefault&&import("./shortcode-insert.js").then(o=>o.registerInsertDefaults({spacer:{size:String(s.spacerDefault)}})).catch(()=>{});const n=e.get(0),r=t.get(0);r.textContent="",
|
|
10
|
+
`)}]},"|",{type:"dropdown",icon:"code-inline",title:"Code",items:[{label:"Inline code",icon:"code-inline",action:e=>wrapSelection(e,"`","`")},{label:"Code block",icon:"code-block",action:e=>wrapSelection(e,"\n```\n","\n```\n")}]},"|",{type:"dropdown",icon:"plus-circle",title:"Insert",insertMenu:!0,items:[]},"|",{icon:"sparkles",title:"Effects",action:"effects"},{icon:"book-open",title:"CRUD tutorial",action:"tutorial"},{icon:"image-add",title:"Upload or insert image",action:"insert:image"},{icon:"help-circle",title:"Editor help",action:"help"}];export function createToolbar(e,t,s={}){L();const i={help:null,tutorial:null,effects:null};s.spacerDefault&&import("./shortcode-insert.js").then(o=>o.registerInsertDefaults({spacer:{size:String(s.spacerDefault)}})).catch(()=>{});const n=e.get(0),r=t.get(0);r.textContent="",v.forEach((o,l)=>{if(o==="|"){const c=document.createElement("span");c.className="editor-toolbar-sep",r.appendChild(c)}else{const c=document.createElement("button");c.className=o.type==="dropdown"?"editor-toolbar-btn editor-toolbar-dropdown-trigger":"editor-toolbar-btn",c.setAttribute("data-tooltip",o.title),c.setAttribute("data-idx",String(l)),c.type="button";const d=document.createElement("span");if(d.setAttribute("data-icon",o.icon),c.appendChild(d),o.type==="dropdown"){const u=document.createElement("span");u.className="editor-toolbar-caret",u.setAttribute("data-icon","chevron-down"),u.setAttribute("data-icon-size","12"),u.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;",c.appendChild(u)}r.appendChild(c)}});const a=document.createElement("div");a.className="editor-toolbar-right",[{mode:"split",icon:"columns",label:"Split view",active:!0},{mode:"write",icon:"file-text",label:"Write only",active:!1},{mode:"preview",icon:"eye",label:"Preview only",active:!1}].forEach(o=>{const l=document.createElement("button");l.className="editor-view-btn"+(o.active?" active":""),l.setAttribute("data-mode",o.mode),l.setAttribute("data-tooltip",o.label),l.type="button";const c=document.createElement("span");c.setAttribute("data-icon",o.icon),l.appendChild(c),a.appendChild(l)});const p=document.createElement("span");p.className="editor-toolbar-sep",a.appendChild(p);const h=document.createElement("button");h.id="fullscreen-btn",h.className="editor-toolbar-btn",h.setAttribute("data-tooltip","Toggle fullscreen"),h.type="button";const f=document.createElement("span");return f.setAttribute("data-icon","expand"),h.appendChild(f),a.appendChild(h),r.appendChild(a),Domma.icons.scan(),r.querySelectorAll("[data-tooltip]").forEach(o=>{E.tooltip(o,{content:o.getAttribute("data-tooltip"),position:"top"})}),t.on("click",".editor-toolbar-btn[data-idx]",function(){const o=parseInt($(this).data("idx"),10),l=v[o];if(!l||l==="|")return;const c=t.get(0).querySelector(`[data-idx="${o}"]`),d={handlers:i};l.type==="dropdown"?l.insertMenu?b().then(u=>k(n,c,u,d)).catch(u=>console.error("Insert menu failed to load",u)):k(n,c,l.items,d):m(l.action,n,c,d)}),attachEditorKeybindings(n),n.addEventListener("keydown",o=>{const l=o.key.toLowerCase();(o.ctrlKey||o.metaKey)&&(l==="b"?(o.preventDefault(),wrapSelection(n,"**","**")):l==="i"?(o.preventDefault(),wrapSelection(n,"_","_")):l==="k"&&(o.preventDefault(),g("link",n)))}),{$toolbar:t,onHelp(o){i.help=o},onTutorial(o){i.tutorial=o},onEffects(o){i.effects=o}}}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{SHORTCODES as A}from"./shortcode-registry.js";import{EFFECTS as w,CELEBRATION_THEMES as Q,getEffectAttrs as z}from"./effect-defs.js";import{boolState as Z,boolValue as ee,findEnclosingShortcode as H,setAttr as P,setAttrs as D,effectAttrKeys as te}from"./shortcode-tags.js";import{insertAtCursor as O,replaceRange as ne}from"./markdown-toolbar.js";import{clearLookupCache as oe,lookupOptions as se}from"./shortcode-lookups.js";import{insertMenuGroups as ie,insertShortcodeByName as ae}from"./shortcode-insert.js";import{openShortcodeForm as $}from"./shortcode-form.js";function ce(e){return se(e,a?.span?.attrs||{})}const le=A.map(e=>({name:e.name,selfClosing:!!e.selfClosing})),re=new Map(A.map(e=>[e.name,e])),j=new Map(w.map(e=>[e.name,e])),de=w.map(e=>({name:e.name,selfClosing:!!e.selfClosing})),W=[...le,...de],Y=new Set(["card","box","hero","banner","col","button"]);let a=null;const B="position:fixed;z-index:10000;min-width:210px;max-height:70vh;overflow-y:auto;background:var(--dm-surface,#1c1c30);border:1px solid var(--dm-border,#2a2a40);border-radius:6px;box-shadow:var(--dm-shadow-lg);padding:.3rem;font-size:.83rem;color:var(--dm-text,#e5e5e5);",p="display:flex;align-items:center;gap:.5rem;width:100%;text-align:left;padding:.35rem .55rem;border:none;background:transparent;color:inherit;border-radius:4px;cursor:pointer;font-size:.83rem;",S="padding:.3rem .55rem;color:var(--dm-text-muted,#8a8a9a);font-size:.68rem;text-transform:uppercase;letter-spacing:.06em;",F="flex:1;min-width:0;padding:.2rem .4rem;background:var(--dm-input-bg,#12121e);border:1px solid var(--dm-border,#333);border-radius:3px;color:var(--dm-text,#eee);font-size:.8rem;",ue="height:1px;background:var(--dm-border,#2a2a40);margin:.3rem .2rem;";function f(e){return e.addEventListener("mouseenter",()=>{e.style.background="var(--dm-primary,#4338ca)",e.style.color="var(--dm-primary-text,#fff)"}),e.addEventListener("mouseleave",()=>{e.style.background="transparent",e.style.color="inherit"}),e}export function attachContextMenu(e){return typeof Domma>"u"||!Domma.elements?.contextMenu?(e.addEventListener("contextmenu",n=>{n.preventDefault(),d();const t=H(e,W);M(e,t,n.clientX,n.clientY)}),null):Domma.elements.contextMenu(e,{inherit:!1,cursor:!1,render:n=>{d();const t=H(e,W);M(e,t,n.x,n.y)}})}function d(){a&&(v(),a.root.remove(),document.removeEventListener("mousedown",q,!0),document.removeEventListener("keydown",U,!0),window.removeEventListener("scroll",K,!0),a=null)}const q=e=>{a&&!a.root.contains(e.target)&&!(a.submenu&&a.submenu.contains(e.target))&&d()},K=e=>{a&&!a.root.contains(e.target)&&!(a.submenu&&a.submenu.contains(e.target))&&d()},U=e=>{e.key==="Escape"&&d()};function M(e,n,t,o){oe();const s=document.createElement("div");s.className="dm-sc-menu",s.style.cssText=B,a={root:s,textarea:e,span:n,submenu:null};const i=n&&(re.get(n.name)||j.get(n.name)),c=n&&Y.has(n.name)?w.filter(r=>r.name in n.attrs):[];i&&pe(s,i);for(const r of c)Ee(s,r);(i||c.length)&&s.appendChild(N()),s.appendChild(y("Celebrations\u2026",()=>ge())),s.appendChild(y("Add effect\u2026",()=>Ce())),s.appendChild(y("Insert\u2026",()=>ve()));const l=e.selectionStart!==e.selectionEnd;(n||l)&&s.appendChild(y(l?"Wrap selection in\u2026":"Wrap in\u2026",()=>we())),document.body.appendChild(s),J(s,t,o),document.addEventListener("mousedown",q,!0),document.addEventListener("keydown",U,!0),window.addEventListener("scroll",K,!0),window.I&&I.scan(s)}function N(){const e=document.createElement("div");return e.style.cssText=ue,e}function C(e){const n=document.createElement("div");return n.style.cssText=S,n.textContent=e,n}function pe(e,n){e.appendChild(C(`${n.label} options`));const t=f(document.createElement("button"));t.type="button",t.style.cssText=p,t.innerHTML='<span data-icon="edit" data-icon-size="13" style="display:inline-flex;align-items:center;"></span>',t.appendChild(document.createTextNode(`Edit ${n.label}\u2026`)),t.addEventListener("click",()=>{const{textarea:i,span:c}=a;d(),$(i,{...n,attrs:z(n,c.attrs)},{span:c})}),e.appendChild(t);for(const i of n.actions||[]){const c=f(document.createElement("button"));c.type="button",c.style.cssText=p,c.innerHTML=`<span data-icon="${i.icon||"zap"}" data-icon-size="13" style="display:inline-flex;align-items:center;"></span>`,c.appendChild(document.createTextNode(i.label)),c.addEventListener("click",()=>{const{textarea:l,span:r}=a;if(i.remove){ne(l,r.openTagStart,r.openTagEnd,""),d();return}a.span=D(l,r,i.set||{}),d()}),e.appendChild(c)}const o=Array.isArray(n.quickAttrs)?new Set(n.quickAttrs):null,s=z(n,a.span.attrs).filter(i=>!o||o.has(i.name));(n.actions||[]).length&&s.length&&e.appendChild(N());for(const i of s)e.appendChild(V(i))}function V(e,n=e.name){const t=a.span.attrs[n];switch(e.type){case"checkbox":return me(e,n,Z(t,e.default));case"select":return be(e,n,t);case"lookup":return ye(e,n,t);case"colour":return he(e,n,t);case"icon":return xe(e,n,t);default:return fe(e,n,t)}}function x(e,n){if(a.span=P(a.textarea,a.span,e,n),e==="theme"){const{textarea:t,span:o,root:s}=a,i=s.getBoundingClientRect();d(),M(t,o,i.left,i.top)}}function me(e,n,t){const o=f(document.createElement("label"));o.style.cssText=p;const s=document.createElement("input");return s.type="checkbox",s.checked=t,s.addEventListener("change",()=>x(n,ee(e,s.checked))),o.appendChild(s),o.appendChild(document.createTextNode(e.label)),o}function fe(e,n,t){const o=document.createElement("div");o.style.cssText=p+"cursor:default;";const s=document.createElement("span");s.textContent=e.label,s.style.cssText="white-space:nowrap;color:var(--dm-text-muted,#9a9aac);";const i=document.createElement("input");i.type=e.type==="number"?"number":"text",i.value=t===!0||t==null?"":t,e.default!=null&&e.default!==""&&(i.placeholder=String(e.default)),i.style.cssText=F;let c=null;return i.addEventListener("input",()=>{clearTimeout(c),c=setTimeout(()=>x(n,i.value.trim()),180)}),i.addEventListener("mousedown",l=>l.stopPropagation()),o.appendChild(s),o.appendChild(i),o}function he(e,n,t){const o=document.createElement("div");o.style.cssText=p+"cursor:default;";const s=document.createElement("span");s.textContent=e.label,s.style.flex="1";const i=document.createElement("input");return i.type="color",typeof t=="string"&&/^#/.test(t)?i.value=t:typeof e.default=="string"&&/^#/.test(e.default)&&(i.value=e.default),i.addEventListener("input",()=>x(n,i.value)),o.appendChild(s),o.appendChild(i),o}function be(e,n,t){const o=t==null||t===!0?e.default??"":t;return y(`${e.label}${o!==""?`: ${o}`:""}`,()=>{const s=g();for(const[i,c]of e.options||[]){const l=f(document.createElement("button"));l.type="button",l.style.cssText=p,l.textContent=c,i===o&&(l.style.fontWeight="700"),l.addEventListener("click",()=>{x(n,i),v()}),s.appendChild(l)}return s})}function xe(e,n,t){const o=t==null||t===!0?"":String(t),s=o?`${e.label}: ${o}`:e.label;return y(s,()=>{const i=g();i.style.width="232px";const c=document.createElement("input");c.type="text",c.placeholder="Search icons\u2026",c.style.cssText=F+"margin:6px;width:calc(100% - 12px);",c.addEventListener("mousedown",L=>L.stopPropagation()),i.appendChild(c);const l=f(document.createElement("button"));l.type="button",l.style.cssText=p,l.textContent="- none -",o||(l.style.fontWeight="700"),l.addEventListener("click",()=>{x(n,null),v()}),i.appendChild(l);const r=document.createElement("div");r.style.cssText="display:flex;flex-wrap:wrap;gap:2px;padding:4px 6px;max-height:220px;overflow-y:auto;",i.appendChild(r);const m=96,T=()=>{const L=typeof I<"u"&&typeof I.list=="function"?I.list():[],R=c.value.trim().toLowerCase(),_=R?L.filter(u=>u.toLowerCase().includes(R)):L;r.replaceChildren();for(const u of _.slice(0,m)){const b=f(document.createElement("button"));b.type="button",b.title=u,b.style.cssText="width:26px;height:26px;display:inline-flex;align-items:center;justify-content:center;background:none;border:1px solid transparent;border-radius:4px;cursor:pointer;color:inherit;",u===o&&(b.style.borderColor="var(--dm-primary,#5b8cff)");const k=document.createElement("span");k.setAttribute("data-icon",u),k.setAttribute("data-icon-size","15"),k.style.cssText="display:inline-flex;align-items:center;",b.appendChild(k),b.addEventListener("click",()=>{x(n,u),v()}),r.appendChild(b)}if(_.length>m){const u=document.createElement("div");u.style.cssText=S,u.textContent=`${_.length-m} more - refine search`,r.appendChild(u)}if(!_.length){const u=document.createElement("div");u.style.cssText=S,u.textContent="No icons match",r.appendChild(u)}window.I&&I.scan(r)};let h=null;return c.addEventListener("input",()=>{clearTimeout(h),h=setTimeout(T,120)}),T(),setTimeout(()=>c.focus(),0),i})}function ye(e,n,t){const o=t==null||t===!0?e.default??"":t;return y(`${e.label}${o!==""?`: ${o}`:""}`,()=>{const s=g();s.style.minHeight="48px";const i=typeof E<"u"&&E.loader?E.loader(s,{type:"dots"}):null;return ce(e.source).then(c=>{if(i&&i.destroy(),!a||a.submenu!==s)return;if(s.style.minHeight="",!c.length){const m=document.createElement("div");m.style.cssText=S,m.textContent="Nothing found",s.appendChild(m)}const l=c.some(([m])=>m===o),r=[["","- none -"],...c];o!==""&&!l&&r.push([o,`${o} (missing)`]);for(const[m,T]of r){const h=f(document.createElement("button"));h.type="button",h.style.cssText=p,h.textContent=T,m===o&&(h.style.fontWeight="700"),h.addEventListener("click",()=>{x(n,m===""?null:m),v()}),s.appendChild(h)}}),s})}function Ee(e,n){e.appendChild(C(`Effect: ${n.label}`));for(const o of n.attrs||[])e.appendChild(V(o,`${n.name}-${o.name}`));const t=f(document.createElement("button"));t.type="button",t.style.cssText=p,t.innerHTML='<span data-icon="trash" data-icon-size="13" style="display:inline-flex;align-items:center;"></span> Remove effect',t.addEventListener("click",()=>{const o={};for(const s of te(a.span.attrs,n.name))o[s]=null;D(a.textarea,a.span,o),d()}),e.appendChild(t)}function ge(){const e=g();e.appendChild(C("Seasonal themes"));for(const[n,t]of[["auto","Auto (date-detected)"],...Object.entries(Q).map(([o,s])=>[o,s.label])]){const o=f(document.createElement("button"));o.type="button",o.style.cssText=p,o.textContent=t,o.addEventListener("click",()=>{O(a.textarea,`[celebrate theme="${n}" /]`),d()}),e.appendChild(o)}e.appendChild(N()),e.appendChild(C("Celebration effects"));for(const n of["butterflies","ticker-tape","firework","fireworks"]){const t=j.get(n),o=f(document.createElement("button"));o.type="button",o.style.cssText=p,o.textContent=t.label,o.addEventListener("click",()=>{const s=a.textarea;d(),$(s,t)}),e.appendChild(o)}return e}function Ce(){const e=g(),n=a.span,t=n&&Y.has(n.name)?n.name:null;for(const o of[...new Set(w.map(s=>s.category))]){const s=w.filter(i=>i.category===o);if(s.length){e.appendChild(C(o));for(const i of s){const c=t&&(i.hosts||[]).includes(t)&&!(i.name in n.attrs),l=f(document.createElement("button"));if(l.type="button",l.style.cssText=p+"justify-content:space-between;",l.appendChild(document.createTextNode(i.label)),c){const r=document.createElement("span");r.textContent=`inject \u2192 [${t}]`,r.style.cssText="opacity:.6;font-size:.7rem;",l.appendChild(r)}l.addEventListener("click",()=>{if(c)P(a.textarea,a.span,i.name,!0);else{const r=i.selfClosing?`[${i.name} /]`:`[${i.name}]
|
|
1
|
+
import{SHORTCODES as A}from"./shortcode-registry.js";import{EFFECTS as T,CELEBRATION_THEMES as Q,getEffectAttrs as P}from"./effect-defs.js";import{boolState as Z,boolValue as ee,findEnclosingShortcode as H,setAttr as $,setAttrs as D,effectAttrKeys as te}from"./shortcode-tags.js";import{insertAtCursor as O,replaceRange as ne}from"./markdown-toolbar.js";import{clearLookupCache as oe,lookupOptions as se}from"./shortcode-lookups.js";import{insertMenuGroups as ie,insertShortcodeByName as ae}from"./shortcode-insert.js";import{openShortcodeForm as M}from"./shortcode-form.js";import{pickMedia as ce}from"./media-picker.js";function re(e){return se(e,a?.span?.attrs||{})}const le=A.map(e=>({name:e.name,selfClosing:!!e.selfClosing})),de=new Map(A.map(e=>[e.name,e])),j=new Map(T.map(e=>[e.name,e])),ue=T.map(e=>({name:e.name,selfClosing:!!e.selfClosing})),B=[...le,...ue],W=new Set(["card","box","hero","banner","col","button"]);let a=null;const Y="position:fixed;z-index:10000;min-width:210px;max-height:70vh;overflow-y:auto;background:var(--dm-surface,#1c1c30);border:1px solid var(--dm-border,#2a2a40);border-radius:6px;box-shadow:var(--dm-shadow-lg);padding:.3rem;font-size:.83rem;color:var(--dm-text,#e5e5e5);",m="display:flex;align-items:center;gap:.5rem;width:100%;text-align:left;padding:.35rem .55rem;border:none;background:transparent;color:inherit;border-radius:4px;cursor:pointer;font-size:.83rem;",S="padding:.3rem .55rem;color:var(--dm-text-muted,#8a8a9a);font-size:.68rem;text-transform:uppercase;letter-spacing:.06em;",F="flex:1;min-width:0;padding:.2rem .4rem;background:var(--dm-input-bg,#12121e);border:1px solid var(--dm-border,#333);border-radius:3px;color:var(--dm-text,#eee);font-size:.8rem;",pe="height:1px;background:var(--dm-border,#2a2a40);margin:.3rem .2rem;";function f(e){return e.addEventListener("mouseenter",()=>{e.style.background="var(--dm-primary,#4338ca)",e.style.color="var(--dm-primary-text,#fff)"}),e.addEventListener("mouseleave",()=>{e.style.background="transparent",e.style.color="inherit"}),e}export function attachContextMenu(e){return typeof Domma>"u"||!Domma.elements?.contextMenu?(e.addEventListener("contextmenu",n=>{n.preventDefault(),d();const t=H(e,B);N(e,t,n.clientX,n.clientY)}),null):Domma.elements.contextMenu(e,{inherit:!1,cursor:!1,render:n=>{d();const t=H(e,B);N(e,t,n.x,n.y)}})}function d(){a&&(w(),a.root.remove(),document.removeEventListener("mousedown",q,!0),document.removeEventListener("keydown",U,!0),window.removeEventListener("scroll",K,!0),a=null)}const q=e=>{a&&!a.root.contains(e.target)&&!(a.submenu&&a.submenu.contains(e.target))&&d()},K=e=>{a&&!a.root.contains(e.target)&&!(a.submenu&&a.submenu.contains(e.target))&&d()},U=e=>{e.key==="Escape"&&d()};function N(e,n,t,o){oe();const s=document.createElement("div");s.className="dm-sc-menu",s.style.cssText=Y,a={root:s,textarea:e,span:n,submenu:null};const i=n&&(de.get(n.name)||j.get(n.name)),r=n&&W.has(n.name)?T.filter(l=>l.name in n.attrs):[];i&&me(s,i);for(const l of r)ge(s,l);(i||r.length)&&s.appendChild(R()),s.appendChild(g("Celebrations\u2026",()=>Ce())),s.appendChild(g("Add effect\u2026",()=>ve())),s.appendChild(g("Insert\u2026",()=>we()));const c=e.selectionStart!==e.selectionEnd;(n||c)&&s.appendChild(g(c?"Wrap selection in\u2026":"Wrap in\u2026",()=>Te())),document.body.appendChild(s),J(s,t,o),document.addEventListener("mousedown",q,!0),document.addEventListener("keydown",U,!0),window.addEventListener("scroll",K,!0),window.I&&I.scan(s)}function R(){const e=document.createElement("div");return e.style.cssText=pe,e}function v(e){const n=document.createElement("div");return n.style.cssText=S,n.textContent=e,n}function me(e,n){e.appendChild(v(`${n.label} options`));const t=f(document.createElement("button"));t.type="button",t.style.cssText=m,t.innerHTML='<span data-icon="edit" data-icon-size="13" style="display:inline-flex;align-items:center;"></span>',t.appendChild(document.createTextNode(`Edit ${n.label}\u2026`)),t.addEventListener("click",()=>{const{textarea:i,span:r}=a;d(),M(i,{...n,attrs:P(n,r.attrs)},{span:r})}),e.appendChild(t);for(const i of n.actions||[]){const r=f(document.createElement("button"));r.type="button",r.style.cssText=m,r.innerHTML=`<span data-icon="${i.icon||"zap"}" data-icon-size="13" style="display:inline-flex;align-items:center;"></span>`,r.appendChild(document.createTextNode(i.label)),r.addEventListener("click",()=>{const{textarea:c,span:l}=a;if(i.remove){ne(c,l.openTagStart,l.openTagEnd,""),d();return}a.span=D(c,l,i.set||{}),d()}),e.appendChild(r)}const o=Array.isArray(n.quickAttrs)?new Set(n.quickAttrs):null,s=P(n,a.span.attrs).filter(i=>!o||o.has(i.name));(n.actions||[]).length&&s.length&&e.appendChild(R());for(const i of s)e.appendChild(V(i))}function V(e,n=e.name){const t=a.span.attrs[n];switch(e.type){case"checkbox":return fe(e,n,Z(t,e.default));case"select":return xe(e,n,t);case"lookup":return Ee(e,n,t);case"colour":return be(e,n,t);case"icon":return ye(e,n,t);default:return he(e,n,t)}}function y(e,n){if(a.span=$(a.textarea,a.span,e,n),e==="theme"){const{textarea:t,span:o,root:s}=a,i=s.getBoundingClientRect();d(),N(t,o,i.left,i.top)}}function fe(e,n,t){const o=f(document.createElement("label"));o.style.cssText=m;const s=document.createElement("input");return s.type="checkbox",s.checked=t,s.addEventListener("change",()=>y(n,ee(e,s.checked))),o.appendChild(s),o.appendChild(document.createTextNode(e.label)),o}function he(e,n,t){const o=document.createElement("div");o.style.cssText=m+"cursor:default;";const s=document.createElement("span");s.textContent=e.label,s.style.cssText="white-space:nowrap;color:var(--dm-text-muted,#9a9aac);";const i=document.createElement("input");i.type=e.type==="number"?"number":"text",i.value=t===!0||t==null?"":t,e.default!=null&&e.default!==""&&(i.placeholder=String(e.default)),i.style.cssText=F;let r=null;if(i.addEventListener("input",()=>{clearTimeout(r),r=setTimeout(()=>y(n,i.value.trim()),180)}),i.addEventListener("mousedown",c=>c.stopPropagation()),o.appendChild(s),o.appendChild(i),e.type==="image"){const c=document.createElement("button");c.type="button",c.textContent="Browse",c.title="Choose from Media",c.style.cssText="padding:2px 8px;background:transparent;border:1px solid var(--dm-border,#333);border-radius:4px;color:inherit;cursor:pointer;flex-shrink:0;font:inherit;",c.addEventListener("mousedown",l=>l.stopPropagation()),c.addEventListener("click",async()=>{const{textarea:l,span:u}=a;d();const b=await ce({current:i.value.trim()});b&&l.isConnected&&$(l,u,n,b)}),o.appendChild(c)}return o}function be(e,n,t){const o=document.createElement("div");o.style.cssText=m+"cursor:default;";const s=document.createElement("span");s.textContent=e.label,s.style.flex="1";const i=document.createElement("input");return i.type="color",typeof t=="string"&&/^#/.test(t)?i.value=t:typeof e.default=="string"&&/^#/.test(e.default)&&(i.value=e.default),i.addEventListener("input",()=>y(n,i.value)),o.appendChild(s),o.appendChild(i),o}function xe(e,n,t){const o=t==null||t===!0?e.default??"":t;return g(`${e.label}${o!==""?`: ${o}`:""}`,()=>{const s=C();for(const[i,r]of e.options||[]){const c=f(document.createElement("button"));c.type="button",c.style.cssText=m,c.textContent=r,i===o&&(c.style.fontWeight="700"),c.addEventListener("click",()=>{y(n,i),w()}),s.appendChild(c)}return s})}function ye(e,n,t){const o=t==null||t===!0?"":String(t),s=o?`${e.label}: ${o}`:e.label;return g(s,()=>{const i=C();i.style.width="232px";const r=document.createElement("input");r.type="text",r.placeholder="Search icons\u2026",r.style.cssText=F+"margin:6px;width:calc(100% - 12px);",r.addEventListener("mousedown",L=>L.stopPropagation()),i.appendChild(r);const c=f(document.createElement("button"));c.type="button",c.style.cssText=m,c.textContent="- none -",o||(c.style.fontWeight="700"),c.addEventListener("click",()=>{y(n,null),w()}),i.appendChild(c);const l=document.createElement("div");l.style.cssText="display:flex;flex-wrap:wrap;gap:2px;padding:4px 6px;max-height:220px;overflow-y:auto;",i.appendChild(l);const u=96,b=()=>{const L=typeof I<"u"&&typeof I.list=="function"?I.list():[],z=r.value.trim().toLowerCase(),_=z?L.filter(p=>p.toLowerCase().includes(z)):L;l.replaceChildren();for(const p of _.slice(0,u)){const x=f(document.createElement("button"));x.type="button",x.title=p,x.style.cssText="width:26px;height:26px;display:inline-flex;align-items:center;justify-content:center;background:none;border:1px solid transparent;border-radius:4px;cursor:pointer;color:inherit;",p===o&&(x.style.borderColor="var(--dm-primary,#5b8cff)");const k=document.createElement("span");k.setAttribute("data-icon",p),k.setAttribute("data-icon-size","15"),k.style.cssText="display:inline-flex;align-items:center;",x.appendChild(k),x.addEventListener("click",()=>{y(n,p),w()}),l.appendChild(x)}if(_.length>u){const p=document.createElement("div");p.style.cssText=S,p.textContent=`${_.length-u} more - refine search`,l.appendChild(p)}if(!_.length){const p=document.createElement("div");p.style.cssText=S,p.textContent="No icons match",l.appendChild(p)}window.I&&I.scan(l)};let h=null;return r.addEventListener("input",()=>{clearTimeout(h),h=setTimeout(b,120)}),b(),setTimeout(()=>r.focus(),0),i})}function Ee(e,n,t){const o=t==null||t===!0?e.default??"":t;return g(`${e.label}${o!==""?`: ${o}`:""}`,()=>{const s=C();s.style.minHeight="48px";const i=typeof E<"u"&&E.loader?E.loader(s,{type:"dots"}):null;return re(e.source).then(r=>{if(i&&i.destroy(),!a||a.submenu!==s)return;if(s.style.minHeight="",!r.length){const u=document.createElement("div");u.style.cssText=S,u.textContent="Nothing found",s.appendChild(u)}const c=r.some(([u])=>u===o),l=[["","- none -"],...r];o!==""&&!c&&l.push([o,`${o} (missing)`]);for(const[u,b]of l){const h=f(document.createElement("button"));h.type="button",h.style.cssText=m,h.textContent=b,u===o&&(h.style.fontWeight="700"),h.addEventListener("click",()=>{y(n,u===""?null:u),w()}),s.appendChild(h)}}),s})}function ge(e,n){e.appendChild(v(`Effect: ${n.label}`));for(const o of n.attrs||[])e.appendChild(V(o,`${n.name}-${o.name}`));const t=f(document.createElement("button"));t.type="button",t.style.cssText=m,t.innerHTML='<span data-icon="trash" data-icon-size="13" style="display:inline-flex;align-items:center;"></span> Remove effect',t.addEventListener("click",()=>{const o={};for(const s of te(a.span.attrs,n.name))o[s]=null;D(a.textarea,a.span,o),d()}),e.appendChild(t)}function Ce(){const e=C();e.appendChild(v("Seasonal themes"));for(const[n,t]of[["auto","Auto (date-detected)"],...Object.entries(Q).map(([o,s])=>[o,s.label])]){const o=f(document.createElement("button"));o.type="button",o.style.cssText=m,o.textContent=t,o.addEventListener("click",()=>{O(a.textarea,`[celebrate theme="${n}" /]`),d()}),e.appendChild(o)}e.appendChild(R()),e.appendChild(v("Celebration effects"));for(const n of["butterflies","ticker-tape","firework","fireworks"]){const t=j.get(n),o=f(document.createElement("button"));o.type="button",o.style.cssText=m,o.textContent=t.label,o.addEventListener("click",()=>{const s=a.textarea;d(),M(s,t)}),e.appendChild(o)}return e}function ve(){const e=C(),n=a.span,t=n&&W.has(n.name)?n.name:null;for(const o of[...new Set(T.map(s=>s.category))]){const s=T.filter(i=>i.category===o);if(s.length){e.appendChild(v(o));for(const i of s){const r=t&&(i.hosts||[]).includes(t)&&!(i.name in n.attrs),c=f(document.createElement("button"));if(c.type="button",c.style.cssText=m+"justify-content:space-between;",c.appendChild(document.createTextNode(i.label)),r){const l=document.createElement("span");l.textContent=`inject \u2192 [${t}]`,l.style.cssText="opacity:.6;font-size:.7rem;",c.appendChild(l)}c.addEventListener("click",()=>{if(r)$(a.textarea,a.span,i.name,!0);else{const l=i.selfClosing?`[${i.name} /]`:`[${i.name}]
|
|
2
2
|
Content
|
|
3
|
-
[/${i.name}]`;O(a.textarea,
|
|
3
|
+
[/${i.name}]`;O(a.textarea,l)}d()}),e.appendChild(c)}}}return e}function g(e,n){const t=f(document.createElement("button"));t.type="button",t.style.cssText=m+"justify-content:space-between;",t.appendChild(document.createTextNode(e));const o=document.createElement("span");return o.setAttribute("data-icon","chevron-right"),o.setAttribute("data-icon-size","12"),o.style.cssText="opacity:.6;display:inline-flex;align-items:center;flex-shrink:0;",t.appendChild(o),t.addEventListener("mouseenter",()=>G(t,n)),t.addEventListener("click",s=>{s.stopPropagation(),G(t,n)}),t}function C(){const e=document.createElement("div");return e.className="dm-sc-submenu",e.style.cssText=Y,e}function G(e,n){w();const t=n();a.submenu=t,document.body.appendChild(t);const o=e.getBoundingClientRect();J(t,o.right+2,o.top,o.left-2),window.I&&I.scan(t)}function w(){a&&a.submenu&&(a.submenu.remove(),a.submenu=null)}function X(e){const n=f(document.createElement("button"));if(n.type="button",n.style.cssText=m,e.icon){const t=document.createElement("span");t.setAttribute("data-icon",e.icon),t.setAttribute("data-icon-size","14"),t.style.cssText="opacity:.75;display:inline-flex;align-items:center;flex-shrink:0;",n.appendChild(t)}return n.appendChild(document.createTextNode(e.label)),n}function we(){const e=C();for(const{category:n,items:t}of ie()){e.appendChild(v(n));for(const o of t){const s=X(o);s.addEventListener("click",()=>{const i=a.textarea;d(),ae(o.name,i)}),e.appendChild(s)}}return e}function Te(){const e=C();for(const n of A.filter(t=>t.wrappable||t.container)){const t=X(n);t.addEventListener("click",()=>{const o=a.textarea;d(),M(o,n)}),e.appendChild(t)}return e}function J(e,n,t,o){e.style.left="0px",e.style.top="0px";const s=e.getBoundingClientRect();let i=n;n+s.width>window.innerWidth-8&&(i=o!=null?o-s.width:n-s.width);let r=t;t+s.height>window.innerHeight-8&&(r=Math.max(8,window.innerHeight-s.height-8)),e.style.left=`${Math.max(8,i)}px`,e.style.top=`${Math.max(8,r)}px`}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{replaceRange as
|
|
1
|
+
import{replaceRange as te}from"./markdown-toolbar.js";import{boolState as ne,boolValue as oe,parseAttrs as J,serialiseTag as Q,setAttrs as le}from"./shortcode-tags.js";import{SHORTCODES as se}from"./shortcode-registry.js";import{clearLookupCache as re,lookupOptions as ie}from"./shortcode-lookups.js";import{PREVIEW_RENDERERS as ce}from"./shortcode-preview.js";import{makeCheckbox as ae,makeColourInput as de,makeField as y,makeIconInput as U,makeImageInput as X,makeLivePreview as pe,makeSelect as M,makeTextInput as D}from"./shortcode-modal.js";const ue=new Map(se.map(e=>[e.name,e])),Z=6;export function templateAttrs(e){const n=String(e.template||"").match(new RegExp(`^\\[${e.name}([\\s\\S]*?)\\s*/?\\]`));return n?J(n[1]):{}}export function templateBody(e){if(e.selfClosing)return"";const n=String(e.template||"").match(new RegExp(`^\\[${e.name}[^\\]]*\\]([\\s\\S]*)\\[/${e.name}\\]$`));return n?n[1].replace(/^\n/,"").replace(/\n$/,""):""}export function templateChildren(e){if(!e.children)return[];const n=e.children.name,i=new RegExp(`\\[${n}([^\\]]*)\\]([\\s\\S]*?)\\[/${n}\\]`,"g"),d=[];for(const s of templateBody(e).matchAll(i))d.push({attrs:J(s[1]),body:s[2].replace(/^\n/,"").replace(/\n$/,"")});return d}const me=new Set(["lookup","url"]);export function seedAttrs(e,n){const i=new Map((e.attrs||[]).map(s=>[s.name,s.type])),d={};for(const[s,c]of Object.entries(n))me.has(i.get(s))||(d[s]=c);return d}export function buildSnippet(e,n,i=""){const d=Q(e.name,n,e.selfClosing);if(e.selfClosing)return d;const s=`[/${e.name}]`;return e.inline?`${d}${i}${s}`:`${d}
|
|
2
2
|
${i}
|
|
3
3
|
${s}`}export function buildChildrenBody(e,n){return n.map(i=>buildSnippet(e,i.attrs,i.body)).join(`
|
|
4
|
-
`)}export function emitSnippet(e,n,i,d){const s=(e.formats||[]).find(
|
|
4
|
+
`)}export function emitSnippet(e,n,i,d){const s=(e.formats||[]).find(c=>c.value===d);if(s&&typeof s.emit=="function"){const c=s.emit(n,i);if(c!=null)return c}return buildSnippet(e,n,i)}const fe="display:block;font-size:.7rem;font-weight:600;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;margin-bottom:.25rem;";function he(e,n,i,d){const s=n===!0||n==null?"":String(n);if(e.type==="checkbox"){const l=ae(e.label),r=l.querySelector("input");return r.checked=ne(n,e.default),r.addEventListener("change",i),{el:l,bare:!0,get:()=>oe(e,r.checked)}}if(e.type==="select"){const l=e.options.some(([C])=>C==="")?e.options:[["","- none -"],...e.options],r=M(l);return r.value=s,r.addEventListener("change",i),{el:y(e.label,r),get:()=>r.value||null}}if(e.type==="icon"){const{el:l,input:r}=U("icon name (optional)",s);return r.addEventListener("input",i),{el:y(e.label,l),get:()=>r.value.trim()||null}}if(e.type==="image"){const{el:l,input:r}=X("/media/photo.jpg",s);return r.addEventListener("input",i),{el:y(e.label,l),get:()=>r.value.trim()||null}}if(e.type==="colour"){const{el:l,input:r}=de("#0f172a or a theme colour",s);return r.addEventListener("input",i),{el:y(e.label,l),get:()=>r.value.trim()||null}}if(e.type==="lookup"){const l=M([["","Loading\u2026"]]);l.disabled=!0,l.addEventListener("change",i);let r;const C=()=>{const h=d(),z=e.source==="collection-fields"?String(h.slug??""):e.source;z!==r&&(r=z,l.disabled=!0,ie(e.source,h).then(u=>{const v=l.value||s,b=u.some(([S])=>S===v),w=[["","- none -"],...u];v&&!b&&w.push([v,`${v} (missing)`]),l.replaceChildren();for(const[S,x]of w){const T=document.createElement("option");T.value=S,T.textContent=x,l.appendChild(T)}l.value=v,l.disabled=!1,i()}))};return C(),{el:y(e.label,l),get:()=>l.value||null,refresh:e.source==="collection-fields"?C:null}}const c=D(e.type==="url"?"/about or https://example.com":"",s);return e.type==="number"&&(c.type="number"),c.addEventListener("input",i),{el:y(e.label,c),get:()=>c.value.trim()||null}}export function openShortcodeForm(e,n,i={}){const{span:d=null,defaults:s=null}=i,c=!!d;re();const l=e.selectionStart,r=e.selectionEnd,C=e.value.slice(l,r),h=n.children?ue.get(n.children.name):null,z={...seedAttrs(n,templateAttrs(n)),...s||{}},u=document.createElement("div");u.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const v=[],b=[];let w=()=>{};const S=()=>{const t={};for(const{attr:o,w:p}of v){const a=p.get();a!=null&&a!==""&&(t[o.name]=a)}return t},x=()=>w(),T=()=>S();let O=null;!c&&n.formats?.length&&(O=M(n.formats.map(t=>[t.value,t.label])),O.addEventListener("change",x),u.appendChild(y("Format",O)));const $=n.attrs||[],P=$.length>Z+2?Z:$.length,F=(t,o)=>{const p=c?d.attrs[t.name]:z[t.name],a=he(t,p,x,T);v.push({attr:t,w:a,initial:a.get()}),o.appendChild(a.el)};for(const t of $.slice(0,P))F(t,u);if(P<$.length){const t=document.createElement("details");t.style.cssText="border-top:1px solid var(--dm-border,#333);padding-top:.6rem;";const o=document.createElement("summary");o.textContent=`More options (${$.length-P})`,o.style.cssText="cursor:pointer;font-size:.75rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",t.appendChild(o);const p=document.createElement("div");p.style.cssText="display:flex;flex-direction:column;gap:.75rem;padding-top:.75rem;",t.appendChild(p);for(const a of $.slice(P))F(a,p);u.appendChild(t)}let k=null,L=null;const N=document.createElement("div");if(!c&&h){const t=document.createElement("div");t.style.cssText=fe,t.textContent=`${h.label}s`,u.appendChild(t),N.style.cssText="display:flex;flex-direction:column;gap:.4rem;",u.appendChild(N),L=document.createElement("button"),L.type="button",L.textContent=`+ Add ${h.label.toLowerCase()}`,L.style.cssText="padding:.35rem .75rem;background:transparent;border:1px dashed var(--dm-border,#555);border-radius:4px;color:var(--dm-text-muted,#aaa);cursor:pointer;font-size:.85em;align-self:flex-start;",L.addEventListener("click",()=>{q({attrs:{},body:templateBody(h)||"Content"}),w()}),u.appendChild(L);const o=templateChildren(n),p=o.length?o:[{attrs:{},body:"Content"}];for(const a of p)q({attrs:seedAttrs(h,a.attrs),body:a.body});C&&(b[0].bodyInput.value=C)}else!c&&!n.selfClosing&&(k=document.createElement("textarea"),k.rows=n.inline?2:4,k.value=C||templateBody(n),k.style.cssText="width:100%;padding:.4rem .6rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text,#eee);font-size:.9em;font-family:inherit;box-sizing:border-box;resize:vertical;",k.addEventListener("input",x),u.appendChild(y("Content",k)));function q(t){if(b.length>=(n.children.max??20))return;const o=document.createElement("div");o.style.cssText="display:flex;gap:.35rem;align-items:center;";const p=[];for(const m of h.attrs||[])if(m.type==="icon"){const{el:f,input:B}=U(m.label.toLowerCase(),t.attrs[m.name]||"");f.style.flex=".7",B.addEventListener("input",x),p.push({attr:m,get:()=>B.value.trim()||null}),o.appendChild(f)}else if(m.type==="image"){const{el:f,input:B}=X(m.label,t.attrs[m.name]||"");f.style.flex="1",B.addEventListener("input",x),p.push({attr:m,get:()=>B.value.trim()||null}),o.appendChild(f)}else if(m.type==="select"){const f=M(m.options);f.value=t.attrs[m.name]||m.options[0][0],f.style.flex=".7",f.addEventListener("change",x),p.push({attr:m,get:()=>f.value||null}),o.appendChild(f)}else{const f=D(m.label,t.attrs[m.name]||"");f.style.flex="1",f.addEventListener("input",x),p.push({attr:m,get:()=>f.value.trim()||null}),o.appendChild(f)}const a=D("Content",t.body||"");a.style.flex="1.2",a.addEventListener("input",x),o.appendChild(a);const g=document.createElement("button");g.type="button",g.textContent="\xD7",g.style.cssText="padding:.3rem .5rem;background:transparent;border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text-muted,#aaa);cursor:pointer;font-size:.85em;flex-shrink:0;";const G={row:o,fields:p,bodyInput:a,remove:g};g.addEventListener("click",()=>{b.length<=(n.children.min??1)||(b.splice(b.indexOf(G),1),o.remove(),w())}),o.appendChild(g),b.push(G),N.appendChild(o),window.I?.scan?.(o)}const Y=ce[n.preview];let R=null;if(Y){const t=document.createElement("div");t.style.cssText="background:var(--dm-background-alt,#111);border:1px solid var(--dm-border,#333);border-radius:4px;padding:.75rem;min-height:2.5rem;display:flex;align-items:center;overflow-x:auto;",R=document.createElement("span"),t.appendChild(R),u.appendChild(y("Preview",t))}const H=pe();u.appendChild(y(c?"Tag preview":"Shortcode preview",H.el));const W=document.createElement("div");W.style.cssText="display:flex;justify-content:flex-end;gap:.75rem;padding-top:.75rem;border-top:1px solid var(--dm-border,#333);";const A=document.createElement("button");A.type="button",A.className="btn btn-ghost",A.textContent="Cancel";const I=document.createElement("button");I.type="button",I.className="btn btn-primary",I.textContent=c?"Apply":`Insert ${n.label}`,W.appendChild(A),W.appendChild(I),u.appendChild(W);const V=()=>h&&b.length?buildChildrenBody(h,b.map(t=>({attrs:Object.fromEntries(t.fields.map(o=>[o.attr.name,o.get()]).filter(([,o])=>o!=null)),body:t.bodyInput.value}))):k?k.value:templateBody(n),K=()=>emitSnippet(n,S(),V(),O?.value),ee=t=>{if(n.inline||n.selfClosing||!t.startsWith("["))return t;const o=e.value.slice(0,l),p=e.value.slice(r),a=o===""||o.endsWith(`
|
|
5
5
|
`)?"":`
|
|
6
6
|
`,g=p===""||p.startsWith(`
|
|
7
7
|
`)?"":`
|
|
8
|
-
`;return`${a}${t}${g}`};w=()=>{L&&(L.disabled=b.length>=(n.children.max??20));for(const{w:t}of v)t.refresh?.();if(R){const t=
|
|
8
|
+
`;return`${a}${t}${g}`};w=()=>{L&&(L.disabled=b.length>=(n.children.max??20));for(const{w:t}of v)t.refresh?.();if(R){const t=Y(c?{...d.attrs,..._()}:S(),c?"":V());R.style.cssText=t.css,R.textContent=t.text}H.update(c?Q(n.name,{...d.attrs,..._()},d.selfClosing):K())};function _(){const t={};for(const{attr:o,w:p,initial:a}of v){const g=p.get();g!==a&&(t[o.name]=g)}return t}const j=E.slideover({title:c?`Edit ${n.label}`:`Insert ${n.label}`,size:h?"lg":"md",position:"right",content:u});return j.open(),window.I?.scan?.(u),w(),A.addEventListener("click",()=>j.close()),I.addEventListener("click",()=>{if(j.close(),c)le(e,d,_());else{const t=ee(K());te(e,l,r,t),e.setSelectionRange(l+t.length,l+t.length)}e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}),requestAnimationFrame(()=>{u.querySelector("input:not([type=checkbox]):not([type=color]), select, textarea")?.focus()}),j}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{openIconPicker as
|
|
1
|
+
import{openIconPicker as s}from"./card-builder.js";import{pickMedia as c}from"./media-picker.js";const l="display:block;font-size:.7rem;font-weight:600;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;margin-bottom:.25rem;",d="width:100%;padding:.4rem .6rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text,#eee);font-size:.9em;box-sizing:border-box;";export function makeField(a,r){const t=document.createElement("div"),e=document.createElement("label");return e.style.cssText=l,e.textContent=a,t.appendChild(e),t.appendChild(r),t}export function makeSelect(a){const r=document.createElement("select");return r.style.cssText=d,a.forEach(([t,e])=>{const n=document.createElement("option");n.value=t,n.textContent=e,r.appendChild(n)}),r}export function makeTextInput(a="",r=""){const t=document.createElement("input");return t.type="text",t.placeholder=a,t.value=r,t.style.cssText=d,t}export function makeCheckbox(a){const r=document.createElement("label");r.style.cssText="display:flex;align-items:center;gap:.5rem;cursor:pointer;";const t=document.createElement("input");t.type="checkbox";const e=document.createElement("span");return e.style.cssText="font-size:.85em;color:var(--dm-text,#eee);",e.textContent=a,r.appendChild(t),r.appendChild(e),r}export function makeIconInput(a="",r=""){const t=document.createElement("div");t.style.cssText="display:flex;gap:.35rem;";const e=makeTextInput(a,r);e.style.flex="1";const n=document.createElement("button");n.type="button",n.title="Browse icons";const o=document.createElement("span");return o.setAttribute("data-icon","grid"),o.setAttribute("data-icon-size","14"),o.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;",n.appendChild(o),n.style.cssText="padding:.35rem .55rem;background:transparent;border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text-muted,#aaa);cursor:pointer;flex-shrink:0;display:inline-flex;align-items:center;",window.I?.scan?.(n),n.addEventListener("click",()=>s(i=>{e.value=i,e.dispatchEvent(new Event("input",{bubbles:!0}))})),t.appendChild(e),t.appendChild(n),{el:t,input:e}}export function makeImageInput(a="",r=""){const t=document.createElement("div");t.style.cssText="display:flex;gap:.35rem;";const e=makeTextInput(a,r);e.style.flex="1";const n=document.createElement("button");n.type="button",n.title="Choose from Media";const o=document.createElement("span");return o.setAttribute("data-icon","image"),o.setAttribute("data-icon-size","14"),o.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;",n.appendChild(o),n.style.cssText="padding:.35rem .55rem;background:transparent;border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text-muted,#aaa);cursor:pointer;flex-shrink:0;display:inline-flex;align-items:center;",window.I?.scan?.(n),n.addEventListener("click",async()=>{const i=await c({current:e.value.trim()});i&&(e.value=i,e.dispatchEvent(new Event("input",{bubbles:!0})))}),t.appendChild(e),t.appendChild(n),{el:t,input:e}}export function makeLivePreview(){const a=document.createElement("pre");return a.style.cssText="background:var(--dm-background-alt,#111);border:1px solid var(--dm-border,#333);border-radius:4px;padding:.5rem .75rem;font-size:.75em;color:var(--dm-text-muted,#aaa);white-space:pre-wrap;word-break:break-all;margin:0;max-height:120px;overflow:auto;",a.textContent="",{el:a,update(r){a.textContent=r}}}export function makeColourInput(a="",r=""){const t=document.createElement("div");t.style.cssText="display:flex;gap:.35rem;";const e=makeTextInput(a,r);e.style.flex="1";const n=document.createElement("input");return n.type="color",n.title="Pick a colour",n.style.cssText="width:2.2rem;height:auto;padding:0;background:none;border:1px solid var(--dm-border,#333);border-radius:4px;cursor:pointer;flex-shrink:0;",/^#[0-9a-f]{3,8}$/i.test(r)&&(n.value=r),n.addEventListener("input",()=>{e.value=n.value,e.dispatchEvent(new Event("input",{bubbles:!0}))}),e.addEventListener("input",()=>{/^#[0-9a-f]{6}$/i.test(e.value)&&(n.value=e.value)}),t.appendChild(e),t.appendChild(n),{el:t,input:e}}
|
|
@@ -33,11 +33,11 @@ Banner content
|
|
|
33
33
|
[/accordion]`,children:{name:"item",min:2,max:12},attrs:[{name:"multiple",type:"checkbox",label:"Allow multiple open"},{name:"id",type:"text",label:"ID"}]},{name:"item",label:"Item",icon:"list",category:"Components",child:!0,selfClosing:!1,container:!0,wrappable:!1,template:'[item title="Item title"]Content[/item]',inline:!0,attrs:[{name:"title",type:"text",label:"Title"}]},{name:"carousel",label:"Carousel",icon:"carousel-insert",category:"Components",selfClosing:!1,container:!0,wrappable:!1,template:`[carousel autoplay="true" interval="5000"]
|
|
34
34
|
[slide title="Slide 1" image="/media/photo.jpg"]Caption.[/slide]
|
|
35
35
|
[slide title="Slide 2"]Text-only slide.[/slide]
|
|
36
|
-
[/carousel]`,children:{name:"slide",min:2,max:12},attrs:[{name:"autoplay",type:"checkbox",label:"Autoplay"},{name:"interval",type:"number",label:"Interval (ms)"},{name:"loop",type:"checkbox",label:"Loop"},{name:"animation",type:"select",label:"Animation",options:[["slide","Slide"],["fade","Fade"],["crossfade","Crossfade"]]},{name:"animation-duration",type:"number",label:"Animation duration (ms)"},{name:"animation-easing",type:"text",label:"Animation easing"},{name:"id",type:"text",label:"ID"}]},{name:"slide",label:"Slide",icon:"image",category:"Components",child:!0,selfClosing:!1,container:!0,wrappable:!1,template:'[slide title="Slide title" image="/media/photo.jpg"]Caption[/slide]',inline:!0,attrs:[{name:"title",type:"text",label:"Title"},{name:"image",type:"
|
|
36
|
+
[/carousel]`,children:{name:"slide",min:2,max:12},attrs:[{name:"autoplay",type:"checkbox",label:"Autoplay"},{name:"interval",type:"number",label:"Interval (ms)"},{name:"loop",type:"checkbox",label:"Loop"},{name:"animation",type:"select",label:"Animation",options:[["slide","Slide"],["fade","Fade"],["crossfade","Crossfade"]]},{name:"animation-duration",type:"number",label:"Animation duration (ms)"},{name:"animation-easing",type:"text",label:"Animation easing"},{name:"id",type:"text",label:"ID"}]},{name:"slide",label:"Slide",icon:"image",category:"Components",child:!0,selfClosing:!1,container:!0,wrappable:!1,template:'[slide title="Slide title" image="/media/photo.jpg"]Caption[/slide]',inline:!0,attrs:[{name:"title",type:"text",label:"Title"},{name:"image",type:"image",label:"Image"}]},{name:"countdown",label:"Countdown",icon:"stopwatch",category:"Components",selfClosing:!0,container:!1,wrappable:!1,template:'[countdown to="2026-12-31" format="DD:HH:mm:ss" /]',attrs:[{name:"to",type:"text",label:"Target date (ISO)"},{name:"duration",type:"number",label:"Duration (seconds)"},{name:"format",type:"select",label:"Format",options:[["mm:ss","mm:ss"],["HH:mm:ss","HH:mm:ss"],["DD:HH:mm:ss","DD:HH:mm:ss"]]},{name:"id",type:"text",label:"ID"}]},{name:"timeline",label:"Timeline",icon:"activity",category:"Components",selfClosing:!1,container:!0,wrappable:!1,template:`[timeline layout="vertical" theme="modern"]
|
|
37
37
|
[event title="Launch" date="2025-01-15" status="completed"]Launched.[/event]
|
|
38
38
|
[/timeline]`,children:{name:"event",min:1,max:20},custom:"timeline",attrs:[{name:"layout",type:"select",label:"Layout",options:[["vertical","Vertical"],["centred","Centred"],["horizontal","Horizontal"]]},{name:"theme",type:"select",label:"Theme",options:[["minimal","Minimal"],["corporate","Corporate"],["modern","Modern"]]},{name:"mode",type:"select",label:"Mode",options:[["timeline","Timeline"],["roadmap","Roadmap"]]},{name:"class",type:"text",label:"CSS class"},{name:"id",type:"text",label:"ID"}]},{name:"event",label:"Event",icon:"dot",category:"Components",child:!0,selfClosing:!1,container:!0,wrappable:!1,template:'[event title="Milestone" date="2025-01-15" status="completed"]Description[/event]',inline:!0,attrs:[{name:"title",type:"text",label:"Title"},{name:"date",type:"text",label:"Date"},{name:"status",type:"select",label:"Status",options:[["planned","Planned"],["in-progress","In progress"],["completed","Completed"],["blocked","Blocked"]]},{name:"icon",type:"icon",label:"Icon"}]},{name:"hero",label:"Hero",icon:"hero",category:"Content",selfClosing:!1,container:!0,wrappable:!0,template:`[hero title="Welcome" tagline="Build something great" size="lg" variant="gradient-blue"]
|
|
39
39
|
Optional body content.
|
|
40
|
-
[/hero]`,attrs:[{name:"title",type:"text",label:"Title"},{name:"tagline",type:"text",label:"Tagline"},{name:"size",type:"select",label:"Size",options:[["","Default"],["sm","Small"],["lg","Large"],["xl","Extra large"],["full","Full"]]},{name:"fullwidth",type:"checkbox",label:"Break out full-width"},{name:"variant",type:"select",label:"Variant",options:[["","None"],["dark","Dark"],["primary","Primary"],["gradient-purple","Gradient purple"],["gradient-blue","Gradient blue"],["gradient-green","Gradient green"],["gradient-sunset","Gradient sunset"],["gradient-ocean","Gradient ocean"],["gradient-rose","Gradient rose"],["gradient-forest","Gradient forest"],["gradient-night","Gradient night"]]},{name:"image",type:"
|
|
40
|
+
[/hero]`,attrs:[{name:"title",type:"text",label:"Title"},{name:"tagline",type:"text",label:"Tagline"},{name:"size",type:"select",label:"Size",options:[["","Default"],["sm","Small"],["lg","Large"],["xl","Extra large"],["full","Full"]]},{name:"fullwidth",type:"checkbox",label:"Break out full-width"},{name:"variant",type:"select",label:"Variant",options:[["","None"],["dark","Dark"],["primary","Primary"],["gradient-purple","Gradient purple"],["gradient-blue","Gradient blue"],["gradient-green","Gradient green"],["gradient-sunset","Gradient sunset"],["gradient-ocean","Gradient ocean"],["gradient-rose","Gradient rose"],["gradient-forest","Gradient forest"],["gradient-night","Gradient night"]]},{name:"image",type:"image",label:"Background image"},{name:"overlay",type:"select",label:"Overlay",options:[["","None"],["light","Light"],["dark","Dark"],["darker","Darker"],["gradient","Gradient"],["gradient-reverse","Gradient reverse"]]},{name:"align",type:"select",label:"Content alignment",options:[["center","Centre"],["left","Left"]]},{name:"bg-fit",type:"select",label:"Background fit",options:[["","Fill area (default)"],["contain","Show whole image"],["cover","Fill area (crop)"]]},{name:"bg-x",type:"select",label:"Background horizontal position",options:[["center","Centre"],["left","Left"],["right","Right"]]},{name:"bg-y",type:"select",label:"Background vertical position",options:[["center","Centre"],["top","Top"],["bottom","Bottom"]]},{name:"bg",type:"colour",label:"Background colour"},{name:"color",type:"colour",label:"Background colour (alias)"},{name:"min-height",type:"text",label:"Min height"},{name:"twinkle",type:"checkbox",label:"Twinkle particles"},{name:"twinkle-count",type:"number",label:"Twinkle count"},{name:"twinkle-colour",type:"colour",label:"Twinkle colour"},{name:"blobs",type:"checkbox",label:"Ambient blobs"},{name:"blobs-type",type:"text",label:"Blobs type"},{name:"class",type:"text",label:"CSS class"},{name:"id",type:"text",label:"ID"}]},{name:"table",label:"Table",icon:"grid",category:"Content",selfClosing:!1,container:!1,wrappable:!1,template:`[table striped="true"]
|
|
41
41
|
| Product | Price |
|
|
42
42
|
| ------- | ----: |
|
|
43
43
|
| Widget | $9.99 |
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{api as g}from"../api.js";import{CardBuilder as
|
|
1
|
+
import{api as g}from"../api.js";import{CardBuilder as it}from"../lib/card-builder.js";import{TimelineBuilder as lt}from"../lib/timeline-builder.js";import{attachEditorKeybindings as ct,createToolbar as dt,insertAtCursor as pt}from"../lib/markdown-toolbar.js";import{EffectsBuilder as ut}from"../lib/effects-builder.js";import{attachContextMenu as vt}from"../lib/shortcode-context-menu.js";import{registerCustomInserters as ft}from"../lib/shortcode-insert.js";import{populateThemeSelect as mt}from"../lib/themes.js";import{createFoldingManager as bt}from"../lib/editor-folding.js";import{openScribeComposer as gt}from"../lib/scribe-composer.js";import{openCrudTutorial as ht}from"../lib/crud-tutorial.js";import{addBannerAction as B}from"../lib/plugin-chrome.js";import{helpPopovers as Be}from"../lib/help-popover.js";import{onceClosed as be,openMenuAt as $e}from"../lib/tool-kit.js";import{pickMedia as yt}from"../lib/media-picker.js";import{openEditorReference as je}from"../lib/page-editor-reference.js";import{cleanType as J,DEFAULT_TYPE as G,EDITOR_FONTS as wt,fontHref as kt,isDefaultType as Et,LINE_HEIGHTS as Mt,SIZES as St,typeVars as qe}from"../lib/editor-type.js";import{getProjectFromHash as Ct}from"../lib/project-context.js";import{SCREEN as Tt,bannerSection as xt,draftIsStale as Pt,draftKey as Lt,initialProject as At,makeDraft as Dt,problems as Ve,readDraft as Ot,snapshot as $}from"../lib/page-editor-arrange.js";import{fmtDateTime as Y}from"../lib/dates.js";function X(a){const r=document.createElement("template");return r.innerHTML=a.trim(),r.content.firstElementChild}const Rt=Y,He=a=>Y(a.createdAt)+(a.label?` - ${a.label}`:""),Ft=`
|
|
2
2
|
<div class="pe-share">
|
|
3
3
|
<p class="form-hint" style="margin-top:0">Anyone with the link can view this page even while it is unpublished, without
|
|
4
4
|
signing in. The link works for this page only, expires on its own, and can be revoked at any time.</p>
|
|
@@ -30,7 +30,7 @@ import{api as g}from"../api.js";import{CardBuilder as rt}from"../lib/card-builde
|
|
|
30
30
|
.pe-share [hidden] { display: none !important; }
|
|
31
31
|
.pe-share-row { display: flex; align-items: center; gap: .6rem; padding: .5rem 0; border-bottom: 1px solid var(--dm-border-light); }
|
|
32
32
|
.pe-share-text { flex: 1 1 auto; min-width: 0; font-size: .82rem; }
|
|
33
|
-
</style>`;function Ke(
|
|
33
|
+
</style>`;function Ke(a){const r=kt(a);if(!r||document.querySelector(`link[data-pe-font="${CSS.escape(a)}"]`))return;const l=Object.assign(document.createElement("link"),{rel:"stylesheet",href:r});l.dataset.peFont=a,document.head.appendChild(l)}const Nt=`
|
|
34
34
|
<div class="pe-settings">
|
|
35
35
|
<p class="pe-settings-note">How the editor looks to you - kept in this browser, for every page.</p>
|
|
36
36
|
<label class="form-label" for="pe-set-font">Font <span data-help="The lettering in the editor (not on the site). Monospace keeps every character the same width, so shortcodes and Markdown line up."></span></label>
|
|
@@ -61,20 +61,20 @@ The quick brown fox - 0O 1lI {} [] () => ==
|
|
|
61
61
|
.pe-settings-sample { white-space: pre-wrap; padding: .75rem 1rem; border-radius: var(--dm-radius-md); border: 1px solid var(--dm-border);
|
|
62
62
|
background: var(--dm-background-alt); font-family: var(--pe-font); font-size: var(--pe-size); line-height: var(--pe-line); }
|
|
63
63
|
.pe-settings-actions { display: flex; gap: .5rem; border-top: 1px solid var(--dm-border); padding-top: .75rem; }
|
|
64
|
-
</style>`;function
|
|
64
|
+
</style>`;function It(a){const r=E.slideover({title:"Editor settings",size:"sm",position:"right"}),l=X(`<div>${Nt}</div>`),s=J(a.peek()),i={font:M.observable(s.font),size:M.observable(String(s.size)),line:M.observable(String(s.line)),wrap:M.observable(s.wrap)},f=M.computed(()=>J({font:i.font.value,size:i.size.value,line:i.line.value,wrap:i.wrap.value}));i.isDefault=M.computed(()=>Et(f.value));const p=l.querySelector("#pe-set-font");for(const[v,k]of[["mono","Monospace"],["sans","Other"],["serif",null]]){const N=wt.filter(m=>m.kind===v),q=k?Object.assign(document.createElement("optgroup"),{label:k}):p.querySelector("optgroup:last-of-type");q.append(...N.map(m=>new Option(m.label,m.id))),k&&p.appendChild(q)}l.querySelector("#pe-set-size").append(...St.map(v=>new Option(`${v}px`,String(v)))),l.querySelector("#pe-set-line").append(...Mt.map(v=>new Option({1.3:"Tight",1.45:"Snug",1.6:"Normal",1.8:"Relaxed",2:"Double"}[v]||String(v),String(v))));const c=l.querySelector(".pe-settings-sample"),u=M.effect(()=>{const v=f.value;Ke(v.font);for(const[k,N]of Object.entries(qe(v)))c.style.setProperty(k,N);c.style.whiteSpace=v.wrap?"pre-wrap":"pre",c.style.overflowX=v.wrap?"":"auto",JSON.stringify(v)!==JSON.stringify(J(a.peek()))&&(a.value=v,Z("type",v))});i.reset=()=>{i.font.value=G.font,i.size.value=String(G.size),i.line.value=String(G.line),i.wrap.value=G.wrap},i.done=()=>r.close(),r.element.appendChild(l);const T=M.applyBindings(i,l),d=Be(l);return be(r,()=>{T.dispose(),d(),u?.()}),Domma.icons?.scan?.(l),r.open(),r}async function zt(a){const r=E.slideover({title:"Share preview link",size:"md",position:"right"}),l=X(`<div>${Ft}</div>`),s={expiry:M.observable("7d"),note:M.observable(""),creating:M.observable(!1),url:M.observable(""),links:M.observable([]),loaded:M.observable(!1),listError:M.observable("")},i=async()=>{try{const p=await g.pages.previewLinks.list(a);s.links.value=p.filter(c=>!c.revokedAt&&!c.expired).map(c=>({id:c.id,title:c.label||"Untitled link",meta:`Expires ${Rt(c.expiresAt)} - ${c.useCount===1?"1 view":`${c.useCount||0} views`}`})),s.listError.value=""}catch(p){s.listError.value="Could not load existing links: "+(p.message||"unknown error")}finally{s.loaded.value=!0}};s.create=async()=>{s.creating.value=!0;try{const p=await g.pages.previewLinks.create(a,s.expiry.peek(),s.note.peek().trim());s.url.value=p.url,s.note.value="",E.toast("Share link created.",{type:"success"}),await i(),l.querySelector(".pe-share-url")?.select()}catch(p){E.toast("Could not create link: "+(p.message||"unknown error"),{type:"error"})}finally{s.creating.value=!1}},s.copy=async()=>{try{await navigator.clipboard.writeText(s.url.peek()),E.toast("Link copied to clipboard.",{type:"success"})}catch{l.querySelector(".pe-share-url")?.select(),E.toast("Press Ctrl+C to copy the selected link.",{type:"info"})}},s.revoke=async p=>{if(await E.confirm("Revoke this link? Anyone holding it loses access immediately."))try{await g.pages.previewLinks.revoke(p),E.toast("Link revoked.",{type:"success"}),await i()}catch(c){E.toast("Could not revoke: "+(c.message||"unknown error"),{type:"error"})}};const f=M.applyBindings(s,l);be(r,()=>f.dispose()),r.element.appendChild(l),r.open(),await i()}function Bt(a){return new Promise(r=>{const l=E.slideover({title:"Save Named Version",size:"sm",position:"right"}),s=X(`
|
|
65
65
|
<div style="padding:1rem">
|
|
66
66
|
<label class="form-label" for="pe-version-label">Version Label</label>
|
|
67
67
|
<input id="pe-version-label" type="text" class="form-input" style="margin-bottom:.75rem"
|
|
68
68
|
placeholder="e.g. Initial design, Before restructure" data-model="label.value" data-on-keydown="key">
|
|
69
69
|
<button type="button" class="btn btn-primary" data-on-click="save" data-bind-disabled="saving.value">Save Version</button>
|
|
70
|
-
</div>`);let
|
|
71
|
-
`).map(
|
|
70
|
+
</div>`);let i=!1;const f={label:M.observable(""),saving:M.observable(!1)};f.save=async()=>{f.saving.value=!0;try{await g.versions.create(a,f.label.peek().trim()||null),E.toast("Named version saved.",{type:"success"}),i=!0,l.close()}catch(c){E.toast("Failed to save version: "+c.message,{type:"error"})}finally{f.saving.value=!1}},f.key=c=>{c.key==="Enter"&&(c.preventDefault(),f.save())};const p=M.applyBindings(f,s);be(l,()=>{p.dispose(),r(i)}),l.element.appendChild(s),l.open(),setTimeout(()=>s.querySelector("input")?.focus(),100)})}let C=null,Ue=!1;function $t(){Ue||!window.R?.use||(Ue=!0,R.use((a,r,l)=>{const s=r?.path||"",i=a?.path||"";return!(Tt.test(s)&&i!==s)||!C||C.path!==s||!C.dirty()?l():E.confirm("You have unsaved changes to this page. Leave anyway? They are kept as a draft for your next visit.").then(p=>{p?(C?.keepDraft(),l()):history.replaceState(null,"","#"+s)})}),M.subscribe("router:afterChange",({to:a}={})=>{if(C&&(a?.path||"")!==C.path){const r=C;C=null,r.dispose()}}))}function jt(a){return a.split(`
|
|
71
|
+
`).map(r=>r.trimEnd()).join(`
|
|
72
72
|
`).replace(/\n{3,}/g,`
|
|
73
73
|
|
|
74
|
-
`)}const
|
|
74
|
+
`)}const _e="editor_prefs";function j(){return S.get(_e)||{viewMode:"split",fullscreen:!1}}function Z(a,r){const l=j();l[a]=r,S.set(_e,l)}const qt=["edit","details","seo","dconfig","live","history"],We=["split","write","preview"],Vt=a=>a.replace(/<\/head>/i,"<style>body.dm-cloaked{opacity:1 !important;transition:none !important}</style></head>");function Je(a,r,l=()=>{}){let s=0;try{s=a.contentWindow.scrollY||0}catch{}a.addEventListener("load",()=>{try{a.contentWindow.scrollTo(0,s)}catch{}l()},{once:!0}),a.srcdoc=r}export const pageEditorView={templateUrl:"/admin/js/templates/page-editor.html",async onMount(a){if($t(),C){const e=C;C=null,e.dispose()}const r=window.location.hash.replace(/^#/,""),l=[],s=e=>(l.push(e),e);let i=()=>!1,f=()=>{};const p={path:r,dirty:()=>i(),keepDraft:()=>f(),dispose:()=>{l.splice(0).forEach(e=>{try{e()}catch{}})}};C=p;const c=a.get(0),u=()=>C===p&&c.isConnected,T=window.location.hash.match(/#\/pages\/edit(\/[^?]*)/),d=T?T[1]:null,v=!!d,k=E.loader(c,{type:"dots"}),[N,q,m,ge,he,Ge]=await Promise.all([g.layouts.get().catch(()=>({})),g.settings.get().catch(()=>({})),v?g.pages.get(d).catch(()=>null):null,v?g.pages.list().catch(()=>[]):[],g.projects.list().catch(()=>[]),g.pages.tags().catch(()=>[])]);if(!u()){k.destroy();return}if(k.destroy(),v&&!m){E.toast("Page not found.",{type:"error"}),R.navigate("/pages");return}const y=e=>c.querySelector(e);if(mt(y("#field-theme"),{includeDefault:!0}),await Wt(y("#field-visibility"),m?.visibility),!u())return;const Ye=_t(y("#field-layout"),N,m?.layout||"default");for(const e of he)y("#field-project").append(new Option(e.name||e.slug,e.slug));const ye=[...Array.isArray(ge)?ge:[]].sort((e,t)=>(e.title||e.urlPath).localeCompare(t.title||t.urlPath));for(const e of ye)y("#quick-switch").append(new Option(`${e.title||"Untitled"} (${e.urlPath})`,e.urlPath,!1,e.urlPath===d));const V=j(),o={urlPath:M.observable(d||""),title:M.observable(m?.title||""),description:M.observable(m?.description||""),layout:M.observable(Ye),status:M.observable(m?.status||"draft"),sortOrder:M.observable(String(m?.sortOrder??99)),showInNav:M.observable(!!m?.showInNav),sidebar:M.observable(!!m?.sidebar),breadcrumbs:M.observable(m?m.breadcrumbs!==!1:!0),bundled:M.observable(!!m?.bundled),tags:M.observable(Array.isArray(m?.tags)?m.tags:[]),category:M.observable(m?.category||""),visibility:M.observable(typeof m?.visibility=="string"&&m.visibility?m.visibility:"public"),project:M.observable(At({isEdit:v,page:m,projects:he,fromHash:Ct()||"",urlPath:d||""})),theme:M.observable(m?.theme||""),seoTitle:M.observable(m?.seo?.title||""),seoDesc:M.observable(m?.seo?.description||""),dconfig:M.observable(m?.dconfig?JSON.stringify(m.dconfig,null,2):""),css:M.observable(""),cssOpened:M.observable(!1)},n={bodyRev:M.observable(0),base:M.observable(""),saving:M.observable(!1),tab:M.observable("edit"),viewMode:M.observable(We.includes(V.viewMode)?V.viewMode:"split"),fullscreen:M.observable(!!V.fullscreen),cssMode:M.observable(!1),folded:M.observable(!1),liveStatus:M.observable("Showing unsaved changes"),liveWidth:M.observable("full"),versions:M.observable([]),histLoading:M.observable(!1),histError:M.observable(""),compare:M.observable(null)},w=y("#markdown-editor"),I=y("#css-editor");w.value=m?.content||"";const L=document.createElement("div");L.className="editor-line-numbers editor-line-numbers--foldable",w.parentElement.insertBefore(L,w);const x=bt(w,L,{onFoldChange:()=>{}});let D=!1;x.setGuard(e=>{D=e});const z=()=>x.getUnfoldedContent(),we=M.observable(J(V.type));s(M.effect(()=>{const e=we.value,t=y("#editor-body");if(t){Ke(e.font);for(const[b,h]of Object.entries(qe(e)))t.style.setProperty(b,h);t.classList.toggle("pe-nowrap",!e.wrap),w.wrap=e.wrap?"soft":"off",I.wrap=e.wrap?"soft":"off"}}));let ke=null;s(()=>{try{ke?.close()}catch{}});const O=()=>(n.bodyRev.value,{urlPath:o.urlPath.value.trim(),title:o.title.value,description:o.description.value,layout:o.layout.value,status:o.status.value,sortOrder:o.sortOrder.value,showInNav:o.showInNav.value,sidebar:o.sidebar.value,breadcrumbs:o.breadcrumbs.value,bundled:o.bundled.value,tags:o.tags.value,category:o.category.value,visibility:o.visibility.value,project:o.project.value,theme:o.theme.value,seoTitle:o.seoTitle.value,seoDesc:o.seoDesc.value,dconfig:o.dconfig.value,body:z(),css:o.cssOpened.value?o.css.value:null}),Xe=M.computed(()=>$(O())!==n.base.value),Ze=M.computed(()=>Ve({urlPath:o.urlPath.value,dconfig:o.dconfig.value})[0]?.text||""),Qe=M.computed(()=>n.versions.value.some(e=>e.checked.value)),et=M.computed(()=>n.versions.value.length>0&&n.versions.value.every(e=>e.checked.value)),tt=M.computed(()=>{const e=n.versions.value.filter(t=>t.checked.value).length;return e>0&&e<n.versions.value.length});i=()=>$(O())!==n.base.peek();const Q=e=>({title:o.title.peek().trim()||"Untitled",description:o.description.peek().trim(),layout:o.layout.peek(),status:o.status.peek(),sortOrder:parseInt(String(o.sortOrder.peek()),10)||99,showInNav:o.showInNav.peek(),sidebar:o.sidebar.peek(),...o.breadcrumbs.peek()?{}:{breadcrumbs:!1},...o.bundled.peek()?{bundled:!0}:{},tags:o.tags.peek(),category:o.category.peek().trim()||null,visibility:o.visibility.peek()||"public",project:o.project.peek()||"",seo:{title:o.seoTitle.peek().trim(),description:o.seoDesc.peek().trim()},dconfig:e,...o.theme.peek()?{theme:o.theme.peek()}:{}}),Ee=()=>{const e=o.dconfig.peek().trim();if(!e)return null;try{return JSON.parse(e)}catch{return null}},Me=()=>o.urlPath.peek().trim()||d||"/",H=y("#markdown-preview");let Se="";g.settings.getCustomCss().then(({css:e})=>{Se=e||""}).catch(()=>{});const Ce=()=>{const e=H?.contentDocument;if(!e?.head)return;const t=o.cssOpened.peek()?o.css.peek():"";if(!t)return;let b=e.getElementById("preview-custom-css");b||(b=e.createElement("style"),b.id="preview-custom-css",e.head.appendChild(b)),b.textContent=t};let ee=null;const K=()=>{clearTimeout(ee),ee=setTimeout(async()=>{if(!(!H||n.viewMode.peek()==="write"))try{const{html:e}=await g.pages.previewFull(Me(),Q(Ee()),z());u()&&Je(H,Vt(e),Ce)}catch(e){H.srcdoc='<!doctype html><meta charset="utf-8"><body style="font:14px system-ui;padding:1rem;color:#b91c1c;">Preview failed: '+String(e?.message||"unknown error").replace(/[<&]/g,t=>t==="<"?"<":"&")+"</body>"}},500)},Te=y("#live-preview-frame");let te=!0,ae=null,se=!1;const oe=async()=>{if(!(se||!Te)){se=!0,n.liveStatus.value="Rendering\u2026";try{const{html:e}=await g.pages.previewFull(Me(),Q(Ee()),z());if(!u())return;Je(Te,e),te=!1,n.liveStatus.value="Showing unsaved changes"}catch(e){n.liveStatus.value="Preview failed - "+(e?.message||"unknown error")}finally{se=!1}}},xe=()=>{te=!0,n.tab.peek()==="live"&&(clearTimeout(ae),ae=setTimeout(oe,600))};s(()=>{clearTimeout(ee),clearTimeout(ae)});const ne=dt(a.find("#markdown-editor"),a.find("#editor-toolbar"),{spacerDefault:q?.layoutOptions?.spacerSize??40});vt(w);const re=c.querySelector(".editor-toolbar-right");re.querySelectorAll(".editor-view-btn[data-mode]").forEach(e=>{const t=e.getAttribute("data-mode");e.classList.remove("active"),e.setAttribute("data-bind-class",`viewMode.value === '${t}' && 'active'`),e.setAttribute("data-on-click",`setMode('${t}')`)}),y("#fullscreen-btn")?.setAttribute("data-on-click","toggleFullscreen");const at=X(`
|
|
75
75
|
<span class="pe-toolbar-extras" style="display:contents">
|
|
76
76
|
<button type="button" class="editor-view-btn" data-tip="Edit Custom CSS" data-on-click="toggleCss"
|
|
77
|
-
data-bind-class="cssMode.value && 'active'"><span
|
|
77
|
+
data-bind-class="cssMode.value && 'active'"><span>CSS</span></button>
|
|
78
78
|
<button type="button" class="editor-view-btn" data-tip="Format Markdown" data-on-click="formatMarkdown"><span data-icon="code"></span></button>
|
|
79
79
|
<button type="button" class="editor-view-btn" data-tip="Fold / unfold all shortcodes" data-on-click="toggleFold"
|
|
80
80
|
style="font-size:9px;letter-spacing:-1px;" data-bind-class="folded.value && 'active'">
|
|
@@ -83,13 +83,5 @@ The quick brown fox - 0O 1lI {} [] () => ==
|
|
|
83
83
|
<span class="pe-fold-icon" hidden data-bind-hidden="!folded.value"><span data-icon="chevrons-right" data-icon-size="10"></span></span>
|
|
84
84
|
</button>
|
|
85
85
|
<span class="editor-toolbar-sep"></span>
|
|
86
|
-
</span>`);re.prepend(at);const Pe=y("#field-tags"),
|
|
87
|
-
`).map((
|
|
88
|
-
<div>
|
|
89
|
-
<p class="text-muted p-3" hidden data-bind-hidden="images.length">No images uploaded yet.</p>
|
|
90
|
-
<div class="media-picker-grid" data-each="images key=url">
|
|
91
|
-
<div class="media-picker-item" data-on-click="$root.pick($data)">
|
|
92
|
-
<img data-bind-src="url" data-bind-alt="name"><span data-bind-text="name"></span>
|
|
93
|
-
</div>
|
|
94
|
-
</div>
|
|
95
|
-
</div>`),a=E.slideover({title:"Insert Image",size:"lg",position:"right"}),l=M.applyBindings({images:i,pick:p=>{pt(s,``),a.close(),s.dispatchEvent(new Event("input",{bubbles:!0}))}},r);G(a,()=>l.dispose()),a.element.appendChild(r),a.open()}function _t(s,i,r){const a=Object.entries(i||{});return s?(s.replaceChildren(...a.map(([l,p])=>new Option(p?.label||l,l))),a.some(([l])=>l===r)?r:a[0]?.[0]||r):r}async function Ut(s,i){if(!s)return;let r=[];try{const u=await g.get("/collections/roles/entries?limit=100");r=Array.isArray(u)?u:u?.entries||[]}catch{}const a=r.map(u=>({name:u.data?.name,label:u.data?.label||u.data?.name,level:u.data?.level??99})).filter(u=>u.name&&u.level!==0).sort((u,T)=>T.level-u.level),l=(u,T)=>Object.assign(document.createElement("option"),{value:u,textContent:T}),p=()=>{typeof i=="string"&&i&&![...s.options].some(u=>u.value===i)&&s.append(l(i,`${i} (custom)`))};if(!a.length)return p();const v=document.createElement("optgroup");v.label="Role and above",a.forEach(u=>v.append(l(u.name,`${u.label} and above`)));const c=document.createElement("optgroup");c.label="Role only",a.forEach(u=>c.append(l(`=${u.name}`,`${u.label} only`))),s.replaceChildren(l("public","Public - everyone"),v,c,l("private","Private - super-admin only")),p()}
|
|
86
|
+
</span>`);re.prepend(at);const Pe=y("#field-tags"),ie=Pe?E.pillbox(Pe,{data:Ge,value:o.tags.peek(),creatable:!0,searchable:!0,placeholder:"Add tag\u2026",onChange:()=>{o.tags.value=ie?[...ie.getValue()]:[]}}):null;let le=!1,ce=null;const U=async()=>{le=!0,n.histLoading.value=!0,n.histError.value="";try{const e=(await g.versions.list(d)).versions||[];if(!u())return;n.versions.value=e.map(t=>({...t,when:Y(t.createdAt),author:t.author||"",label:t.label||"",checked:M.observable(!1)}))}catch(e){n.histError.value="Failed to load versions: "+e.message}finally{n.histLoading.value=!1}},de=e=>n.versions.peek().find(t=>t.filename===e),pe=async e=>{try{const t=await g.versions.get(d,e.filename);ce=e.filename,n.compare.value={label:He(e),old:t.content,current:z()}}catch(t){E.toast("Failed to load version: "+t.message,{type:"error"})}},Le=async e=>{if(!(!e||!await E.confirm("Restore this version? The current page content will be overwritten (a pre-restore snapshot will be saved automatically).")))try{await g.versions.restore(d,e),E.toast("Page restored. Reloading editor\u2026",{type:"success"}),R.navigate("/pages"),setTimeout(()=>R.navigate(`/pages/edit${d}`),300)}catch(t){E.toast("Restore failed: "+t.message,{type:"error"})}},st=async e=>{if(await E.confirm("Delete this version? This cannot be undone."))try{await g.versions.delete(d,e.filename),E.toast("Version deleted.",{type:"success"}),await U()}catch(t){E.toast("Failed to delete: "+t.message,{type:"error"})}},Ae=()=>{n.bodyRev.value=n.bodyRev.peek()+1},De=()=>{o.cssOpened.peek()||(o.css.value=Se,o.cssOpened.value=!0,ct(I))},Oe=e=>{for(const t of["urlPath","title","description","layout","status","sortOrder","category","visibility","project","theme","seoTitle","seoDesc","dconfig"])o[t].value=e[t]==null?"":String(e[t]);for(const t of["showInNav","sidebar","breadcrumbs","bundled"])o[t].value=!!e[t];o.tags.value=Array.isArray(e.tags)?e.tags:[],ie?.setValue(o.tags.peek()),x.unfoldAll(),D=!0,w.value=e.body==null?"":String(e.body),D=!1,x.refresh(),e.css!=null&&(De(),o.css.value=String(e.css)),Ae()};n.base.value=$(O());const _=Lt(d||"");f=()=>{if(i())try{S.set(_,Dt(O(),n.base.peek()))}catch{}};const ue=()=>{try{S.remove?S.remove(_):S.set(_,null)}catch{}},Re=e=>{i()&&(f(),e.preventDefault(),e.returnValue="")};window.addEventListener("beforeunload",Re),s(()=>window.removeEventListener("beforeunload",Re));const ve=async()=>{if(n.saving.peek())return;const e=O(),t=Ve(e);if(t.length){E.toast(t[0].text,{type:"warning"}),c.querySelectorAll("#editor-meta-tabs .tab-item")[qt.indexOf(t[0].field==="dconfig"?"dconfig":"details")]?.click();return}const b=(e.dconfig||"").trim(),h=Q(b?JSON.parse(b):null),P=o.cssOpened.peek();n.saving.value=!0;try{if(v){const A={frontmatter:h,body:e.body};e.urlPath!==d&&(A.newUrlPath=e.urlPath),await g.pages.update(d,A)}else await g.pages.create({urlPath:e.urlPath,frontmatter:h,body:e.body});P&&await g.settings.saveCustomCss(o.css.peek()),E.toast(P?"Page and CSS saved.":"Page saved.",{type:"success"}),ue(),n.base.value=$(O()),v?e.urlPath!==d&&R.navigate(`/pages/edit${e.urlPath}`):R.navigate("/pages")}catch(A){E.toast(`Save failed: ${A.message||"Unknown error"}`,{type:"error"})}finally{n.saving.value=!1}},Fe=c.querySelector(".dm-plugin-body")||c,ot={...o,...n,dirty:Xe,problem:Ze,anySelected:Qe,allSelected:et,someSelected:tt,isEdit:v,savedPath:d||"",hasPages:ye.length>0},nt={save:()=>ve(),discard:async()=>{!i()||!await E.confirm("Discard the changes you have not saved?")||(Oe(JSON.parse(n.base.peek())),ue())},switchPage:e=>{const t=e?.target?.value;t&&R.navigate("/pages/edit"+t)},showTab:e=>{n.tab.value=e,e==="live"&&te&&oe(),e==="history"&&v&&!le&&U()},setMode:e=>{n.cssMode.peek()&&(n.cssMode.value=!1),n.viewMode.value=e,Z("viewMode",e),e!=="write"&&K()},toggleFullscreen:()=>{n.fullscreen.value=!n.fullscreen.peek(),Z("fullscreen",n.fullscreen.peek())},toggleCss:()=>{n.cssMode.peek()?(n.cssMode.value=!1,n.viewMode.value=We.includes(j().viewMode)?j().viewMode:"split",x.refresh()):(De(),n.cssMode.value=!0,n.viewMode.value="split")},formatMarkdown:()=>{const e=w.selectionStart,t=jt(z());x.unfoldAll(),D=!0,w.value=t,D=!1,w.selectionStart=w.selectionEnd=Math.min(e,t.length),w.dispatchEvent(new Event("input")),x.refresh(),E.toast("Markdown formatted.",{type:"success"})},toggleFold:()=>{n.folded.peek()?x.unfoldAll():x.foldAll(),n.folded.value=!n.folded.peek()},setWidth:e=>{n.liveWidth.value=e;const t=y("#live-preview-stage");t&&(t.scrollTop=0)},refreshLive:()=>oe(),share:async()=>{if(!v){E.toast("Save the page first - a share link needs a page to point at.",{type:"warning"});return}await zt(d)},toggleAll:e=>{const t=!!e?.target?.checked;n.versions.peek().forEach(b=>{b.checked.value=t})},deleteSelected:async()=>{const e=n.versions.peek().filter(b=>b.checked.peek()).map(b=>b.filename),t=e.length;if(!(!t||!await E.confirm(`Delete ${t} version${t>1?"s":""}? This cannot be undone.`)))try{await g.versions.bulkDelete(d,e),E.toast(`${t} version${t>1?"s":""} deleted.`,{type:"success"}),await U()}catch(b){E.toast("Delete failed: "+b.message,{type:"error"})}},saveNamed:async()=>{await Bt(d)&&u()&&(n.tab.peek()==="history"?await U():le=!1)},closeCompare:()=>{n.compare.value=null,ce=null},restoreCompared:()=>Le(ce)};re.querySelectorAll("[data-tip]").forEach(e=>E.tooltip(e,{content:e.getAttribute("data-tip"),position:"top"}));const rt=M.applyBindings(ot,Fe,{methods:nt});s(()=>rt.dispose()),E.tabs(y("#editor-meta-tabs"));let fe=null;s(()=>clearTimeout(fe)),w.addEventListener("input",()=>{x.refresh(),L.scrollTop=w.scrollTop,!D&&(clearTimeout(fe),fe=setTimeout(Ae,120),K(),xe())}),w.addEventListener("scroll",()=>{L.scrollTop=w.scrollTop}),I.addEventListener("scroll",()=>{L.scrollTop=I.scrollTop});let Ne=!0;s(M.effect(()=>{for(const e of Object.keys(o))e!=="css"&&e!=="cssOpened"&&o[e].value;if(n.bodyRev.value,Ne){Ne=!1,K();return}K(),xe()}));let me=null;if(s(()=>clearTimeout(me)),s(M.effect(()=>{const e=o.css.value;n.cssMode.value&&(Ht(L,e,I),clearTimeout(me),me=setTimeout(Ce,400))})),v){const e=y(".pe-version-list"),t=E.contextMenu(e,{cursor:"glyph",match:"tr[data-file]",inherit:!1,density:"compact",items:b=>{const h=de(b.dataset.file);return h?[{header:He(h)},{label:"Compare with the editor",icon:"columns",action:()=>pe(h)},{label:"Restore this version\u2026",icon:"rotate-ccw",action:()=>Le(h.filename)},{type:"divider"},{label:"Delete\u2026",icon:"trash",danger:!0,action:()=>st(h)}]:[]}});s(()=>t?.destroy?.()),e.addEventListener("click",b=>{const h=b.target.closest("tr[data-file]");if(!h||b.target.matches("input"))return;const P=b.target.closest(".pe-kebab");if(P){$e(P);return}const A=de(h.dataset.file);A&&pe(A)}),e.addEventListener("keydown",b=>{const h=b.target.closest("tr[data-file]");if(h){if(b.key==="F10"&&b.shiftKey)b.preventDefault(),$e(h);else if(b.key==="Enter"&&b.target===h){const P=de(h.dataset.file);P&&pe(P)}}})}Kt(y("#editor-body"),y("#editor-divider"),s),ft({image:e=>(n.cssMode.value=!1,Ut(e)),scribe:e=>gt(e),card:e=>it.open(e,{onMediaBrowse:()=>g.media.list().catch(()=>[])}),timeline:e=>lt.open(e,{onPreview:async t=>{try{return await g.pages.preview(t)}catch{return null}},onListCollections:()=>g.collections.list().catch(()=>[]),onGetCollection:t=>g.collections.get(t).catch(()=>null)})}),ne.onEffects(e=>ut.open(e)),ne.onHelp(()=>je()),ne.onTutorial(e=>ht(e));const Ie=e=>{(e.ctrlKey||e.metaKey)&&!e.shiftKey&&!e.altKey&&e.key.toLowerCase()==="s"&&u()&&(e.preventDefault(),ve())};document.addEventListener("keydown",Ie),s(()=>document.removeEventListener("keydown",Ie));const W=c.querySelector(".dm-plugin-banner-name");if(W){const e=W.lastChild,t=xt(v,m?.title,d);e&&e.nodeType===3&&W.querySelector(".dm-plugin-banner-sep")?e.textContent=t:W.textContent=`Pages \u203A ${t}`}B(a,{id:"page-editor-back",icon:"arrow-left",title:"Back to Pages",onClick:()=>R.navigate("/pages")}),B(a,{id:"page-editor-help",icon:"help-circle",title:"Editor reference",onClick:()=>je()}),v&&B(a,{id:"page-editor-view",icon:"external-link",title:"View on the site",onClick:()=>window.open(o.urlPath.peek()||d,"_blank","noopener")}),B(a,{id:"page-editor-save",icon:"save",title:"Save (Ctrl+S)",onClick:()=>ve()}),B(a,{id:"page-editor-settings",icon:"settings",title:"Editor settings - font, size, spacing",onClick:()=>{ke=It(we)}}),s(Be(Fe,{position:"bottom"})),Domma.icons.scan();let ze=null;try{ze=S.get(_)}catch{}const F=Ot(ze);if(F&&(ue(),$(F.state)!==n.base.peek())){const e=F.at?` (${Y(F.at)})`:"",t=Pt(F,n.base.peek())?" The saved page has changed since - restoring puts your version back over it (the saved one stays in History).":"";await E.confirm(`You left unsaved changes to this page${e}. Restore them?${t}`)&&u()&&Oe(F.state)}}};function Ht(a,r,l){a.replaceChildren(...String(r).split(`
|
|
87
|
+
`).map((s,i)=>{const f=document.createElement("span");f.className="editor-line-number-row";const p=document.createElement("span");p.className="fold-toggle fold-toggle--empty";const c=document.createElement("span");return c.className="editor-line-num",c.textContent=String(i+1),f.append(p,c),f})),a.scrollTop=l.scrollTop}function Kt(a,r,l){if(!a||!r)return;const s=15,i=85,f=d=>Math.min(i,Math.max(s,d));let p=f(parseFloat(j().splitRatio)||50);const c=d=>{a.style.setProperty("--dm-editor-split",p+"%"),r.setAttribute("aria-valuenow",String(Math.round(p))),d&&Z("splitRatio",p)};c(!1);const u=d=>{const v=a.getBoundingClientRect();v.width&&(p=f((d.clientX-v.left)/v.width*100)),c(!1)},T=()=>{document.removeEventListener("pointermove",u),document.removeEventListener("pointerup",T),a.classList.remove("is-resizing"),r.classList.remove("is-dragging"),c(!0)};l(T),r.addEventListener("pointerdown",d=>{window.matchMedia("(max-width: 768px)").matches||(d.preventDefault(),a.classList.add("is-resizing"),r.classList.add("is-dragging"),document.addEventListener("pointermove",u),document.addEventListener("pointerup",T))}),r.addEventListener("dblclick",()=>{p=50,c(!0)}),r.addEventListener("keydown",d=>{const v=d.shiftKey?10:2;let k=p;if(d.key==="ArrowLeft")k=p-v;else if(d.key==="ArrowRight")k=p+v;else if(d.key==="Home")k=s;else if(d.key==="End")k=i;else if(d.key==="Enter"||d.key===" ")k=50;else return;d.preventDefault(),p=f(k),c(!0)})}async function Ut(a){const r=a.selectionStart,l=a.selectionEnd,s=await yt({title:"Upload or insert an image"});if(!s||!a.isConnected)return;let i=s.split("/").pop().split("?")[0];try{i=decodeURIComponent(i)}catch{}const f=i.replace(/[\\[\]]/g,"\\$&"),p=s.replace(/\(/g,"%28").replace(/\)/g,"%29").replace(/ /g,"%20");a.setSelectionRange(r,l),pt(a,``),a.dispatchEvent(new Event("input",{bubbles:!0}))}function _t(a,r,l){const s=Object.entries(r||{});return a?(a.replaceChildren(...s.map(([i,f])=>new Option(f?.label||i,i))),s.some(([i])=>i===l)?l:s[0]?.[0]||l):l}async function Wt(a,r){if(!a)return;let l=[];try{const u=await g.get("/collections/roles/entries?limit=100");l=Array.isArray(u)?u:u?.entries||[]}catch{}const s=l.map(u=>({name:u.data?.name,label:u.data?.label||u.data?.name,level:u.data?.level??99})).filter(u=>u.name&&u.level!==0).sort((u,T)=>T.level-u.level),i=(u,T)=>Object.assign(document.createElement("option"),{value:u,textContent:T}),f=()=>{typeof r=="string"&&r&&![...a.options].some(u=>u.value===r)&&a.append(i(r,`${r} (custom)`))};if(!s.length)return f();const p=document.createElement("optgroup");p.label="Role and above",s.forEach(u=>p.append(i(u.name,`${u.label} and above`)));const c=document.createElement("optgroup");c.label="Role only",s.forEach(u=>c.append(i(`=${u.name}`,`${u.label} only`))),a.replaceChildren(i("public","Public - everyone"),p,c,i("private","Private - super-admin only")),f()}
|