domma-cms 1.10.23 → 1.10.25

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.
@@ -1,4 +1,4 @@
1
- import{api as h}from"../api.js";import{CardBuilder as en}from"../lib/card-builder.js";import{TimelineBuilder as tn}from"../lib/timeline-builder.js";import{attachEditorKeybindings as on,createToolbar as an,insertAtCursor as sn}from"../lib/markdown-toolbar.js";import{EffectsBuilder as nn}from"../lib/effects-builder.js";import{attachContextMenu as rn}from"../lib/shortcode-context-menu.js";import{registerCustomInserters as ln}from"../lib/shortcode-insert.js";import{populateThemeSelect as cn}from"../lib/themes.js";import{createFoldingManager as dn}from"../lib/editor-folding.js";import{openScribeComposer as pn}from"../lib/scribe-composer.js";import{openCrudTutorial as un}from"../lib/crud-tutorial.js";import{addBannerAction as dt}from"../lib/plugin-chrome.js";import{exampleJson as mn,parseSchema as Po,schemaText as fn}from"../lib/seo-structured-data.js";import{helpPopovers as qa}from"../lib/help-popover.js";import{onceClosed as jt,openMenuAt as Ce,sidebarCount as pt}from"../lib/tool-kit.js";import{pickMedia as bn}from"../lib/media-picker.js";import{openPageClone as vn}from"../lib/page-clone.js";import{openEditorReference as Ha}from"../lib/page-editor-reference.js";import{cleanType as Bt,DEFAULT_TYPE as It,EDITOR_FONTS as gn,fontHref as hn,isDefaultType as kn,LINE_HEIGHTS as yn,SIZES as wn,typeVars as Va}from"../lib/editor-type.js";import{getProjectFromHash as Ft}from"../lib/project-context.js";import{attachSmoothCaret as _a,getCaretPreference as Sn,setCaretPreference as En}from"../lib/smooth-caret.js";import{SCREEN as Oo,bannerSection as Tn,draftIsStale as Mn,draftKey as ze,initialProject as Cn,makeDraft as Ka,problems as Ao,readDraft as xn,snapshot as W}from"../lib/page-editor-arrange.js";import{fmtDateTime as qe}from"../lib/dates.js";import{hasDraft as xe,heldBlockEdits as Pn,hold as Ro,takeHeld as $o,wireHeldRouter as On}from"../lib/editor-hop.js";import{hopTarget as Ua}from"../lib/editor-hop-arrange.js";import{checkNewName as An,copyName as Lo,usageText as Rn}from"../lib/blocks-arrange.js";import{isCollapsed as Ja,setCollapsed as Wa}from"../lib/sidebar-size.js";import{blockTagDefs as Ya,blocksInBody as $n}from"../lib/block-tags.js";import{draftKey as He,draftOffer as Ln,extractPlaceholders as Ga,formFromBlock as Xa,payloadFromForm as Za,rawPlaceholders as No,shortcodeFor as Nn,snapshot as Do}from"../lib/block-editor-arrange.js";import{blockTabs as Dn,notHereLine as jn,otherUses as Qa,outlineBlock as Bn,previewBlocks as In,saveQuestion as Fn,savedMessage as zn,usesLine as qn}from"../lib/page-blocks-arrange.js";import{addressFor as es,blockAloneBody as Hn,blockRows as Vn,cleanLayout as jo,closeTab as _n,componentRows as Kn,componentStatusText as Un,componentsInBody as Jn,moveTab as Wn,nextLayout as Yn,openTab as Bo,pageRows as Gn,pageStatusText as Xn,rememberedTabs as Zn,renameTab as Qn,sampleRows as ts,saveAllLabel as er,startingTabs as tr,tabId as X,tabItem as I,tabsToClose as Io,workspaceKey as or}from"../lib/editor-workspace-arrange.js";import{PANES as zt,STARTER_SOURCE as ar,assembleSource as os,attributeFor as sr,draftKey as Ve,draftStatus as nr,nameProblem as rr,previewRows as as,readValue as ir,snapshot as Fo,splitSource as ut,writeValue as ss}from"../lib/component-editor-arrange.js";import{attachColourLayer as ns,createPlainEditor as zo}from"../lib/plain-editor.js";import{cleanCodePrefs as qt,codePrefs as lr,DEFAULT_CODE_PREFS as Ht,formatTextarea as _e,INDENT_SIZES as cr,setCodePrefs as dr}from"../lib/code-format.js";function mt(d){const b=document.createElement("template");return b.innerHTML=d.trim(),b.content.firstElementChild}const pr=qe,rs=d=>qe(d.createdAt)+(d.label?` - ${d.label}`:""),ur=`
1
+ import{api as h}from"../api.js";import{CardBuilder as tn}from"../lib/card-builder.js";import{TimelineBuilder as on}from"../lib/timeline-builder.js";import{attachEditorKeybindings as an,createToolbar as sn,insertAtCursor as nn}from"../lib/markdown-toolbar.js";import{EffectsBuilder as rn}from"../lib/effects-builder.js";import{attachContextMenu as ln}from"../lib/shortcode-context-menu.js";import{registerCustomInserters as cn}from"../lib/shortcode-insert.js";import{populateThemeSelect as dn}from"../lib/themes.js";import{createFoldingManager as pn}from"../lib/editor-folding.js";import{openScribeComposer as un}from"../lib/scribe-composer.js";import{openCrudTutorial as mn}from"../lib/crud-tutorial.js";import{addBannerAction as dt}from"../lib/plugin-chrome.js";import{exampleJson as fn,parseSchema as Po,schemaText as bn}from"../lib/seo-structured-data.js";import{helpPopovers as qa}from"../lib/help-popover.js";import{onceClosed as Bt,openMenuAt as Ce,sidebarCount as pt}from"../lib/tool-kit.js";import{pickMedia as vn}from"../lib/media-picker.js";import{openPageClone as gn}from"../lib/page-clone.js";import{openEditorReference as Ha}from"../lib/page-editor-reference.js";import{dconfigNotes as hn}from"../lib/dconfig-check.js";import{catalogueNow as yn,setCatalogue as kn}from"../lib/domma-catalogue.js";import{cleanType as It,DEFAULT_TYPE as Ft,EDITOR_FONTS as wn,fontHref as Sn,isDefaultType as En,LINE_HEIGHTS as Mn,SIZES as Tn,typeVars as Va}from"../lib/editor-type.js";import{getProjectFromHash as zt}from"../lib/project-context.js";import{attachSmoothCaret as _a,getCaretPreference as Cn,setCaretPreference as xn}from"../lib/smooth-caret.js";import{SCREEN as Oo,bannerSection as Pn,draftIsStale as On,draftKey as ze,initialProject as Rn,makeDraft as Ka,problems as Ro,readDraft as An,snapshot as W}from"../lib/page-editor-arrange.js";import{fmtDateTime as qe}from"../lib/dates.js";import{hasDraft as xe,heldBlockEdits as $n,hold as Ao,takeHeld as $o,wireHeldRouter as Ln}from"../lib/editor-hop.js";import{hopTarget as Ua}from"../lib/editor-hop-arrange.js";import{checkNewName as Nn,copyName as Lo,usageText as Dn}from"../lib/blocks-arrange.js";import{isCollapsed as Ja,setCollapsed as Wa}from"../lib/sidebar-size.js";import{blockTagDefs as Ya,blocksInBody as jn}from"../lib/block-tags.js";import{draftKey as He,draftOffer as Bn,extractPlaceholders as Ga,formFromBlock as Xa,payloadFromForm as Za,rawPlaceholders as No,shortcodeFor as In,snapshot as Do}from"../lib/block-editor-arrange.js";import{blockTabs as Fn,notHereLine as zn,otherUses as Qa,outlineBlock as qn,previewBlocks as Hn,saveQuestion as Vn,savedMessage as _n,usesLine as Kn}from"../lib/page-blocks-arrange.js";import{addressFor as es,blockAloneBody as Un,blockRows as Jn,cleanLayout as jo,closeTab as Wn,componentRows as Yn,componentStatusText as Gn,componentsInBody as Xn,moveTab as Zn,nextLayout as Qn,openTab as Bo,pageRows as er,pageStatusText as tr,rememberedTabs as or,renameTab as ar,sampleRows as ts,saveAllLabel as sr,startingTabs as nr,tabId as X,tabItem as I,tabsToClose as Io,workspaceKey as rr}from"../lib/editor-workspace-arrange.js";import{PANES as qt,STARTER_SOURCE as ir,assembleSource as os,attributeFor as lr,draftKey as Ve,draftStatus as cr,nameProblem as dr,previewRows as as,readValue as pr,snapshot as Fo,splitSource as ut,writeValue as ss}from"../lib/component-editor-arrange.js";import{attachColourLayer as ns,createPlainEditor as zo}from"../lib/plain-editor.js";import{cleanCodePrefs as Ht,codePrefs as ur,DEFAULT_CODE_PREFS as Vt,formatTextarea as _e,INDENT_SIZES as mr,setCodePrefs as fr}from"../lib/code-format.js";function mt(d){const b=document.createElement("template");return b.innerHTML=d.trim(),b.content.firstElementChild}const br=qe,rs=d=>qe(d.createdAt)+(d.label?` - ${d.label}`:""),vr=`
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 h}from"../api.js";import{CardBuilder as en}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 is(d){const b=hn(d);if(!b||document.querySelector(`link[data-pe-font="${CSS.escape(d)}"]`))return;const v=Object.assign(document.createElement("link"),{rel:"stylesheet",href:b});v.dataset.peFont=d,document.head.appendChild(v)}const mr=`
33
+ </style>`;function is(d){const b=Sn(d);if(!b||document.querySelector(`link[data-pe-font="${CSS.escape(d)}"]`))return;const v=Object.assign(document.createElement("link"),{rel:"stylesheet",href:b});v.dataset.peFont=d,document.head.appendChild(v)}const gr=`
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>
@@ -94,17 +94,17 @@ The quick brown fox - 0O 1lI {} [] () =&gt; ==
94
94
  .pe-settings-sample { white-space: pre-wrap; padding: .75rem 1rem; border-radius: var(--dm-radius-md); border: 1px solid var(--dm-border);
95
95
  background: var(--dm-background-alt); font-family: var(--pe-font); font-size: var(--pe-size); line-height: var(--pe-line); }
96
96
  .pe-settings-actions { display: flex; gap: .5rem; border-top: 1px solid var(--dm-border); padding-top: .75rem; }
97
- </style>`;function fr(d,b){const v=E.slideover({title:"Editor settings",size:"sm",position:"right"}),i=mt(`<div>${mr}</div>`),y=Bt(d.peek()),p={font:M.observable(y.font),size:M.observable(String(y.size)),line:M.observable(String(y.line)),wrap:M.observable(y.wrap),caret:M.observable(Sn()),sidebar:M.observable(Pe().closeSidebar===!0)},w=qt(b.peek());p.indent=M.observable(w.indent),p.indentSize=M.observable(String(w.size));for(const T of["detect","autoIndent","continueLists","shortTags","tables","html","formatOnSave"])p[T]=M.observable(w[T]);const k=M.computed(()=>qt({indent:p.indent.value,size:p.indentSize.value,detect:p.detect.value,autoIndent:p.autoIndent.value,continueLists:p.continueLists.value,shortTags:p.shortTags.value,tables:p.tables.value,html:p.html.value,formatOnSave:p.formatOnSave.value})),x=M.effect(()=>{const T=k.value;JSON.stringify(T)!==JSON.stringify(qt(b.peek()))&&(b.value=T,Ke("code",T))}),j=M.effect(()=>{const T=p.sidebar.value;T!==(Pe().closeSidebar===!0)&&Ke("closeSidebar",T)}),c=M.computed(()=>Bt({font:p.font.value,size:p.size.value,line:p.line.value,wrap:p.wrap.value}));p.isDefault=M.computed(()=>kn(c.value)&&p.caret.value==="auto"&&!p.sidebar.value&&JSON.stringify(k.value)===JSON.stringify(Ht));const A=M.effect(()=>En(p.caret.value)),H=i.querySelector("#pe-set-font");for(const[T,ne]of[["mono","Monospace"],["sans","Other"],["serif",null]]){const Oe=gn.filter(re=>re.kind===T),O=ne?Object.assign(document.createElement("optgroup"),{label:ne}):H.querySelector("optgroup:last-of-type");O.append(...Oe.map(re=>new Option(re.label,re.id))),ne&&H.appendChild(O)}i.querySelector("#pe-set-indent-size").append(...cr.map(T=>new Option(String(T),String(T)))),i.querySelector("#pe-set-size").append(...wn.map(T=>new Option(`${T}px`,String(T)))),i.querySelector("#pe-set-line").append(...yn.map(T=>new Option({1.3:"Tight",1.45:"Snug",1.6:"Normal",1.8:"Relaxed",2:"Double"}[T]||String(T),String(T))));const Y=i.querySelector(".pe-settings-sample"),D=M.effect(()=>{const T=c.value;is(T.font);for(const[ne,Oe]of Object.entries(Va(T)))Y.style.setProperty(ne,Oe);Y.style.whiteSpace=T.wrap?"pre-wrap":"pre",Y.style.overflowX=T.wrap?"":"auto",JSON.stringify(T)!==JSON.stringify(Bt(d.peek()))&&(d.value=T,Ke("type",T))});p.reset=()=>{p.font.value=It.font,p.size.value=String(It.size),p.line.value=String(It.line),p.wrap.value=It.wrap,p.caret.value="auto",p.sidebar.value=!1,p.indent.value=Ht.indent,p.indentSize.value=String(Ht.size);for(const T of["detect","autoIndent","continueLists","shortTags","tables","html","formatOnSave"])p[T].value=Ht[T]},p.done=()=>v.close(),v.element.appendChild(i);const se=M.applyBindings(p,i),Vt=qa(i);return jt(v,()=>{se.dispose(),Vt(),D?.(),A?.(),j?.(),x?.()}),Domma.icons?.scan?.(i),v.open(),v}async function br(d){const b=E.slideover({title:"Share preview link",size:"md",position:"right"}),v=mt(`<div>${ur}</div>`),i={expiry:M.observable("7d"),note:M.observable(""),creating:M.observable(!1),url:M.observable(""),links:M.observable([]),loaded:M.observable(!1),listError:M.observable("")},y=async()=>{try{const w=await h.pages.previewLinks.list(d);i.links.value=w.filter(k=>!k.revokedAt&&!k.expired).map(k=>({id:k.id,title:k.label||"Untitled link",meta:`Expires ${pr(k.expiresAt)} - ${k.useCount===1?"1 view":`${k.useCount||0} views`}`})),i.listError.value=""}catch(w){i.listError.value="Could not load existing links: "+(w.message||"unknown error")}finally{i.loaded.value=!0}};i.create=async()=>{i.creating.value=!0;try{const w=await h.pages.previewLinks.create(d,i.expiry.peek(),i.note.peek().trim());i.url.value=w.url,i.note.value="",E.toast("Share link created.",{type:"success"}),await y(),v.querySelector(".pe-share-url")?.select()}catch(w){E.toast("Could not create link: "+(w.message||"unknown error"),{type:"error"})}finally{i.creating.value=!1}},i.copy=async()=>{try{await navigator.clipboard.writeText(i.url.peek()),E.toast("Link copied to clipboard.",{type:"success"})}catch{v.querySelector(".pe-share-url")?.select(),E.toast("Press Ctrl+C to copy the selected link.",{type:"info"})}},i.revoke=async w=>{if(await E.confirm("Revoke this link? Anyone holding it loses access immediately."))try{await h.pages.previewLinks.revoke(w),E.toast("Link revoked.",{type:"success"}),await y()}catch(k){E.toast("Could not revoke: "+(k.message||"unknown error"),{type:"error"})}};const p=M.applyBindings(i,v);jt(b,()=>p.dispose()),b.element.appendChild(v),b.open(),await y()}function vr(d){return new Promise(b=>{const v=E.slideover({title:"Save Named Version",size:"sm",position:"right"}),i=mt(`
97
+ </style>`;function hr(d,b){const v=E.slideover({title:"Editor settings",size:"sm",position:"right"}),i=mt(`<div>${gr}</div>`),k=It(d.peek()),u={font:M.observable(k.font),size:M.observable(String(k.size)),line:M.observable(String(k.line)),wrap:M.observable(k.wrap),caret:M.observable(Cn()),sidebar:M.observable(Pe().closeSidebar===!0)},w=Ht(b.peek());u.indent=M.observable(w.indent),u.indentSize=M.observable(String(w.size));for(const T of["detect","autoIndent","continueLists","shortTags","tables","html","formatOnSave"])u[T]=M.observable(w[T]);const y=M.computed(()=>Ht({indent:u.indent.value,size:u.indentSize.value,detect:u.detect.value,autoIndent:u.autoIndent.value,continueLists:u.continueLists.value,shortTags:u.shortTags.value,tables:u.tables.value,html:u.html.value,formatOnSave:u.formatOnSave.value})),x=M.effect(()=>{const T=y.value;JSON.stringify(T)!==JSON.stringify(Ht(b.peek()))&&(b.value=T,Ke("code",T))}),j=M.effect(()=>{const T=u.sidebar.value;T!==(Pe().closeSidebar===!0)&&Ke("closeSidebar",T)}),c=M.computed(()=>It({font:u.font.value,size:u.size.value,line:u.line.value,wrap:u.wrap.value}));u.isDefault=M.computed(()=>En(c.value)&&u.caret.value==="auto"&&!u.sidebar.value&&JSON.stringify(y.value)===JSON.stringify(Vt));const A=M.effect(()=>xn(u.caret.value)),H=i.querySelector("#pe-set-font");for(const[T,ne]of[["mono","Monospace"],["sans","Other"],["serif",null]]){const Oe=wn.filter(re=>re.kind===T),O=ne?Object.assign(document.createElement("optgroup"),{label:ne}):H.querySelector("optgroup:last-of-type");O.append(...Oe.map(re=>new Option(re.label,re.id))),ne&&H.appendChild(O)}i.querySelector("#pe-set-indent-size").append(...mr.map(T=>new Option(String(T),String(T)))),i.querySelector("#pe-set-size").append(...Tn.map(T=>new Option(`${T}px`,String(T)))),i.querySelector("#pe-set-line").append(...Mn.map(T=>new Option({1.3:"Tight",1.45:"Snug",1.6:"Normal",1.8:"Relaxed",2:"Double"}[T]||String(T),String(T))));const Y=i.querySelector(".pe-settings-sample"),D=M.effect(()=>{const T=c.value;is(T.font);for(const[ne,Oe]of Object.entries(Va(T)))Y.style.setProperty(ne,Oe);Y.style.whiteSpace=T.wrap?"pre-wrap":"pre",Y.style.overflowX=T.wrap?"":"auto",JSON.stringify(T)!==JSON.stringify(It(d.peek()))&&(d.value=T,Ke("type",T))});u.reset=()=>{u.font.value=Ft.font,u.size.value=String(Ft.size),u.line.value=String(Ft.line),u.wrap.value=Ft.wrap,u.caret.value="auto",u.sidebar.value=!1,u.indent.value=Vt.indent,u.indentSize.value=String(Vt.size);for(const T of["detect","autoIndent","continueLists","shortTags","tables","html","formatOnSave"])u[T].value=Vt[T]},u.done=()=>v.close(),v.element.appendChild(i);const se=M.applyBindings(u,i),_t=qa(i);return Bt(v,()=>{se.dispose(),_t(),D?.(),A?.(),j?.(),x?.()}),Domma.icons?.scan?.(i),v.open(),v}async function yr(d){const b=E.slideover({title:"Share preview link",size:"md",position:"right"}),v=mt(`<div>${vr}</div>`),i={expiry:M.observable("7d"),note:M.observable(""),creating:M.observable(!1),url:M.observable(""),links:M.observable([]),loaded:M.observable(!1),listError:M.observable("")},k=async()=>{try{const w=await h.pages.previewLinks.list(d);i.links.value=w.filter(y=>!y.revokedAt&&!y.expired).map(y=>({id:y.id,title:y.label||"Untitled link",meta:`Expires ${br(y.expiresAt)} - ${y.useCount===1?"1 view":`${y.useCount||0} views`}`})),i.listError.value=""}catch(w){i.listError.value="Could not load existing links: "+(w.message||"unknown error")}finally{i.loaded.value=!0}};i.create=async()=>{i.creating.value=!0;try{const w=await h.pages.previewLinks.create(d,i.expiry.peek(),i.note.peek().trim());i.url.value=w.url,i.note.value="",E.toast("Share link created.",{type:"success"}),await k(),v.querySelector(".pe-share-url")?.select()}catch(w){E.toast("Could not create link: "+(w.message||"unknown error"),{type:"error"})}finally{i.creating.value=!1}},i.copy=async()=>{try{await navigator.clipboard.writeText(i.url.peek()),E.toast("Link copied to clipboard.",{type:"success"})}catch{v.querySelector(".pe-share-url")?.select(),E.toast("Press Ctrl+C to copy the selected link.",{type:"info"})}},i.revoke=async w=>{if(await E.confirm("Revoke this link? Anyone holding it loses access immediately."))try{await h.pages.previewLinks.revoke(w),E.toast("Link revoked.",{type:"success"}),await k()}catch(y){E.toast("Could not revoke: "+(y.message||"unknown error"),{type:"error"})}};const u=M.applyBindings(i,v);Bt(b,()=>u.dispose()),b.element.appendChild(v),b.open(),await k()}function kr(d){return new Promise(b=>{const v=E.slideover({title:"Save Named Version",size:"sm",position:"right"}),i=mt(`
98
98
  <div style="padding:1rem">
99
99
  <label class="form-label" for="pe-version-label">Version Label</label>
100
100
  <input id="pe-version-label" type="text" class="form-input" style="margin-bottom:.75rem"
101
101
  placeholder="e.g. Initial design, Before restructure" data-model="label.value" data-on-keydown="key">
102
102
  <button type="button" class="btn btn-primary" data-on-click="save" data-bind-disabled="saving.value">Save Version</button>
103
- </div>`);let y=!1;const p={label:M.observable(""),saving:M.observable(!1)};p.save=async()=>{p.saving.value=!0;try{await h.versions.create(d,p.label.peek().trim()||null),E.toast("Named version saved.",{type:"success"}),y=!0,v.close()}catch(k){E.toast("Failed to save version: "+k.message,{type:"error"})}finally{p.saving.value=!1}},p.key=k=>{k.key==="Enter"&&(k.preventDefault(),p.save())};const w=M.applyBindings(p,i);jt(v,()=>{w.dispose(),b(y)}),v.element.appendChild(i),v.open(),setTimeout(()=>i.querySelector("input")?.focus(),100)})}const gr=`<div class="card">
103
+ </div>`);let k=!1;const u={label:M.observable(""),saving:M.observable(!1)};u.save=async()=>{u.saving.value=!0;try{await h.versions.create(d,u.label.peek().trim()||null),E.toast("Named version saved.",{type:"success"}),k=!0,v.close()}catch(y){E.toast("Failed to save version: "+y.message,{type:"error"})}finally{u.saving.value=!1}},u.key=y=>{y.key==="Enter"&&(y.preventDefault(),u.save())};const w=M.applyBindings(u,i);Bt(v,()=>{w.dispose(),b(k)}),v.element.appendChild(i),v.open(),setTimeout(()=>i.querySelector("input")?.focus(),100)})}const wr=`<div class="card">
104
104
  <h3>{{title}}</h3>
105
105
  <p>{{description}}</p>
106
106
  </div>
107
- `,hr=`
107
+ `,Sr=`
108
108
  <div class="pe-new">
109
109
  <p class="form-hint" style="margin-top:0" data-bind-text="hint.value"></p>
110
110
  <label class="form-label" for="pe-new-name">Name</label>
@@ -124,7 +124,7 @@ The quick brown fox - 0O 1lI {} [] () =&gt; ==
124
124
  .pe-new [hidden] { display: none !important; }
125
125
  .pe-new-err { display: block; margin-top: .3rem; color: var(--dm-danger); font-size: var(--dm-text-xs); }
126
126
  .pe-new-actions { display: flex; justify-content: flex-end; gap: .5rem; margin-top: 1.25rem; }
127
- </style>`;function ls({kind:d,projects:b,taken:v,project:i="",name:y="",check:p,create:w,register:k=()=>{}}){return new Promise(x=>{const j=E.slideover({title:d==="block"?"New block":"New component",size:"sm",position:"right"});k(()=>{try{j.close()}catch{}});const c=mt(`<div>${hr}</div>`);for(const D of b)c.querySelector("#pe-new-project").append(new Option(D.name||D.slug,D.slug));const A={name:M.observable(y),project:M.observable(i),busy:M.observable(!1),hint:M.observable(d==="block"?"A block is a reusable piece of HTML with {{placeholders}}, used on pages with its short tag or by a collection display. Its name is its tag - fixed once created.":"A component is a custom element - <dm-name> - with a template, props, a script and a style. Its name is its tag - fixed once created."),placeholder:M.observable(d==="block"?"e.g. team-card":"e.g. pricing-table")};A.error=M.computed(()=>A.name.value.trim()?p(A.name.value.trim(),v):""),A.canCreate=M.computed(()=>!A.busy.value&&!!A.name.value.trim()&&!p(A.name.value.trim(),v));let H="";A.create=async()=>{const D=A.name.peek().trim();if(!(!D||A.error.peek()||A.busy.peek())){A.busy.value=!0;try{await w(D,A.project.peek()),H=D,j.close()}catch(se){E.toast(`Not created: ${se.message||se}`,{type:"error"})}finally{A.busy.value=!1}}},A.cancel=()=>j.close(),A.key=D=>{D.key==="Enter"&&(D.preventDefault(),A.create())};const Y=M.applyBindings(A,c);jt(j,()=>{Y.dispose(),x(H)}),j.element.appendChild(c),c.querySelector("#pe-new-project").value=i,j.open(),setTimeout(()=>{const D=c.querySelector("#pe-new-name");D?.focus(),D?.select()},100)})}let F=null,cs=!1;function kr(){cs||!window.R?.use||(cs=!0,On(),R.use((d,b,v)=>{if(F&&!F.alive()){const p=F;F=null,p.dispose()}const i=b?.path||"",y=d?.path||"";if(!F||!Oo.test(i))return v();if(Oo.test(y)){const p=Ua(y);if(p){F.open(p,y);return}return v()}return F.dirty()?E.confirm("You have unsaved changes. Leave anyway? They are kept as drafts for your next visit.").then(p=>{p?(F?.keepDraft(),v()):F&&history.replaceState({pe:1},"","#"+F.address)}):v()}),M.subscribe("router:afterChange",({to:d}={})=>{if(F&&!Oo.test(d?.path||"")){const b=F;F=null,b.dispose()}}))}const ds="editor_prefs";function Pe(){return S.get(ds)||{viewMode:"split",fullscreen:!1}}const yr=()=>{try{return Pe()||{}}catch{return{}}};function Ke(d,b){const v=Pe();v[d]=b,S.set(ds,v)}const ps="editor-workspace.tabs",us="editor-workspace.folded",ft="editor-workspace.css",wr="/__block-preview",Sr=d=>d.replace(/<\/head>/i,"<style>body.dm-cloaked{opacity:1 !important;transition:none !important}</style></head>");function Er(d,b,v=()=>{}){let i=0;try{i=d.contentWindow.scrollY||0}catch{}d.addEventListener("load",()=>{try{d.contentWindow.scrollTo(0,i)}catch{}v()},{once:!0}),d.srcdoc=b}const Tr=["urlPath","title","description","layout","status","sortOrder","category","visibility","project","theme","seoTitle","seoDesc","seoSchema","dconfig"],Mr=["showInNav","sidebar","breadcrumbs","bundled"],ms=()=>({urlPath:"",title:"",description:"",layout:"",status:"draft",sortOrder:"99",showInNav:!1,sidebar:!1,breadcrumbs:!0,bundled:!1,tags:[],adminTags:[],category:"",visibility:"public",project:"",theme:"",seoTitle:"",seoDesc:"",seoSchema:"",dconfig:"",body:"",css:null});export const pageEditorView={templateUrl:"/admin/js/templates/page-editor.html",async onMount(d){if(kr(),F){const e=F;F=null,e.dispose()}const b=window.location.hash.replace(/^#/,""),v=[],i=e=>(v.push(e),e);let y=()=>!1,p=()=>{},w=()=>{};const k=d.get(0),x=k.querySelector("#pe-workspace"),j={address:b,alive:()=>x?.isConnected===!0,dirty:()=>y(),keepDraft:()=>p(),open:(e,t)=>w(e,t),dispose:()=>{v.splice(0).forEach(e=>{try{e()}catch{}})}};F=j;const c=()=>F===j&&j.alive();if(yr().closeSidebar===!0){const e=document.querySelector("#admin-sidebar");e&&!Ja(e)&&!window.matchMedia("(max-width: 768px)").matches&&(Wa(e,!0,!1),i(()=>{e.isConnected&&Ja(e)&&Wa(e,!1,!1)}))}const A=E.loader(k,{type:"dots"});let[H,Y,D,se,Vt,T,ne,Oe]=await Promise.all([h.layouts.get().catch(()=>({})),h.settings.get().catch(()=>({})),h.pages.list().catch(()=>[]),h.projects.list().catch(()=>[]),h.pages.tags().catch(()=>[]),h.listTags.list("pages").then(e=>e.map(t=>t.name)).catch(()=>[]),h.get("/blocks?usage=1").catch(()=>h.blocks.list()).catch(()=>[]),h.components.list().catch(()=>[])]);if(!c()){A.destroy();return}A.destroy();const O=e=>k.querySelector(e);if(D=Array.isArray(D)?D:[],cn(O("#field-theme"),{includeDefault:!0}),await Ar(O("#field-visibility")),!c())return;const re=Object.keys(H||{});Or(O("#field-layout"),H,re[0]||"default");const Ho=e=>re.includes(e)?e:re[0]||e||"default";for(const e of se)for(const t of["#field-project","#block-project","#comp-project"])O(t).append(new Option(e.name||e.slug,e.slug));let ie=Array.isArray(ne)?ne:[],bt=Ya(ie);const vt=new Map(ie.map(e=>[e.name,e.updatedAt])),Ue=new Map(ie.map(e=>[e.name,e.usage])),be=new Set(ie.map(e=>e.name)),Vo=async()=>{const e=await h.get("/blocks?usage=1").catch(()=>null);if(!(!c()||!Array.isArray(e))){ie=e,bt=Ya(ie);for(const t of ie)be.add(t.name),Ue.set(t.name,t.usage),vt.has(t.name)||vt.set(t.name,t.updatedAt)}},_t=Array.isArray(Y?.footer?.blocks)?Y.footer.blocks.filter(e=>typeof e=="string"):[];let Je=Array.isArray(Oe)?Oe.filter(e=>typeof e?.name=="string"):[];const le=new Set(Je.map(e=>e.name)),_o=async()=>{const e=await h.components.list().catch(()=>null);if(!(!c()||!Array.isArray(e))){Je=e.filter(t=>typeof t?.name=="string");for(const t of Je)le.add(t.name)}},Z=Pe(),u={urlPath:M.observable(""),title:M.observable(""),description:M.observable(""),layout:M.observable(Ho("default")),status:M.observable("draft"),sortOrder:M.observable("99"),showInNav:M.observable(!1),sidebar:M.observable(!1),breadcrumbs:M.observable(!0),bundled:M.observable(!1),tags:M.observable([]),adminTags:M.observable([]),category:M.observable(""),visibility:M.observable("public"),project:M.observable(""),theme:M.observable(""),seoTitle:M.observable(""),seoDesc:M.observable(""),seoSchema:M.observable(""),dconfig:M.observable(""),css:M.observable(""),cssOpened:M.observable(!1)},a={bodyRev:M.observable(0),base:M.observable(""),saving:M.observable(!1),viewMode:M.observable(jo(Z.viewMode)),fullscreen:M.observable(!!Z.fullscreen),explorerOn:M.observable(Z.explorer??!window.matchMedia("(max-width: 1024px)").matches),dockOn:M.observable(!!Z.dock),dockTab:M.observable("details"),seoSchemaNote:M.observable(""),cssMode:M.observable(!1),folded:M.observable(!1),previewStatus:M.observable("Showing unsaved changes"),liveWidth:M.observable("full"),versions:M.observable([]),histLoading:M.observable(!1),histError:M.observable(""),compare:M.observable(null),heldNote:M.observable(""),tabs:M.observable([]),active:M.observable(""),curId:M.observable(null),blockTab:M.observable(""),blockPart:M.observable("html"),blockReady:M.observable(!1),blockNote:M.observable(""),blockUses:M.observable(""),blockProject:M.observable(""),blockBundled:M.observable(!1),blockWhere:M.observable(""),compTab:M.observable(""),compPart:M.observable("template"),compReady:M.observable(!1),compNote:M.observable(""),compReadOnly:M.observable(!1),compState:M.observable(""),compErrors:M.observable(""),compProject:M.observable(""),compBundled:M.observable(!1),blockRev:M.observable(0),compRev:M.observable(0),docRev:M.observable(0),filter:M.observable(""),secHere:M.observable(Z.secHere!==!1),secPages:M.observable(Z.secPages!==!1),secBlocks:M.observable(Z.secBlocks!==!1),secComps:M.observable(Z.secComps!==!1),thisPage:M.observable([]),pageRows:M.observable([]),blockRows:M.observable([]),compRows:M.observable([])},V=O("#markdown-editor"),ve=O("#css-editor"),fs=_a(V),bs=_a(ve);i(()=>fs.destroy()),i(()=>bs.destroy());const ce=document.createElement("div");ce.className="editor-line-numbers editor-line-numbers--foldable",V.parentElement.insertBefore(ce,V);const We=ns(V,"md"),Kt=ns(ve,"css");i(()=>{We.destroy(),Kt.destroy()});const Ko=()=>{We.paint(),Kt.paint()},Q=dn(V,ce,{onFoldChange:()=>We.paint()});let gt=!1;Q.setGuard(e=>{gt=e});const Ut=()=>Q.getUnfoldedContent(),Jt=()=>{Q.unfoldAll(),a.folded.value=!1,We.paint()},vs=e=>{if(e?.kind==="page")Jt(),_e(V,"md");else if(e?.kind==="block")oe&&_e(oe.textarea,"html"),me&&_e(me.textarea,"css");else if(e?.kind==="component"){if(N.get(e.id)?.readOnly)return;for(const[o,s]of Object.entries({template:"html",props:"json",script:"js",style:"css"}))ae[o]&&_e(ae[o].textarea,s)}},Uo=e=>{e.error?E.toast(e.error,{type:"warning"}):E.toast(e.unchanged?"Already tidy":"Formatted",{type:"info",duration:900})},Jo=M.observable(Bt(Z.type)),Wo=M.observable(qt(Z.code));i(M.effect(()=>{const e=Wo.value;dr(e),O("#editor-body")?.style.setProperty("--pe-tab",String(e.size))})),i(M.effect(()=>{const e=Jo.value,t=O("#editor-body");if(t){is(e.font);for(const[o,s]of Object.entries(Va(e)))t.style.setProperty(o,s);t.classList.toggle("pe-nowrap",!e.wrap),V.wrap=e.wrap?"soft":"off",ve.wrap=e.wrap?"soft":"off",requestAnimationFrame(()=>{c()&&Ko()})}}));let Yo=null;i(()=>{try{Yo?.close()}catch{}});const _=()=>(a.bodyRev.value,{urlPath:u.urlPath.value.trim(),title:u.title.value,description:u.description.value,layout:u.layout.value,status:u.status.value,sortOrder:u.sortOrder.value,showInNav:u.showInNav.value,sidebar:u.sidebar.value,breadcrumbs:u.breadcrumbs.value,bundled:u.bundled.value,tags:u.tags.value,adminTags:u.adminTags.value,category:u.category.value,visibility:u.visibility.value,project:u.project.value,theme:u.theme.value,seoTitle:u.seoTitle.value,seoDesc:u.seoDesc.value,seoSchema:u.seoSchema.value,dconfig:u.dconfig.value,body:Ut(),css:null}),Go=()=>M.untracked?M.untracked(_):_(),ee=M.observable(""),ht=()=>u.cssOpened.peek()&&u.css.peek()!==ee.peek(),K=new Map;let m=null;const L=new Map,N=new Map;let P=[];const de=e=>Do(e.form)!==e.base,ge=()=>[...L.entries()].filter(([,e])=>de(e)).map(([e])=>e),he=e=>!e.readOnly&&Fo({name:e.name,...e.form})!==e.base,Ye=()=>[...N.values()].filter(he).map(e=>e.name),Wt=()=>W(Go())!==a.base.peek(),Yt=e=>e.loaded&&(e===m?Wt():W(e.state)!==e.base),Ae=()=>[...K.values()].filter(Yt),gs=M.computed(()=>W(_())!==a.base.value),hs=M.computed(()=>u.cssOpened.value&&u.css.value!==ee.value),ks=M.computed(()=>(a.blockRev.value,a.compRev.value,a.docRev.value,W(_())!==a.base.value||u.cssOpened.value&&u.css.value!==ee.value||Ae().some(e=>e!==m)||ge().length>0||Ye().length>0)),ys=M.computed(()=>{a.blockRev.value,a.compRev.value;const e=I(a.active.value);if(e?.kind==="block"){const t=L.get(e.id);return!!(t&&de(t))}if(e?.kind==="component"){const t=N.get(e.id);return!!(t&&he(t))}return W(_())!==a.base.value||u.cssOpened.value&&u.css.value!==ee.value}),ws=M.computed(()=>a.curId.value!==null),Xo=M.computed(()=>I(a.active.value)?.kind||""),Zo=M.computed(()=>!!a.curId.value&&I(a.active.value)?.kind==="page"),Ss=M.computed(()=>u.urlPath.value.trim()||a.curId.value||""),Es=M.computed(()=>Ao({urlPath:u.urlPath.value,dconfig:u.dconfig.value})[0]?.text||""),Ts=M.computed(()=>{a.docRev.value;const e=I(a.active.value);return e?e.kind==="block"?a.blockUses.value:e.kind==="component"?Un({name:e.id,readOnly:a.compReadOnly.value,state:a.compReady.value?a.compState.value:""}):Xn({urlPath:u.urlPath.value,status:u.status.value,isEdit:!!a.curId.value}):""}),Qo=M.computed(()=>a.compTab.value?"component":a.blockTab.value?"block":a.curId.value!==null?"page":""),Ms=M.computed(()=>a.blockTab.value?`[${a.blockTab.value} /]`:""),Cs=M.computed(()=>({compiling:"Compiling\u2026",ok:"Compiles",error:"Does not compile"})[a.compState.value]||""),xs=M.computed(()=>a.compTab.value?`<dm-${a.compTab.value}>`:""),Ps=M.computed(()=>a.versions.value.some(e=>e.checked.value)),Os=M.computed(()=>a.versions.value.length>0&&a.versions.value.every(e=>e.checked.value)),As=M.computed(()=>{const e=a.versions.value.filter(t=>t.checked.value).length;return e>0&&e<a.versions.value.length});y=()=>Ae().length>0||ge().length>0||Ye().length>0||ht();const Gt=(e,t,o)=>({title:String(e.title||"").trim()||"Untitled",description:String(e.description||"").trim(),layout:e.layout,status:e.status,sortOrder:parseInt(String(e.sortOrder),10)||99,showInNav:!!e.showInNav,sidebar:!!e.sidebar,...e.breadcrumbs?{}:{breadcrumbs:!1},...e.bundled?{bundled:!0}:{},tags:Array.isArray(e.tags)?e.tags:[],...t?.isEdit&&JSON.stringify(e.adminTags)===t.savedAdminTags?{}:{adminTags:Array.isArray(e.adminTags)?e.adminTags:[]},category:String(e.category||"").trim()||null,visibility:e.visibility||"public",project:e.project||"",seo:{title:String(e.seoTitle||"").trim(),description:String(e.seoDesc||"").trim(),...ea(e)?{schema:ea(e)}:t?.isEdit?{schema:null}:{}},dconfig:o,...e.theme?{theme:e.theme}:{}}),ea=e=>Po(e.seoSchema).value,Xt=e=>{const t=String(e.dconfig||"").trim();if(!t)return null;try{return JSON.parse(t)}catch{return null}},Rs=()=>u.urlPath.peek().trim()||m?.id||"/";let kt=[],ta=[];const yt=e=>kt.includes(e)||_t.includes(e);let Re=new Set;const wt=()=>{const e=[...new Set([...kt,..._t,...L.keys()])],t=Pn(e.filter(s=>!L.has(s)),vt);Re=new Set(Object.keys(t));const o=Re.size?`Preview shows unsaved changes to ${[...Re].join(", ")}`:"";return o!==a.heldNote.peek()&&(a.heldNote.value=o),In(t,[...L.entries()].map(([s,r])=>({name:s,content:r.form.content,css:r.form.css,dirty:de(r)})))};let Zt="";const $s=()=>{oa();const e=Zt;if(e){Zt="";try{$e.contentDocument?.querySelector(`[data-block="${CSS.escape(e)}"]`)?.scrollIntoView({block:"center"})}catch{}}},$e=O("#markdown-preview");h.settings.getCustomCss().then(({css:e})=>{if(!c())return;ee.value=e||"";let t=null;try{t=S.get(ft)}catch{}typeof t=="string"&&t!==ee.peek()?(ia(),u.css.value=t,E.toast("Your unsaved custom CSS is back - the CSS button shows it.",{type:"info"})):u.cssOpened.peek()||(u.css.value=ee.peek()),J(ft)}).catch(()=>{});const oa=()=>{const e=$e?.contentDocument;if(!e?.head)return;const t=u.cssOpened.peek()?u.css.peek():"";if(!t)return;let o=e.getElementById("preview-custom-css");o||(o=e.createElement("style"),o.id="preview-custom-css",e.head.appendChild(o)),o.textContent=t};let Qt=null,eo=0;const U=(e=!1)=>{clearTimeout(Qt),Qt=setTimeout(async()=>{if(!$e||a.viewMode.peek()==="write"||!a.active.peek()||a.compTab.peek())return;const t=++eo,o=a.blockTab.peek();a.previewStatus.value="Rendering\u2026";try{let s;if(o&&(!m||!yt(o)))({html:s}=await h.pages.previewFull(wr,{title:o,layout:"blank",breadcrumbs:!1},Hn(o,Vs(o)),wt()));else if(m){const r=_();({html:s}=await h.pages.previewFull(Rs(),Gt(r,m,Xt(r)),r.body,wt()))}else{$e.srcdoc="";return}if(!c()||t!==eo)return;Er($e,Bn(Sr(s),o),$s),a.previewStatus.value="Showing unsaved changes"}catch(s){if(!c()||t!==eo)return;a.previewStatus.value="Preview failed - "+(s?.message||"unknown error"),$e.srcdoc='<!doctype html><meta charset="utf-8"><body style="font:14px system-ui;padding:1rem;color:#b91c1c;">Preview failed: '+String(s?.message||"unknown error").replace(/[<&]/g,r=>r==="<"?"&lt;":"&amp;")+"</body>"}},e?0:500)};i(()=>clearTimeout(Qt));const to=an(d.find("#markdown-editor"),d.find("#editor-toolbar"),{spacerDefault:Y?.layoutOptions?.spacerSize??40,beforeFormat:()=>Jt()});rn(V,{blocks:()=>bt,openBlock:e=>Be(e)});const Ge=k.querySelector(".editor-toolbar-right");Ge.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}')`)}),O("#fullscreen-btn")?.setAttribute("data-on-click","toggleFullscreen");const Ls=mt(`
127
+ </style>`;function ls({kind:d,projects:b,taken:v,project:i="",name:k="",check:u,create:w,register:y=()=>{}}){return new Promise(x=>{const j=E.slideover({title:d==="block"?"New block":"New component",size:"sm",position:"right"});y(()=>{try{j.close()}catch{}});const c=mt(`<div>${Sr}</div>`);for(const D of b)c.querySelector("#pe-new-project").append(new Option(D.name||D.slug,D.slug));const A={name:M.observable(k),project:M.observable(i),busy:M.observable(!1),hint:M.observable(d==="block"?"A block is a reusable piece of HTML with {{placeholders}}, used on pages with its short tag or by a collection display. Its name is its tag - fixed once created.":"A component is a custom element - <dm-name> - with a template, props, a script and a style. Its name is its tag - fixed once created."),placeholder:M.observable(d==="block"?"e.g. team-card":"e.g. pricing-table")};A.error=M.computed(()=>A.name.value.trim()?u(A.name.value.trim(),v):""),A.canCreate=M.computed(()=>!A.busy.value&&!!A.name.value.trim()&&!u(A.name.value.trim(),v));let H="";A.create=async()=>{const D=A.name.peek().trim();if(!(!D||A.error.peek()||A.busy.peek())){A.busy.value=!0;try{await w(D,A.project.peek()),H=D,j.close()}catch(se){E.toast(`Not created: ${se.message||se}`,{type:"error"})}finally{A.busy.value=!1}}},A.cancel=()=>j.close(),A.key=D=>{D.key==="Enter"&&(D.preventDefault(),A.create())};const Y=M.applyBindings(A,c);Bt(j,()=>{Y.dispose(),x(H)}),j.element.appendChild(c),c.querySelector("#pe-new-project").value=i,j.open(),setTimeout(()=>{const D=c.querySelector("#pe-new-name");D?.focus(),D?.select()},100)})}let F=null,cs=!1;function Er(){cs||!window.R?.use||(cs=!0,Ln(),R.use((d,b,v)=>{if(F&&!F.alive()){const u=F;F=null,u.dispose()}const i=b?.path||"",k=d?.path||"";if(!F||!Oo.test(i))return v();if(Oo.test(k)){const u=Ua(k);if(u){F.open(u,k);return}return v()}return F.dirty()?E.confirm("You have unsaved changes. Leave anyway? They are kept as drafts for your next visit.").then(u=>{u?(F?.keepDraft(),v()):F&&history.replaceState({pe:1},"","#"+F.address)}):v()}),M.subscribe("router:afterChange",({to:d}={})=>{if(F&&!Oo.test(d?.path||"")){const b=F;F=null,b.dispose()}}))}const ds="editor_prefs";function Pe(){return S.get(ds)||{viewMode:"split",fullscreen:!1}}let Mr=null;const Tr=()=>Mr??(Mr=h.pages.dommaCatalogue().then(d=>(kn(d),yn()))),Cr=d=>{try{return document.createDocumentFragment().querySelector(d),!0}catch{return!1}},xr=()=>{try{return Pe()||{}}catch{return{}}};function Ke(d,b){const v=Pe();v[d]=b,S.set(ds,v)}const ps="editor-workspace.tabs",us="editor-workspace.folded",ft="editor-workspace.css",Pr="/__block-preview",Or=d=>d.replace(/<\/head>/i,"<style>body.dm-cloaked{opacity:1 !important;transition:none !important}</style></head>");function Rr(d,b,v=()=>{}){let i=0;try{i=d.contentWindow.scrollY||0}catch{}d.addEventListener("load",()=>{try{d.contentWindow.scrollTo(0,i)}catch{}v()},{once:!0}),d.srcdoc=b}const Ar=["urlPath","title","description","layout","status","sortOrder","category","visibility","project","theme","seoTitle","seoDesc","seoSchema","dconfig"],$r=["showInNav","sidebar","breadcrumbs","bundled"],ms=()=>({urlPath:"",title:"",description:"",layout:"",status:"draft",sortOrder:"99",showInNav:!1,sidebar:!1,breadcrumbs:!0,bundled:!1,tags:[],adminTags:[],category:"",visibility:"public",project:"",theme:"",seoTitle:"",seoDesc:"",seoSchema:"",dconfig:"",body:"",css:null});export const pageEditorView={templateUrl:"/admin/js/templates/page-editor.html",async onMount(d){if(Er(),F){const e=F;F=null,e.dispose()}const b=window.location.hash.replace(/^#/,""),v=[],i=e=>(v.push(e),e);let k=()=>!1,u=()=>{},w=()=>{};const y=d.get(0),x=y.querySelector("#pe-workspace"),j={address:b,alive:()=>x?.isConnected===!0,dirty:()=>k(),keepDraft:()=>u(),open:(e,t)=>w(e,t),dispose:()=>{v.splice(0).forEach(e=>{try{e()}catch{}})}};F=j;const c=()=>F===j&&j.alive();if(xr().closeSidebar===!0){const e=document.querySelector("#admin-sidebar");e&&!Ja(e)&&!window.matchMedia("(max-width: 768px)").matches&&(Wa(e,!0,!1),i(()=>{e.isConnected&&Ja(e)&&Wa(e,!1,!1)}))}const A=E.loader(y,{type:"dots"});let[H,Y,D,se,_t,T,ne,Oe]=await Promise.all([h.layouts.get().catch(()=>({})),h.settings.get().catch(()=>({})),h.pages.list().catch(()=>[]),h.projects.list().catch(()=>[]),h.pages.tags().catch(()=>[]),h.listTags.list("pages").then(e=>e.map(t=>t.name)).catch(()=>[]),h.get("/blocks?usage=1").catch(()=>h.blocks.list()).catch(()=>[]),h.components.list().catch(()=>[])]);if(!c()){A.destroy();return}A.destroy();const O=e=>y.querySelector(e);if(D=Array.isArray(D)?D:[],dn(O("#field-theme"),{includeDefault:!0}),await Br(O("#field-visibility")),!c())return;const re=Object.keys(H||{});jr(O("#field-layout"),H,re[0]||"default");const Ho=e=>re.includes(e)?e:re[0]||e||"default";for(const e of se)for(const t of["#field-project","#block-project","#comp-project"])O(t).append(new Option(e.name||e.slug,e.slug));let ie=Array.isArray(ne)?ne:[],bt=Ya(ie);const vt=new Map(ie.map(e=>[e.name,e.updatedAt])),Ue=new Map(ie.map(e=>[e.name,e.usage])),be=new Set(ie.map(e=>e.name)),Vo=async()=>{const e=await h.get("/blocks?usage=1").catch(()=>null);if(!(!c()||!Array.isArray(e))){ie=e,bt=Ya(ie);for(const t of ie)be.add(t.name),Ue.set(t.name,t.usage),vt.has(t.name)||vt.set(t.name,t.updatedAt)}},Kt=Array.isArray(Y?.footer?.blocks)?Y.footer.blocks.filter(e=>typeof e=="string"):[];let Je=Array.isArray(Oe)?Oe.filter(e=>typeof e?.name=="string"):[];const le=new Set(Je.map(e=>e.name)),_o=async()=>{const e=await h.components.list().catch(()=>null);if(!(!c()||!Array.isArray(e))){Je=e.filter(t=>typeof t?.name=="string");for(const t of Je)le.add(t.name)}},Z=Pe(),p={urlPath:M.observable(""),title:M.observable(""),description:M.observable(""),layout:M.observable(Ho("default")),status:M.observable("draft"),sortOrder:M.observable("99"),showInNav:M.observable(!1),sidebar:M.observable(!1),breadcrumbs:M.observable(!0),bundled:M.observable(!1),tags:M.observable([]),adminTags:M.observable([]),category:M.observable(""),visibility:M.observable("public"),project:M.observable(""),theme:M.observable(""),seoTitle:M.observable(""),seoDesc:M.observable(""),seoSchema:M.observable(""),dconfig:M.observable(""),css:M.observable(""),cssOpened:M.observable(!1)},o={bodyRev:M.observable(0),base:M.observable(""),saving:M.observable(!1),viewMode:M.observable(jo(Z.viewMode)),fullscreen:M.observable(!!Z.fullscreen),explorerOn:M.observable(Z.explorer??!window.matchMedia("(max-width: 1024px)").matches),dockOn:M.observable(!!Z.dock),dockTab:M.observable("details"),seoSchemaNote:M.observable(""),catalogue:M.observable(null),cssMode:M.observable(!1),folded:M.observable(!1),previewStatus:M.observable("Showing unsaved changes"),liveWidth:M.observable("full"),versions:M.observable([]),histLoading:M.observable(!1),histError:M.observable(""),compare:M.observable(null),heldNote:M.observable(""),tabs:M.observable([]),active:M.observable(""),curId:M.observable(null),blockTab:M.observable(""),blockPart:M.observable("html"),blockReady:M.observable(!1),blockNote:M.observable(""),blockUses:M.observable(""),blockProject:M.observable(""),blockBundled:M.observable(!1),blockWhere:M.observable(""),compTab:M.observable(""),compPart:M.observable("template"),compReady:M.observable(!1),compNote:M.observable(""),compReadOnly:M.observable(!1),compState:M.observable(""),compErrors:M.observable(""),compProject:M.observable(""),compBundled:M.observable(!1),blockRev:M.observable(0),compRev:M.observable(0),docRev:M.observable(0),filter:M.observable(""),secHere:M.observable(Z.secHere!==!1),secPages:M.observable(Z.secPages!==!1),secBlocks:M.observable(Z.secBlocks!==!1),secComps:M.observable(Z.secComps!==!1),thisPage:M.observable([]),pageRows:M.observable([]),blockRows:M.observable([]),compRows:M.observable([])},V=O("#markdown-editor"),ve=O("#css-editor"),fs=_a(V),bs=_a(ve);i(()=>fs.destroy()),i(()=>bs.destroy());const ce=document.createElement("div");ce.className="editor-line-numbers editor-line-numbers--foldable",V.parentElement.insertBefore(ce,V);const We=ns(V,"md"),Ut=ns(ve,"css");i(()=>{We.destroy(),Ut.destroy()});const Ko=()=>{We.paint(),Ut.paint()},Q=pn(V,ce,{onFoldChange:()=>We.paint()});let gt=!1;Q.setGuard(e=>{gt=e});const ht=()=>Q.getUnfoldedContent(),Jt=()=>{Q.unfoldAll(),o.folded.value=!1,We.paint()},vs=e=>{if(e?.kind==="page")Jt(),_e(V,"md");else if(e?.kind==="block")oe&&_e(oe.textarea,"html"),me&&_e(me.textarea,"css");else if(e?.kind==="component"){if(N.get(e.id)?.readOnly)return;for(const[a,s]of Object.entries({template:"html",props:"json",script:"js",style:"css"}))ae[a]&&_e(ae[a].textarea,s)}},Uo=e=>{e.error?E.toast(e.error,{type:"warning"}):E.toast(e.unchanged?"Already tidy":"Formatted",{type:"info",duration:900})},Jo=M.observable(It(Z.type)),Wo=M.observable(Ht(Z.code));i(M.effect(()=>{const e=Wo.value;fr(e),O("#editor-body")?.style.setProperty("--pe-tab",String(e.size))})),i(M.effect(()=>{const e=Jo.value,t=O("#editor-body");if(t){is(e.font);for(const[a,s]of Object.entries(Va(e)))t.style.setProperty(a,s);t.classList.toggle("pe-nowrap",!e.wrap),V.wrap=e.wrap?"soft":"off",ve.wrap=e.wrap?"soft":"off",requestAnimationFrame(()=>{c()&&Ko()})}}));let Yo=null;i(()=>{try{Yo?.close()}catch{}});const _=()=>(o.bodyRev.value,{urlPath:p.urlPath.value.trim(),title:p.title.value,description:p.description.value,layout:p.layout.value,status:p.status.value,sortOrder:p.sortOrder.value,showInNav:p.showInNav.value,sidebar:p.sidebar.value,breadcrumbs:p.breadcrumbs.value,bundled:p.bundled.value,tags:p.tags.value,adminTags:p.adminTags.value,category:p.category.value,visibility:p.visibility.value,project:p.project.value,theme:p.theme.value,seoTitle:p.seoTitle.value,seoDesc:p.seoDesc.value,seoSchema:p.seoSchema.value,dconfig:p.dconfig.value,body:ht(),css:null}),Go=()=>M.untracked?M.untracked(_):_(),ee=M.observable(""),yt=()=>p.cssOpened.peek()&&p.css.peek()!==ee.peek(),K=new Map;let m=null;const L=new Map,N=new Map;let P=[];const de=e=>Do(e.form)!==e.base,ge=()=>[...L.entries()].filter(([,e])=>de(e)).map(([e])=>e),he=e=>!e.readOnly&&Fo({name:e.name,...e.form})!==e.base,Ye=()=>[...N.values()].filter(he).map(e=>e.name),Wt=()=>W(Go())!==o.base.peek(),Yt=e=>e.loaded&&(e===m?Wt():W(e.state)!==e.base),Re=()=>[...K.values()].filter(Yt),gs=M.computed(()=>W(_())!==o.base.value),hs=M.computed(()=>p.cssOpened.value&&p.css.value!==ee.value),ys=M.computed(()=>(o.blockRev.value,o.compRev.value,o.docRev.value,W(_())!==o.base.value||p.cssOpened.value&&p.css.value!==ee.value||Re().some(e=>e!==m)||ge().length>0||Ye().length>0)),ks=M.computed(()=>{o.blockRev.value,o.compRev.value;const e=I(o.active.value);if(e?.kind==="block"){const t=L.get(e.id);return!!(t&&de(t))}if(e?.kind==="component"){const t=N.get(e.id);return!!(t&&he(t))}return W(_())!==o.base.value||p.cssOpened.value&&p.css.value!==ee.value}),ws=M.computed(()=>o.curId.value!==null),Xo=M.computed(()=>I(o.active.value)?.kind||""),Zo=M.computed(()=>!!o.curId.value&&I(o.active.value)?.kind==="page"),Ss=M.computed(()=>p.urlPath.value.trim()||o.curId.value||""),Es=M.computed(()=>Ro({urlPath:p.urlPath.value,dconfig:p.dconfig.value})[0]?.text||""),Ms=M.computed(()=>(o.bodyRev.value,o.catalogue.value?hn({dconfig:p.dconfig.value,body:ht()},o.catalogue.value,{isSelector:Cr}).map((e,t)=>({key:`${t}:${e}`,text:e})):[]));Tr().then(e=>{o.catalogue.value=e});const Ts=M.computed(()=>{o.docRev.value;const e=I(o.active.value);return e?e.kind==="block"?o.blockUses.value:e.kind==="component"?Gn({name:e.id,readOnly:o.compReadOnly.value,state:o.compReady.value?o.compState.value:""}):tr({urlPath:p.urlPath.value,status:p.status.value,isEdit:!!o.curId.value}):""}),Qo=M.computed(()=>o.compTab.value?"component":o.blockTab.value?"block":o.curId.value!==null?"page":""),Cs=M.computed(()=>o.blockTab.value?`[${o.blockTab.value} /]`:""),xs=M.computed(()=>({compiling:"Compiling\u2026",ok:"Compiles",error:"Does not compile"})[o.compState.value]||""),Ps=M.computed(()=>o.compTab.value?`<dm-${o.compTab.value}>`:""),Os=M.computed(()=>o.versions.value.some(e=>e.checked.value)),Rs=M.computed(()=>o.versions.value.length>0&&o.versions.value.every(e=>e.checked.value)),As=M.computed(()=>{const e=o.versions.value.filter(t=>t.checked.value).length;return e>0&&e<o.versions.value.length});k=()=>Re().length>0||ge().length>0||Ye().length>0||yt();const Gt=(e,t,a)=>({title:String(e.title||"").trim()||"Untitled",description:String(e.description||"").trim(),layout:e.layout,status:e.status,sortOrder:parseInt(String(e.sortOrder),10)||99,showInNav:!!e.showInNav,sidebar:!!e.sidebar,...e.breadcrumbs?{}:{breadcrumbs:!1},...e.bundled?{bundled:!0}:{},tags:Array.isArray(e.tags)?e.tags:[],...t?.isEdit&&JSON.stringify(e.adminTags)===t.savedAdminTags?{}:{adminTags:Array.isArray(e.adminTags)?e.adminTags:[]},category:String(e.category||"").trim()||null,visibility:e.visibility||"public",project:e.project||"",seo:{title:String(e.seoTitle||"").trim(),description:String(e.seoDesc||"").trim(),...ea(e)?{schema:ea(e)}:t?.isEdit?{schema:null}:{}},dconfig:a,...e.theme?{theme:e.theme}:{}}),ea=e=>Po(e.seoSchema).value,Xt=e=>{const t=String(e.dconfig||"").trim();if(!t)return null;try{return JSON.parse(t)}catch{return null}},$s=()=>p.urlPath.peek().trim()||m?.id||"/";let kt=[],ta=[];const wt=e=>kt.includes(e)||Kt.includes(e);let Ae=new Set;const St=()=>{const e=[...new Set([...kt,...Kt,...L.keys()])],t=$n(e.filter(s=>!L.has(s)),vt);Ae=new Set(Object.keys(t));const a=Ae.size?`Preview shows unsaved changes to ${[...Ae].join(", ")}`:"";return a!==o.heldNote.peek()&&(o.heldNote.value=a),Hn(t,[...L.entries()].map(([s,r])=>({name:s,content:r.form.content,css:r.form.css,dirty:de(r)})))};let Zt="";const Ls=()=>{oa();const e=Zt;if(e){Zt="";try{$e.contentDocument?.querySelector(`[data-block="${CSS.escape(e)}"]`)?.scrollIntoView({block:"center"})}catch{}}},$e=O("#markdown-preview");h.settings.getCustomCss().then(({css:e})=>{if(!c())return;ee.value=e||"";let t=null;try{t=S.get(ft)}catch{}typeof t=="string"&&t!==ee.peek()?(ia(),p.css.value=t,E.toast("Your unsaved custom CSS is back - the CSS button shows it.",{type:"info"})):p.cssOpened.peek()||(p.css.value=ee.peek()),J(ft)}).catch(()=>{});const oa=()=>{const e=$e?.contentDocument;if(!e?.head)return;const t=p.cssOpened.peek()?p.css.peek():"";if(!t)return;let a=e.getElementById("preview-custom-css");a||(a=e.createElement("style"),a.id="preview-custom-css",e.head.appendChild(a)),a.textContent=t};let Qt=null,eo=0;const U=(e=!1)=>{clearTimeout(Qt),Qt=setTimeout(async()=>{if(!$e||o.viewMode.peek()==="write"||!o.active.peek()||o.compTab.peek())return;const t=++eo,a=o.blockTab.peek();o.previewStatus.value="Rendering\u2026";try{let s;if(a&&(!m||!wt(a)))({html:s}=await h.pages.previewFull(Pr,{title:a,layout:"blank",breadcrumbs:!1},Un(a,_s(a)),St()));else if(m){const r=_();({html:s}=await h.pages.previewFull($s(),Gt(r,m,Xt(r)),r.body,St()))}else{$e.srcdoc="";return}if(!c()||t!==eo)return;Rr($e,qn(Or(s),a),Ls),o.previewStatus.value="Showing unsaved changes"}catch(s){if(!c()||t!==eo)return;o.previewStatus.value="Preview failed - "+(s?.message||"unknown error"),$e.srcdoc='<!doctype html><meta charset="utf-8"><body style="font:14px system-ui;padding:1rem;color:#b91c1c;">Preview failed: '+String(s?.message||"unknown error").replace(/[<&]/g,r=>r==="<"?"&lt;":"&amp;")+"</body>"}},e?0:500)};i(()=>clearTimeout(Qt));const to=sn(d.find("#markdown-editor"),d.find("#editor-toolbar"),{spacerDefault:Y?.layoutOptions?.spacerSize??40,beforeFormat:()=>Jt()});ln(V,{blocks:()=>bt,openBlock:e=>Be(e)});const Ge=y.querySelector(".editor-toolbar-right");Ge.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}')`)}),O("#fullscreen-btn")?.setAttribute("data-on-click","toggleFullscreen");const Ns=mt(`
128
128
  <span class="pe-toolbar-extras" style="display:contents">
129
129
  <button type="button" class="editor-view-btn" data-tip="Edit Custom CSS" data-on-click="toggleCss"
130
130
  data-bind-class="cssMode.value && 'active'"><span>CSS</span></button>
@@ -136,8 +136,8 @@ The quick brown fox - 0O 1lI {} [] () =&gt; ==
136
136
  <span class="pe-fold-icon" hidden data-bind-hidden="!folded.value"><span data-icon="chevrons-right" data-icon-size="10"></span></span>
137
137
  </button>
138
138
  <span class="editor-toolbar-sep"></span>
139
- </span>`);Ge.prepend(Ls),Ge.before(O(".pe-block-bar")),Ge.before(O(".pe-comp-bar"));const aa=e=>(Array.isArray(e)?e:[]).map(t=>({value:t,label:t})),sa=O("#field-tags");let St=null;St=sa?E.pillbox(sa,{data:aa(Vt),value:[],creatable:!0,searchable:!0,placeholder:"Add tag\u2026",onChange:()=>{St&&(u.tags.value=[...St.getValue()])}}):null;const na=O("#field-admin-tags");let Et=null;Et=na?E.pillbox(na,{data:aa(T),value:[],creatable:!0,searchable:!0,placeholder:"Add admin tag\u2026",onChange:()=>{Et&&(u.adminTags.value=[...Et.getValue()])}}):null;const ra=()=>{a.bodyRev.value=a.bodyRev.peek()+1},Le=()=>{a.blockRev.value=a.blockRev.peek()+1},ke=()=>{a.compRev.value=a.compRev.peek()+1},Xe=()=>{a.docRev.value=a.docRev.peek()+1},ia=()=>{u.cssOpened.peek()||(u.css.peek()||(u.css.value=ee.peek()),u.cssOpened.value=!0,on(ve,{language:"css"}))},Ze=e=>{for(const t of Tr)u[t].value=e[t]==null?"":String(e[t]);for(const t of Mr)u[t].value=!!e[t];u.tags.value=Array.isArray(e.tags)?e.tags:[],St?.setValue(u.tags.peek()),Array.isArray(e.adminTags)&&(u.adminTags.value=e.adminTags),Et?.setValue(u.adminTags.peek()),qo(O("#field-visibility"),u.visibility.peek()),Q.unfoldAll(),a.folded.value=!1,gt=!0,V.value=e.body==null?"":String(e.body),gt=!1,Q.refresh(),Ko(),ra()},la=(e,t)=>({urlPath:t||"",title:e?.title||"",description:e?.description||"",layout:Ho(e?.layout||"default"),status:e?.status||"draft",sortOrder:String(e?.sortOrder??99),showInNav:!!e?.showInNav,sidebar:!!e?.sidebar,breadcrumbs:e?e.breadcrumbs!==!1:!0,bundled:!!e?.bundled,tags:Array.isArray(e?.tags)?e.tags:[],adminTags:Array.isArray(e?.adminTags)?e.adminTags:[],category:e?.category||"",visibility:typeof e?.visibility=="string"&&e.visibility?e.visibility:"public",project:Cn({isEdit:!!t,page:e,projects:se,fromHash:t?"":Ft()||"",urlPath:t||""}),theme:e?.theme||"",seoTitle:e?.seo?.title||"",seoDesc:e?.seo?.description||"",seoSchema:fn(e?.seo?.schema),dconfig:e?.dconfig?JSON.stringify(e.dconfig,null,2):"",body:e?.content||"",css:null}),ca=()=>{m&&(m.state=_(),m.at=Date.now())},da=e=>{m!==e&&(ca(),m=e,Ze(e.state),a.base.value=e.base,a.curId.value=e.id,e.at=Date.now(),Mt(),Xe())},Ns=()=>{ca(),m=null;const e=ms();Ze(e),a.base.value=W(e),a.curId.value=null,Mt(),Xe()};Ze(ms()),a.base.value=W(_());const J=e=>{try{S.remove?S.remove(e):S.set(e,null)}catch{}},pa=(e,t)=>({name:e.name,...e.form,base:e.base,at:t});p=()=>{try{for(const t of Ae())S.set(ze(t.id),Ka(t===m?Go():t.state,t.base));ht()&&S.set(ft,u.css.peek());const e=new Date().toISOString();for(const t of ge()){const o=L.get(t);S.set(He(t),{form:{...o.form},base:o.base,at:e})}for(const t of Ye())S.set(Ve(t),pa(N.get(t),e))}catch{}};const ua=e=>{y()&&(p(),e.preventDefault(),e.returnValue="")};window.addEventListener("beforeunload",ua),i(()=>window.removeEventListener("beforeunload",ua));let Qe=!1,Tt=null;const Mt=()=>{Qe=!1,Tt=null,a.versions.value=[],a.compare.value=null,a.histError.value="",a.dockOn.peek()&&a.dockTab.peek()==="history"&&(m?.isEdit?pe():a.dockTab.value="details")},pe=async()=>{const e=m;if(e?.isEdit){Qe=!0,a.histLoading.value=!0,a.histError.value="";try{const t=(await h.versions.list(e.id)).versions||[];if(!c()||m!==e)return;a.versions.value=t.map(o=>({...o,when:qe(o.createdAt),author:o.author||"",label:o.label||"",who:[o.author,o.label].filter(Boolean).join(" - "),checked:M.observable(!1)}))}catch(t){m===e&&(a.histError.value="Failed to load versions: "+t.message)}finally{m===e&&(a.histLoading.value=!1)}}},oo=e=>a.versions.peek().find(t=>t.filename===e),ao=async e=>{const t=m;try{const o=await h.versions.get(t.id,e.filename);if(!c()||m!==t)return;Tt=e.filename,a.compare.value={label:rs(e),old:o.content,current:Ut()}}catch(o){E.toast("Failed to load version: "+o.message,{type:"error"})}},Ds=async()=>{const e=m;if(!e?.isEdit)return;const t=await h.pages.get(e.id).catch(()=>null);if(!c()||m!==e||!t)return;e.page=t;const o=la(t,e.id);e.base=W(o),e.savedAdminTags=JSON.stringify(o.adminTags),Ze(o),a.base.value=e.base,Mt(),a.dockOn.peek()&&a.dockTab.peek()==="history"&&pe(),U()},ma=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 h.versions.restore(m.id,e),E.toast("Page restored.",{type:"success"}),await Ds()}catch(t){E.toast("Restore failed: "+t.message,{type:"error"})}},js=async e=>{if(await E.confirm("Delete this version? This cannot be undone."))try{await h.versions.delete(m.id,e.filename),E.toast("Version deleted.",{type:"success"}),await pe()}catch(t){E.toast("Failed to delete: "+t.message,{type:"error"})}},Ne=new Map,Bs=e=>{if(!Ne.has(e)){const t=I(e);Ne.set(e,{id:e,kind:t.kind,kindText:t.kind==="page"?"Page":t.kind==="component"?"Component":"Block",label:M.observable(""),title:M.observable(""),active:M.observable(!1),dirty:M.observable(!1)})}return Ne.get(e)},fa=e=>{const t=e===m?u.title.peek():e?.loaded?e.state.title:D.find(o=>o.urlPath===e?.id)?.title;return String(t||"").trim()||e?.id||"New page"};let ba=!0,va="";const Is=()=>{if(ba)return;const e={ids:P,active:a.active.peek()},t=JSON.stringify(e);if(t!==va){va=t;try{S.set(ps,e)}catch{}}},q=()=>{const e=P.map(Bs);for(const t of e){const o=I(t.id);let s,r;if(o.kind==="page"){const l=K.get(o.id);s=fa(l),r=l?.loaded?Yt(l):xe(o),t.title.value=o.id?`${s} (${o.id})`:"New page"}else if(o.kind==="component"){const l=N.get(o.id);s=o.id,r=l?he(l):xe(o),t.title.value=`Component <dm-${o.id}>`}else{const l=L.get(o.id);s=o.id,r=l?de(l):Re.has(o.id)||xe(o),t.title.value=`Block ${o.id}`}t.label.peek()!==s&&(t.label.value=s),t.dirty.peek()!==r&&(t.dirty.value=r);const n=t.id===a.active.peek();t.active.peek()!==n&&(t.active.value=n)}e.map(t=>t.id).join("|")!==a.tabs.peek().map(t=>t.id).join("|")&&(a.tabs.value=e),Is()};let ye=new Set;try{const e=S.get(us);Array.isArray(e)&&(ye=new Set(e.filter(t=>typeof t=="string")))}catch{}const ga=new Map,so=e=>{let t=ga.get(e.key);return t?(t.label.peek()!==e.label&&(t.label.value=e.label),t.meta.peek()!==(e.meta||"")&&(t.meta.value=e.meta||""),t.status.peek()!==(e.status||"")&&(t.status.value=e.status||""),t.folder.peek()!==!!e.folder&&(t.folder.value=!!e.folder)):(t={...e,label:M.observable(e.label),meta:M.observable(e.meta||""),status:M.observable(e.status||""),folder:M.observable(!!e.folder),active:M.observable(!1),dirty:M.observable(!1),folded:M.observable(!1),title:""},ga.set(e.key,t)),t.title=e.kind==="block"||e.kind==="component"?e.meta?`${e.id} - ${e.meta}`:e.id:e.kind==="folder"?e.meta:`${e.label} (${e.meta})`,t},no=new Map,z=()=>{const e=a.filter.peek(),t=I(a.active.peek()),o=t?.kind==="page"?t.id:null,s=t?.kind==="block"?t.id:null,r=t?.kind==="component"?t.id:null,n=new Set(Ae().map(f=>f.id)),l=Gn(D,{filter:e,folded:ye}).map(so);for(const f of l){const C=f.kind==="page"&&f.id===o,B=f.kind==="page"&&(n.has(f.id)||!K.get(f.id)?.loaded&&xe({kind:"page",id:f.id})),fe=ye.has(f.id);f.active.peek()!==C&&(f.active.value=C),f.dirty.peek()!==B&&(f.dirty.value=B),f.folded.peek()!==fe&&(f.folded.value=fe)}const g=Vn(ie,e).map(so),$=f=>{const C=L.get(f);return C?de(C):Re.has(f)||xe({kind:"block",id:f})};for(const f of g){const C=f.id===s,B=$(f.id);f.active.peek()!==C&&(f.active.value=C),f.dirty.peek()!==B&&(f.dirty.value=B)}const G=Kn(Je,e).map(so),Me=f=>{const C=N.get(f);return C?he(C):xe({kind:"component",id:f})};for(const f of G){const C=f.id===r,B=Me(f.id);f.active.peek()!==C&&(f.active.value=C),f.dirty.peek()!==B&&(f.dirty.value=B)}const Co=m?Dn(kt,_t,be):[],za=(f,C,B)=>(no.has(f)||no.set(f,{key:f,id:C,label:B,kindText:"",title:"",active:M.observable(!1),dirty:M.observable(!1)}),no.get(f)),xo=Co.map(f=>{const C=za(`block:${f.name}`,f.name,f.name);C.kindText=f.footer?"Footer":"Block",C.title=`${f.name} - ${f.footer?"in the footer, on every page":"a block on this page"}`;const B=f.name===s,fe=$(f.name);return C.active.peek()!==B&&(C.active.value=B),C.dirty.peek()!==fe&&(C.dirty.value=fe),C});for(const f of ta){const C=za(`component:${f}`,f,f);C.kindText="Component",C.title=`<dm-${f}> - a component on this page`;const B=f===r,fe=Me(f);C.active.peek()!==B&&(C.active.value=B),C.dirty.peek()!==fe&&(C.dirty.value=fe),xo.push(C)}const Dt=(f,C)=>f.map(B=>B.key).join("|")===C.map(B=>B.key).join("|");Dt(l,a.pageRows.peek())||(a.pageRows.value=l),Dt(g,a.blockRows.peek())||(a.blockRows.value=g),Dt(G,a.compRows.peek())||(a.compRows.value=G),Dt(xo,a.thisPage.peek())||(a.thisPage.value=xo)},ha=async()=>{const e=await h.pages.list().catch(()=>null);!c()||!Array.isArray(e)||(D=e,z(),q())},te=()=>{const e=I(a.active.peek()),t=e?es(e):"/pages/new",o=window.location.hash.replace(/^#/,"");j.address=o.split("?")[0]===t?o:t,o.split("?")[0]!==t?history.replaceState({pe:1},"","#"+t):history.state?.pe||history.replaceState({pe:1},"",window.location.hash)},Fs=async e=>{if(e.loading)return e.loading;e.loading=(async()=>{let t=null;if(e.isEdit){if(t=await h.pages.get(e.id).catch(()=>null),!c())return!1;if(!t)return E.toast(`Page ${e.id} not found.`,{type:"error"}),!1}e.page=t;const o=la(t,e.id);e.state=o,e.base=W(o),e.savedAdminTags=JSON.stringify(o.adminTags),e.loaded=!0;let s=null;try{s=S.get(ze(e.id))}catch{}const r=xn(s),n=$o({kind:"page",id:e.id});if(r){J(ze(e.id));const l=W(r.state)!==e.base,g=Mn(r,e.base),$={...o,...r.state,adminTags:o.adminTags};if(l&&n&&!g)e.state=$,E.toast(`Your unsaved changes to ${e.id||"the new page"} are back.`,{type:"info"});else if(l){const G=r.at?` (${qe(r.at)})`:"",Me=g?" 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 ${e.id||"a new page"}${G}. Restore them?${Me}`)&&c()&&(e.state=$)}}return!0})();try{return await e.loading}finally{e.loading=null}},ka=e=>(K.has(e)||K.set(e,{kind:"page",id:e,isEdit:!!e,loaded:!1,page:null,state:null,base:"",savedAdminTags:"[]",at:0}),K.get(e)),ue=async e=>{const t=X({kind:"page",id:e});({ids:P}=Bo(P,t)),a.active.value=t,a.blockTab.value="",vo();const o=ka(e);if(q(),!o.loaded){a.previewStatus.value=`Opening ${e||"a new page"}\u2026`;const s=await Fs(o);if(!c()||!P.includes(t)||K.get(e)!==o)return;if(!s){ya(t);return}if(a.active.peek()!==t){q(),z();return}}da(o),te(),q(),z(),U(),Q.refresh(),V.focus()};w=async(e,t)=>{if(j.address=t,e.kind==="page"){ue(e.id);return}if(!e.id){(e.kind==="block"?Lt:nt)({project:Ft(t)||""});return}const o=e.kind==="block"?be:le;if(o.has(e.id)||await(e.kind==="block"?Vo:_o)(),!!c()){if(!o.has(e.id)){E.toast(`There is no ${e.kind} called "${e.id}".`,{type:"warning"}),te(),z();return}e.kind==="block"?Be(e.id):st(e.id)}};const ya=e=>{const t=a.active.peek(),o=_n(P,e,t);P=o.ids,Ne.delete(e);const s=I(e),r=o.active!==t?I(o.active):null;if(s.kind==="page"){if(K.delete(s.id),m?.id===s.id){const n=[...K.values()].filter(l=>l.loaded&&l.id!==s.id).sort((l,g)=>g.at-l.at)[0];n?da(n):Ns()}}else s.kind==="component"?(N.delete(s.id),a.compTab.peek()===s.id&&vo()):(L.delete(s.id),a.blockTab.peek()===s.id&&(a.blockTab.value="",a.blockReady.value=!1));if(a.active.value=o.active,r?.kind==="page"){ue(r.id);return}if(r?.kind==="block"){Be(r.id);return}if(r?.kind==="component"){st(r.id);return}te(),Xe(),Le(),ke(),q(),z(),U()},et=e=>{const t=I(e);if(!t||!P.includes(e))return;let o="";try{if(t.kind==="page"){const s=K.get(t.id);s&&Yt(s)&&(S.set(ze(s.id),Ka(s===m?_():s.state,s.base)),Ro({kind:"page",id:s.id}),o=fa(s))}else if(t.kind==="component"){const s=N.get(t.id);s&&he(s)&&(S.set(Ve(t.id),pa(s,new Date().toISOString())),Ro({kind:"component",id:t.id}),o=t.id)}else{const s=L.get(t.id);s&&de(s)&&(S.set(He(t.id),{form:{...s.form},base:s.base,at:new Date().toISOString()}),Ro({kind:"block",id:t.id}),o=t.id)}}catch{}ya(e),o&&E.toast(`Changes to "${o}" kept as a draft - back when you open it again.`,{type:"info"})},Ct=e=>{const t=I(e);t&&(t.kind==="page"?ue(t.id):t.kind==="component"?st(t.id):Be(t.id))},wa=new Set,zs=async e=>{const t=[];for(const o of e){const s=L.get(o);if(!s)continue;const r={...s.form};try{const n=Za(r,s.block?.meta);await h.blocks.put(o,n),s.block={...s.block,meta:n.meta},s.saved=r,s.base=Do(r),vt.set(o,new Date().toISOString()),c()&&J(He(o)),t.push(o)}catch(n){E.toast(`Block "${o}" not saved: ${n.message||"Unknown error"}`,{type:"error"})}}return t.forEach(o=>wa.add(o)),t.length&&(Le(),pt("#/blocks")),t},qs=async e=>{const t=e===m?_():e.state,o=Po(t.seoSchema).error;if(o)return E.toast(`${e.id||"The new page"} not saved - structured data: ${o}`,{type:"error"}),e===m&&(a.seoSchemaNote.value=o,a.dockOn.value=!0,a.dockTab.value="seo"),!1;const s=Gt(t,e,Xt(t)),r=e.id;try{if(e.isEdit){const n={frontmatter:s,body:t.body};t.urlPath!==e.id&&(n.newUrlPath=t.urlPath),await h.pages.update(e.id,n)}else await h.pages.create({urlPath:t.urlPath,frontmatter:s,body:t.body})}catch(n){return E.toast(`${e.id||"The new page"} not saved: ${n.message||"Unknown error"}`,{type:"error"}),!1}if(!c())return!0;if(e.savedAdminTags=JSON.stringify(t.adminTags),e.base=W(t),e===m?a.base.value=e.base:e.state=t,J(ze(r)),!e.isEdit||t.urlPath!==e.id){K.delete(r),e.id=t.urlPath,e.isEdit=!0,K.set(e.id,e);const n=X({kind:"page",id:r}),l=X({kind:"page",id:e.id});Ne.delete(n),{ids:P}=Qn(P,n,l,a.active.peek()),a.active.peek()===n&&(a.active.value=l),e===m&&(a.curId.value=e.id,te())}return!0},Hs=async e=>{const t=[];for(const o of e){const s=N.get(o);if(!s||s.readOnly)continue;if(Rt===s?(clearTimeout(At),Rt=null,ke(),at(s)):s.state||at(s),s.compiling&&await s.compiling,!c())return t;if(s.state!=="ok"){E.toast(`Component "${o}" not saved: ${s.state==="error"?"it does not compile - fix the errors first.":"it has not compiled yet - try again in a moment."}`,{type:"warning"});continue}const r={...s.form},n={...s.meta||{}};delete n.bundled,r.project?n.project=r.project:delete n.project;try{await h.components.put(o,{source:r.source,bundled:r.bundled,meta:n}),s.meta=n,s.saved=r,s.base=Fo({name:o,...r});const l=Je.find(g=>g.name===o);l&&(l.bundled=r.bundled,l.meta=n),c()&&J(Ve(o)),t.push(o)}catch(l){E.toast(`Component "${o}" not saved: ${l.message||"Unknown error"}`,{type:"error"})}}return t.length&&(ke(),pt("#/components")),t};let ro=!1;const io=async(e=!1)=>{if(a.saving.peek()||ro)return;ro=!0;let t,o,s=[];try{if(await Ea(),!c())return;const n=I(a.active.peek());if(lr().formatOnSave&&vs(n),e)t=Ae(),o=ge(),s=Ye();else if(n?.kind==="block")t=[],o=L.has(n.id)&&de(L.get(n.id))?[n.id]:[];else if(n?.kind==="component")t=[],o=[],s=N.has(n.id)&&he(N.get(n.id))?[n.id]:[];else if(n?.kind==="page"&&m)o=ge().filter(yt),t=!m.isEdit||Wt()||!o.length?[m]:[];else return;if(!t.length&&!o.length&&!s.length){E.toast("Nothing to save.",{type:"info"});return}for(const g of t){const $=Ao(g===m?_():g.state);if($.length){E.toast(`${g.id||"New page"}: ${$[0].text}`,{type:"warning"}),g!==m&&await ue(g.id),a.dockOn.value=!0,a.dockTab.value=$[0].field==="dconfig"?"dconfig":"details",Ke("dock",!0);return}}const l=Fn(o,Object.fromEntries(o.map(g=>[g,Qa(Ue.get(g),m?.id||"")])),wa);if(l&&(!await E.confirm(l)||!c()))return}finally{ro=!1}const r=t.length>0&&ht();a.saving.value=!0;try{let n=0;for(const $ of t)await qs($)&&n++;if(!c())return;if(r){const $=u.css.peek();await h.settings.saveCustomCss($),ee.value=$,J(ft)}const l=await zs(o);if(!c())return;const g=await Hs(s);if((n||l.length||g.length)&&E.toast(zn({pages:n,css:r,blocks:l,components:g}),{type:"success"}),Xe(),!c())return;q(),z(),n&&(pt("#/pages"),Mt(),ha())}catch(n){E.toast(`Save failed: ${n.message||"Unknown error"}`,{type:"error"})}finally{a.saving.value=!1}};let oe=null,me=null;const De=new Map,je=new Map,Sa=()=>{const e=L.get(a.blockTab.peek());!e||!oe||(a.blockReady.value=!1,oe.setValue(e.form.content),me.setValue(e.form.css),a.blockProject.value=e.form.project,qo(O("#block-project"),e.form.project),a.blockBundled.value=e.form.bundled,a.blockWhere.value=Rn({usage:Ue.get(e.form.name)})||"Where it is used could not be read.",a.blockNote.value="",a.blockReady.value=!0,uo())},Vs=e=>{const t=L.get(e);if(!t)return{};const o=t.form.content;return Object.fromEntries(ts(Ga(o),No(o),t.samples||{}).map(s=>[s.name,s.value]))};i(M.effect(()=>{const e=a.blockProject.value,t=a.blockBundled.value,o=L.get(a.blockTab.peek());!o||!a.blockReady.peek()||o.form.project===e&&o.form.bundled===t||(o.form.project=e,o.form.bundled=t,Le())}));const lo=async(e,{quiet:t=!1}={})=>{for(;De.has(e);)if(await De.get(e),L.has(e)||t)return L.get(e)||null;if(L.has(e))return L.get(e);const o=(async()=>{try{const s=await h.blocks.get(e);if(!c()||!t&&!P.includes(X({kind:"block",id:e})))return null;const r=Xa({...s,name:e}),n={block:s,saved:r,base:Do(r),form:{...r},samples:{}};let l=null;try{l=S.get(He(e))}catch{}const g=Ln(l,n.base);if(t&&g?.stale)return null;if($o({kind:"block",id:e}),g){const $=g.at?` (${qe(g.at)})`:"",G=!g.stale||await E.confirm(`You left unsaved changes to "${e}"${$}, but the block has been saved since. Restore your version anyway?`);if(!c())return null;G&&(n.form={...n.form,...g.form,name:e},g.stale||E.toast(`Your unsaved changes to "${e}" are back.`,{type:"info"}))}return l&&J(He(e)),L.set(e,n),Le(),n}catch(s){return c()&&a.blockTab.peek()===e&&(a.blockNote.value=`Could not open "${e}": ${s.message||"unknown error"}`),null}finally{De.delete(e)}})();return De.set(e,o),o},Ea=async()=>{for(;De.size||je.size;)await Promise.all([...De.values(),...je.values()])},Be=async e=>{if(!e||!be.has(e))return;const t=X({kind:"block",id:e});({ids:P}=Bo(P,t)),a.active.value=t,vo(),a.cssMode.peek()&&(a.cssMode.value=!1),a.viewMode.peek()==="preview"&&(a.viewMode.value="split"),a.blockTab.peek()!==e&&(a.blockReady.value=!1),a.blockTab.value=e,a.blockUses.value=m&&yt(e)?qn(Qa(Ue.get(e),m.id||"")):jn(Ue.get(e)),te(),q(),z();let o=L.get(e);o||(a.blockReady.value=!1,a.blockNote.value=`Opening ${e}\u2026`,o=await lo(e)),!(!o||!c()||a.blockTab.peek()!==e)&&(Sa(),q(),z(),Zt=e,U(),(a.blockPart.peek()==="css"?me:oe)?.focus())};let co=null;i(()=>clearTimeout(co));const Ta=(e,t)=>{const o=L.get(a.blockTab.peek());!o||!a.blockReady.peek()||(o.form[e]=t,clearTimeout(co),co=setTimeout(()=>{Le(),e==="content"&&uo()},120),U())},we=O("#pe-block-samples"),Ma=e=>{we.replaceChildren();const t=document.createElement("p");t.className="pe-dock-none",t.textContent=e,we.appendChild(t)};let tt=[],po=null;function uo(){const e=L.get(a.blockTab.peek());if(!e){tt=[],po=null,Ma("Open a block to see its placeholders.");return}const t=ts(Ga(e.form.content),No(e.form.content),e.samples);if(!(po===e&&t.map(o=>o.name).join("|")===tt.join("|"))){if(tt=t.map(o=>o.name),po=e,!t.length){Ma("No {{placeholders}} in the template yet.");return}we.replaceChildren();for(const o of t){const s=document.createElement("div");s.className="pe-comp-prop",s.tabIndex=0,s.dataset.sample=o.name;const r=document.createElement("label");r.className="pe-comp-prop-label",r.textContent=o.name,r.title=o.raw?`{{{${o.name}}}} - raw markup`:`{{${o.name}}}`;const n=document.createElement("input");n.type="text",n.className="form-input form-input--sm pe-comp-prop-input",n.value=o.value,n.setAttribute("aria-label",`Sample value for ${o.name}`),n.addEventListener("input",()=>{e.samples[o.name]=n.value,U()});const l=document.createElement("button");l.type="button",l.className="pe-kebab",l.setAttribute("aria-label",`Actions for ${o.name}`),l.title="Actions",l.textContent="\u22EE",s.append(r,n,l),we.appendChild(s)}}}const mo=(e,t)=>No(e.form.content).has(t)?`{{{${t}}}}`:`{{${t}}}`,_s=e=>{const t=L.get(a.blockTab.peek());return!t||!tt.includes(e)?[]:[{header:mo(t,e)},{label:"Insert into the template",icon:"corner-down-right",action:()=>{const o=oe?.textarea;o&&(a.blockPart.value="html",o.focus(),o.setRangeText(mo(t,e),o.selectionStart,o.selectionEnd,"end"),o.dispatchEvent(new Event("input",{bubbles:!0})))}},{label:"Copy the placeholder",icon:"copy",action:()=>Ie(mo(t,e),"Placeholder")},{type:"divider"},{label:"Reset the sample",icon:"rotate-ccw",action:()=>{delete t.samples[e],tt=[],uo(),U()}}]};{const e=E.contextMenu(we,{cursor:"glyph",match:".pe-comp-prop",inherit:!1,density:"compact",items:t=>_s(t.dataset.sample)});i(()=>e?.destroy?.()),we.addEventListener("click",t=>{const o=t.target.closest(".pe-kebab");o&&Ce(o)}),we.addEventListener("keydown",t=>{const o=t.target.closest(".pe-comp-prop");o&&t.key==="F10"&&t.shiftKey&&(t.preventDefault(),Ce(o))})}const ae={},Se=O("#component-preview"),xt=e=>{try{Se?.contentWindow?.postMessage(e,"*")}catch{}};let fo=Se.contentDocument?.readyState==="complete"&&/component-preview/.test(Se.contentDocument?.URL||""),Pt=!1,ot=null;const Ca=()=>{fo=!0,ot&&c()&&(xt({type:"mount",payload:ot}),Pt=!0),ot=null};Se.addEventListener("load",Ca),i(()=>Se.removeEventListener("load",Ca));const Ks=e=>{if(!fo){ot=e;return}if(!Pt){Pt=!0,xt({type:"mount",payload:e});return}ot=e,fo=!1,Pt=!1,Se.src=Se.src};let Ot="";const bo=(e=!1)=>{const t=N.get(a.compTab.peek());if(!(!t||t.state!=="ok"||!t.js)){if(a.viewMode.peek()==="write"){t.previewStale=!0;return}!e&&Ot===t.name&&!t.previewStale||(t.previewStale=!1,Ot=t.name,Ks({compiledJs:t.js,tagName:`dm-${t.name}`,props:t.previewProps}))}},at=e=>{const t=++e.seq;return e.state="compiling",a.compTab.peek()===e.name&&(a.compState.value="compiling"),e.compiling=(async()=>{let o;try{o=await h.components.compile(e.name,e.form.source)}catch(s){o={errors:[{type:"request",message:s.message||"Compile request failed."}]}}if(!(t!==e.seq||!c())){if(o.errors?.length?(e.state="error",e.errors=o.errors.map(s=>`[${s.type}] ${s.message}`).join(`
140
- `),e.js=null):(e.state="ok",e.errors="",e.js=o.js),a.compTab.peek()!==e.name){e.previewStale=!0;return}a.compState.value=e.state,a.compErrors.value=e.errors,e.state==="ok"&&(yo(),bo(!0))}})().finally(()=>{e.compiling&&t===e.seq&&(e.compiling=null)}),e.compiling};let At=null,Rt=null;i(()=>clearTimeout(At));const xa=()=>{const e=N.get(a.compTab.peek());if(!e||!ae.template)return;a.compReady.value=!1;const t=ut(e.form.source);for(const o of zt)ae[o].setValue(t[o]),ae[o].textarea.readOnly=e.readOnly;a.compReadOnly.value=e.readOnly,a.compProject.value=e.form.project,qo(O("#comp-project"),e.form.project),a.compBundled.value=e.form.bundled,a.compState.value=e.state,a.compErrors.value=e.errors,a.compNote.value="",a.compReady.value=!0,yo(),e.state==="ok"?bo():e.state||at(e)},vo=()=>{a.compTab.peek()&&(a.compTab.value="",a.compReady.value=!1)},Pa={page:"details",block:"details",component:"details"};let $t="";i(M.effect(()=>{const e=Qo.value;e!==$t&&($t&&(Pa[$t]=a.dockTab.peek()),$t=e,e&&(a.dockTab.value=Pa[e]||"details",e==="page"&&a.dockTab.peek()==="history"&&a.dockOn.peek()&&m?.isEdit&&!Qe&&pe()))}));const go=async(e,{quiet:t=!1}={})=>{if(je.has(e))return je.get(e);if(N.has(e))return N.get(e);const o=(async()=>{try{const s=await h.components.get(e);if(!c()||!P.includes(X({kind:"component",id:e})))return null;const r=s.readOnly===!0||s.origin==="plugin",n={project:s.meta?.project||"",bundled:!!s.bundled,source:os(ut(s.source))},l={name:e,comp:s,saved:n,base:Fo({name:e,...n}),form:{...n},meta:s.meta||{},readOnly:r,state:"",errors:"",js:null,seq:0,compiling:null,previewProps:{},previewStale:!1};let g=null;try{g=S.get(Ve(e))}catch{}const $=nr(g,l.base);if(t&&(!$.ok||$.stale||r))return null;const G=$o({kind:"component",id:e});if(t&&!G)return null;if($.ok&&!r){const Me=g.at?` (${qe(g.at)})`:"",Co=G&&!$.stale||await E.confirm($.stale?`You left unsaved changes to the component "${e}"${Me}, but it has been saved since. Restore your version anyway?`:`You left unsaved changes to the component "${e}"${Me}. Restore them?`);if(!c())return null;Co&&(l.form={project:String(g.project??""),bundled:g.bundled===!0,source:String(g.source)},G&&!$.stale&&E.toast(`Your unsaved changes to the component "${e}" are back.`,{type:"info"}))}return g&&J(Ve(e)),N.set(e,l),ke(),l}catch(s){return c()&&a.compTab.peek()===e&&(a.compNote.value=`Could not open <dm-${e}>: ${s.message||"unknown error"}`),null}finally{je.delete(e)}})();return je.set(e,o),o},st=async e=>{if(!e||!le.has(e))return;const t=X({kind:"component",id:e});({ids:P}=Bo(P,t)),a.active.value=t,a.blockTab.value="",a.cssMode.peek()&&(a.cssMode.value=!1),a.viewMode.peek()==="preview"&&(a.viewMode.value="split"),a.compTab.value=e,te(),q(),z();let o=N.get(e);o||(a.compReady.value=!1,a.compReadOnly.value=!1,a.compState.value="",a.compNote.value=`Opening <dm-${e}>\u2026`,o=await go(e)),!(!o||!c()||a.compTab.peek()!==e)&&(xa(),q(),z(),ae[a.compPart.peek()]?.focus())},Us=(e,t)=>{const o=N.get(a.compTab.peek());if(!o||!a.compReady.peek()||o.readOnly)return;const s=ut(o.form.source);s[e]=t,o.form.source=os(s),clearTimeout(At),Rt=o,At=setTimeout(()=>{Rt=null,ke(),at(o)},300)};i(M.effect(()=>{const e=a.compProject.value,t=a.compBundled.value,o=N.get(a.compTab.peek());!o||!a.compReady.peek()||o.readOnly||o.form.project===e&&o.form.bundled===t||(o.form.project=e,o.form.bundled=t,ke())}));const Ee=O("#pe-comp-props");let ho=[];const ko=e=>{Ee.replaceChildren();const t=document.createElement("p");t.className="pe-dock-none",t.textContent=e,Ee.appendChild(t)};function yo(){const e=N.get(a.compTab.peek());if(!e){ho=[],ko("Open a component to try its props.");return}const{rows:t,error:o}=as(ut(e.form.source).props,e.previewProps);if(ho=t,o){ko("The <props> block is not valid JSON - fix it to see the props here.");return}if(!t.length){e.previewProps={},ko("No props declared. Add them in the <props> block.");return}e.previewProps=Object.fromEntries(t.map(s=>[s.name,s.value])),Ee.replaceChildren();for(const s of t){const r=document.createElement("div");r.className="pe-comp-prop",r.tabIndex=0,r.dataset.prop=s.name;const n=document.createElement("label");n.className="pe-comp-prop-label",n.textContent=s.label,n.title=`${s.name} (${s.type})`;const l=s.type==="array"||s.type==="object"?document.createElement("textarea"):document.createElement("input");s.type==="boolean"?(l.type="checkbox",l.className="form-check",l.checked=ss(s.type,s.value)):(l.tagName==="INPUT"?l.type=s.type==="number"?"number":"text":l.rows=2,l.className="form-input form-input--sm pe-comp-prop-input",l.value=ss(s.type,s.value)),l.setAttribute("aria-label",s.label);const g=()=>{e.previewProps[s.name]=ir(s.type,s.type==="boolean"?l.checked:l.value),Ot===e.name&&xt({type:"update",payload:{props:e.previewProps}})};l.addEventListener("input",g),l.addEventListener("change",g);const $=document.createElement("button");$.type="button",$.className="pe-kebab",$.setAttribute("aria-label",`Actions for ${s.label}`),$.title="Actions",$.textContent="\u22EE",r.append(n,l,$),Ee.appendChild(r)}}const Ie=async(e,t)=>{try{await navigator.clipboard.writeText(e),E.toast(`${t} copied.`,{type:"success"})}catch{E.toast(e,{type:"info",duration:8e3})}},Js=e=>{const t=N.get(a.compTab.peek()),o=ho.find(n=>n.name===e);if(!t||!o)return[];const s=sr(o.name,o.type,t.previewProps[o.name]),r=`dm-${t.name}`;return[{header:o.label},{label:"Reset to its default",icon:"rotate-ccw",action:()=>{delete t.previewProps[o.name];const n=as(ut(t.form.source).props,{}).rows.find(l=>l.name===o.name);t.previewProps[o.name]=n?n.value:null,yo(),Ot===t.name&&xt({type:"update",payload:{props:t.previewProps}})}},{label:"Copy as an attribute",icon:"copy",disabled:!s,action:()=>Ie(s,"Attribute")},{label:"Copy the tag with this value",icon:"code",action:()=>Ie(`<${r}${s?` ${s}`:""}></${r}>`,"Tag")},{label:"Copy the prop name",icon:"copy",action:()=>Ie(o.name,"Name")},{type:"divider"},{label:"Edit in <props>",icon:"edit",action:()=>{a.compPart.value="props";const n=ae.props?.textarea;if(!n)return;const l=n.value.indexOf(`"${o.name}"`);n.focus(),l>=0&&n.setSelectionRange(l,l+o.name.length+2)}}]};{const e=E.contextMenu(Ee,{cursor:"glyph",match:".pe-comp-prop",inherit:!1,density:"compact",items:t=>Js(t.dataset.prop)});i(()=>e?.destroy?.()),Ee.addEventListener("click",t=>{const o=t.target.closest(".pe-kebab");o&&Ce(o)}),Ee.addEventListener("keydown",t=>{const o=t.target.closest(".pe-comp-prop");o&&t.key==="F10"&&t.shiftKey&&(t.preventDefault(),Ce(o))})}let Fe=!1;const Oa=()=>Ft()||"",Lt=async({project:e=Oa(),seed:t="",content:o=gr,css:s=""}={})=>{if(!Fe){Fe=!0;try{const n=await ls({kind:"block",projects:se,taken:[...be],project:e,name:t,check:An,register:i,create:async(l,g)=>{await h.blocks.put(l,Za({name:l,project:g,bundled:!1,content:o,css:s}))}});if(!c())return;if(!n){te();return}if(await Vo(),!c())return;pt("#/blocks"),E.toast(`Created the block "${n}".`,{type:"success"}),Be(n)}finally{Fe=!1}}},nt=async({name:e="",source:t=ar,project:o=Oa()}={})=>{if(!Fe){Fe=!0;try{const s=await ls({kind:"component",projects:se,taken:[...le],project:o,name:e,register:i,check:(r,n)=>rr(r,{isNew:!0,taken:n}),create:async(r,n)=>{await h.components.put(r,{source:t,bundled:!1,meta:n?{project:n}:{}})}});if(!c())return;if(!s){te();return}if(await _o(),!c())return;pt("#/components"),E.toast(`Created the component "${s}".`,{type:"success"}),st(s)}finally{Fe=!1}}},Aa=k.querySelector(".dm-plugin-body")||k,Ws=M.computed(()=>{a.blockRev.value,a.compRev.value,a.docRev.value,W(_()),a.base.value;const e=I(a.active.value),t=[...Ae().map(s=>X({kind:"page",id:s.id})),...ge().map(s=>X({kind:"block",id:s})),...Ye().map(s=>X({kind:"component",id:s}))];let o=[];return e?.kind==="block"||e?.kind==="component"?o=[a.active.value]:e?.kind==="page"&&m&&(o=[a.active.value,...ge().filter(yt).map(s=>X({kind:"block",id:s}))]),er(t,o)}),Ys={...u,...a,dirty:ks,pageDirty:gs,activeDirty:ys,cssUnsaved:hs,hasPage:ws,activeKind:Xo,canView:Zo,viewHref:Ss,problem:Es,statusText:Ts,saveAll:Ws,dockKind:Qo,blockTagText:Ms,compStateText:Cs,compTagText:xs,anySelected:Ps,allSelected:Os,someSelected:As},rt=(e,t)=>Ke(e,t),wo={save:()=>io(!1),saveAllOpen:()=>io(!0),discard:async()=>{if(await Ea(),!c())return;const e=I(a.active.peek());if(e?.kind==="block"){const t=L.get(e.id);if(!t||!de(t)||!await E.confirm(`Discard the changes to "${e.id}" you have not saved?`))return;t.form={...t.saved},J(He(e.id)),Sa(),Le()}else if(e?.kind==="component"){const t=N.get(e.id);if(!t||!he(t)||!await E.confirm(`Discard the changes to the component "${e.id}" you have not saved?`))return;t.form={...t.saved},t.state="",J(Ve(e.id)),xa(),ke()}else{if(!m||e?.kind==="page"&&e.id!==m.id||!(Wt()||ht())||!await E.confirm("Discard the changes to this page you have not saved?"))return;Ze(JSON.parse(a.base.peek())),u.cssOpened.peek()&&(u.css.value=ee.peek()),J(ze(m.id)),J(ft),Xe()}q(),z(),U()},newPage:()=>ue(""),newBlock:()=>Lt(),newComponent:()=>nt(),toggleSection:e=>{const t={here:"secHere",pages:"secPages",blocks:"secBlocks",components:"secComps"}[e];t&&(a[t].value=!a[t].peek(),rt(t,a[t].peek()))},toggleExplorer:()=>{a.explorerOn.value=!a.explorerOn.peek(),rt("explorer",a.explorerOn.peek())},toggleDock:()=>{a.dockOn.value=!a.dockOn.peek(),rt("dock",a.dockOn.peek()),a.dockOn.peek()&&a.dockTab.peek()==="history"&&!Qe&&pe()},showDock:e=>{a.dockTab.value=e,e==="history"&&m?.isEdit&&!Qe&&pe()},schemaChanged:()=>{a.seoSchemaNote.value=Po(u.seoSchema.peek()).error},insertSchemaExample:async e=>{const t=e?.target,o=t?.value||"";if(t&&(t.value=""),!o||u.seoSchema.peek().trim()&&!await E.confirm("Replace the structured data with the example?"))return;const s=u.urlPath.peek().trim()||m?.id||"/";u.seoSchema.value=mn(o,{title:u.seoTitle.peek().trim()||u.title.peek().trim(),description:u.seoDesc.peek().trim()||u.description.peek().trim(),url:`${location.origin}${s}`,siteName:Y?.title||Y?.seo?.defaultTitle||""}),a.seoSchemaNote.value=""},setBlockPart:e=>{a.blockPart.value=e==="css"?"css":"html",(e==="css"?me:oe)?.focus()},formatBlock:()=>{const e=a.blockPart.peek()==="css",t=e?me:oe;!t||!a.blockReady.peek()||Uo(_e(t.textarea,e?"css":"html"))},copyShortcode:async()=>{const e=a.blockTab.peek();e&&await Ie(Nn(e),"Shortcode")},setCompPart:e=>{a.compPart.value=zt.includes(e)?e:"template",ae[a.compPart.peek()]?.focus()},copyComponent:()=>{const e=N.get(a.compTab.peek());e&&nt({name:Lo(e.name,[...le]),source:e.form.source})},setMode:e=>{a.cssMode.peek()&&(a.cssMode.value=!1),a.viewMode.value=jo(e),rt("viewMode",a.viewMode.peek()),e!=="write"&&(U(!0),bo())},toggleFullscreen:()=>{a.fullscreen.value=!a.fullscreen.peek(),rt("fullscreen",a.fullscreen.peek())},toggleCss:()=>{a.blockTab.peek()||a.compTab.peek()||(a.cssMode.peek()?(a.cssMode.value=!1,a.viewMode.value=jo(Pe().viewMode),Q.refresh()):(ia(),a.cssMode.value=!0,a.viewMode.value="split"))},formatMarkdown:()=>{Jt(),Uo(_e(V,"md"))},toggleFold:()=>{a.folded.peek()?Q.unfoldAll():Q.foldAll(),a.folded.value=!a.folded.peek(),We.paint()},setWidth:e=>{a.liveWidth.value=e},refreshPreview:()=>{if(a.compTab.peek()){const e=N.get(a.compTab.peek());e&&at(e)}else U(!0)},share:async()=>{if(!m?.isEdit){E.toast("Save the page first - a share link needs a page to point at.",{type:"warning"});return}await br(m.id)},toggleAll:e=>{const t=!!e?.target?.checked;a.versions.peek().forEach(o=>{o.checked.value=t})},deleteSelected:async()=>{const e=a.versions.peek().filter(o=>o.checked.peek()).map(o=>o.filename),t=e.length;if(!(!t||!await E.confirm(`Delete ${t} version${t>1?"s":""}? This cannot be undone.`)))try{await h.versions.bulkDelete(m.id,e),E.toast(`${t} version${t>1?"s":""} deleted.`,{type:"success"}),await pe()}catch(o){E.toast("Delete failed: "+o.message,{type:"error"})}},saveNamed:async()=>{if(!m?.isEdit)return;const e=m;await vr(e.id)&&c()&&m===e&&await pe()},closeCompare:()=>{a.compare.value=null,Tt=null},restoreCompared:()=>ma(Tt)};Ge.querySelectorAll("[data-tip]").forEach(e=>E.tooltip(e,{content:e.getAttribute("data-tip"),position:"top"}));const Gs=M.applyBindings(Ys,Aa,{methods:wo});i(()=>Gs.dispose()),oe=zo(O('.pe-block-edit[data-part="html"]'),{ariaLabel:"Block template HTML",language:"html",onChange:e=>Ta("content",e)}),me=zo(O('.pe-block-edit[data-part="css"]'),{ariaLabel:"Block CSS",language:"css",placeholder:`/* Scoped to this block - e.g.
139
+ </span>`);Ge.prepend(Ns),Ge.before(O(".pe-block-bar")),Ge.before(O(".pe-comp-bar"));const aa=e=>(Array.isArray(e)?e:[]).map(t=>({value:t,label:t})),sa=O("#field-tags");let Et=null;Et=sa?E.pillbox(sa,{data:aa(_t),value:[],creatable:!0,searchable:!0,placeholder:"Add tag\u2026",onChange:()=>{Et&&(p.tags.value=[...Et.getValue()])}}):null;const na=O("#field-admin-tags");let Mt=null;Mt=na?E.pillbox(na,{data:aa(T),value:[],creatable:!0,searchable:!0,placeholder:"Add admin tag\u2026",onChange:()=>{Mt&&(p.adminTags.value=[...Mt.getValue()])}}):null;const ra=()=>{o.bodyRev.value=o.bodyRev.peek()+1},Le=()=>{o.blockRev.value=o.blockRev.peek()+1},ye=()=>{o.compRev.value=o.compRev.peek()+1},Xe=()=>{o.docRev.value=o.docRev.peek()+1},ia=()=>{p.cssOpened.peek()||(p.css.peek()||(p.css.value=ee.peek()),p.cssOpened.value=!0,an(ve,{language:"css"}))},Ze=e=>{for(const t of Ar)p[t].value=e[t]==null?"":String(e[t]);for(const t of $r)p[t].value=!!e[t];p.tags.value=Array.isArray(e.tags)?e.tags:[],Et?.setValue(p.tags.peek()),Array.isArray(e.adminTags)&&(p.adminTags.value=e.adminTags),Mt?.setValue(p.adminTags.peek()),qo(O("#field-visibility"),p.visibility.peek()),Q.unfoldAll(),o.folded.value=!1,gt=!0,V.value=e.body==null?"":String(e.body),gt=!1,Q.refresh(),Ko(),ra()},la=(e,t)=>({urlPath:t||"",title:e?.title||"",description:e?.description||"",layout:Ho(e?.layout||"default"),status:e?.status||"draft",sortOrder:String(e?.sortOrder??99),showInNav:!!e?.showInNav,sidebar:!!e?.sidebar,breadcrumbs:e?e.breadcrumbs!==!1:!0,bundled:!!e?.bundled,tags:Array.isArray(e?.tags)?e.tags:[],adminTags:Array.isArray(e?.adminTags)?e.adminTags:[],category:e?.category||"",visibility:typeof e?.visibility=="string"&&e.visibility?e.visibility:"public",project:Rn({isEdit:!!t,page:e,projects:se,fromHash:t?"":zt()||"",urlPath:t||""}),theme:e?.theme||"",seoTitle:e?.seo?.title||"",seoDesc:e?.seo?.description||"",seoSchema:bn(e?.seo?.schema),dconfig:e?.dconfig?JSON.stringify(e.dconfig,null,2):"",body:e?.content||"",css:null}),ca=()=>{m&&(m.state=_(),m.at=Date.now())},da=e=>{m!==e&&(ca(),m=e,Ze(e.state),o.base.value=e.base,o.curId.value=e.id,e.at=Date.now(),Ct(),Xe())},Ds=()=>{ca(),m=null;const e=ms();Ze(e),o.base.value=W(e),o.curId.value=null,Ct(),Xe()};Ze(ms()),o.base.value=W(_());const J=e=>{try{S.remove?S.remove(e):S.set(e,null)}catch{}},pa=(e,t)=>({name:e.name,...e.form,base:e.base,at:t});u=()=>{try{for(const t of Re())S.set(ze(t.id),Ka(t===m?Go():t.state,t.base));yt()&&S.set(ft,p.css.peek());const e=new Date().toISOString();for(const t of ge()){const a=L.get(t);S.set(He(t),{form:{...a.form},base:a.base,at:e})}for(const t of Ye())S.set(Ve(t),pa(N.get(t),e))}catch{}};const ua=e=>{k()&&(u(),e.preventDefault(),e.returnValue="")};window.addEventListener("beforeunload",ua),i(()=>window.removeEventListener("beforeunload",ua));let Qe=!1,Tt=null;const Ct=()=>{Qe=!1,Tt=null,o.versions.value=[],o.compare.value=null,o.histError.value="",o.dockOn.peek()&&o.dockTab.peek()==="history"&&(m?.isEdit?pe():o.dockTab.value="details")},pe=async()=>{const e=m;if(e?.isEdit){Qe=!0,o.histLoading.value=!0,o.histError.value="";try{const t=(await h.versions.list(e.id)).versions||[];if(!c()||m!==e)return;o.versions.value=t.map(a=>({...a,when:qe(a.createdAt),author:a.author||"",label:a.label||"",who:[a.author,a.label].filter(Boolean).join(" - "),checked:M.observable(!1)}))}catch(t){m===e&&(o.histError.value="Failed to load versions: "+t.message)}finally{m===e&&(o.histLoading.value=!1)}}},oo=e=>o.versions.peek().find(t=>t.filename===e),ao=async e=>{const t=m;try{const a=await h.versions.get(t.id,e.filename);if(!c()||m!==t)return;Tt=e.filename,o.compare.value={label:rs(e),old:a.content,current:ht()}}catch(a){E.toast("Failed to load version: "+a.message,{type:"error"})}},js=async()=>{const e=m;if(!e?.isEdit)return;const t=await h.pages.get(e.id).catch(()=>null);if(!c()||m!==e||!t)return;e.page=t;const a=la(t,e.id);e.base=W(a),e.savedAdminTags=JSON.stringify(a.adminTags),Ze(a),o.base.value=e.base,Ct(),o.dockOn.peek()&&o.dockTab.peek()==="history"&&pe(),U()},ma=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 h.versions.restore(m.id,e),E.toast("Page restored.",{type:"success"}),await js()}catch(t){E.toast("Restore failed: "+t.message,{type:"error"})}},Bs=async e=>{if(await E.confirm("Delete this version? This cannot be undone."))try{await h.versions.delete(m.id,e.filename),E.toast("Version deleted.",{type:"success"}),await pe()}catch(t){E.toast("Failed to delete: "+t.message,{type:"error"})}},Ne=new Map,Is=e=>{if(!Ne.has(e)){const t=I(e);Ne.set(e,{id:e,kind:t.kind,kindText:t.kind==="page"?"Page":t.kind==="component"?"Component":"Block",label:M.observable(""),title:M.observable(""),active:M.observable(!1),dirty:M.observable(!1)})}return Ne.get(e)},fa=e=>{const t=e===m?p.title.peek():e?.loaded?e.state.title:D.find(a=>a.urlPath===e?.id)?.title;return String(t||"").trim()||e?.id||"New page"};let ba=!0,va="";const Fs=()=>{if(ba)return;const e={ids:P,active:o.active.peek()},t=JSON.stringify(e);if(t!==va){va=t;try{S.set(ps,e)}catch{}}},q=()=>{const e=P.map(Is);for(const t of e){const a=I(t.id);let s,r;if(a.kind==="page"){const l=K.get(a.id);s=fa(l),r=l?.loaded?Yt(l):xe(a),t.title.value=a.id?`${s} (${a.id})`:"New page"}else if(a.kind==="component"){const l=N.get(a.id);s=a.id,r=l?he(l):xe(a),t.title.value=`Component <dm-${a.id}>`}else{const l=L.get(a.id);s=a.id,r=l?de(l):Ae.has(a.id)||xe(a),t.title.value=`Block ${a.id}`}t.label.peek()!==s&&(t.label.value=s),t.dirty.peek()!==r&&(t.dirty.value=r);const n=t.id===o.active.peek();t.active.peek()!==n&&(t.active.value=n)}e.map(t=>t.id).join("|")!==o.tabs.peek().map(t=>t.id).join("|")&&(o.tabs.value=e),Fs()};let ke=new Set;try{const e=S.get(us);Array.isArray(e)&&(ke=new Set(e.filter(t=>typeof t=="string")))}catch{}const ga=new Map,so=e=>{let t=ga.get(e.key);return t?(t.label.peek()!==e.label&&(t.label.value=e.label),t.meta.peek()!==(e.meta||"")&&(t.meta.value=e.meta||""),t.status.peek()!==(e.status||"")&&(t.status.value=e.status||""),t.folder.peek()!==!!e.folder&&(t.folder.value=!!e.folder)):(t={...e,label:M.observable(e.label),meta:M.observable(e.meta||""),status:M.observable(e.status||""),folder:M.observable(!!e.folder),active:M.observable(!1),dirty:M.observable(!1),folded:M.observable(!1),title:""},ga.set(e.key,t)),t.title=e.kind==="block"||e.kind==="component"?e.meta?`${e.id} - ${e.meta}`:e.id:e.kind==="folder"?e.meta:`${e.label} (${e.meta})`,t},no=new Map,z=()=>{const e=o.filter.peek(),t=I(o.active.peek()),a=t?.kind==="page"?t.id:null,s=t?.kind==="block"?t.id:null,r=t?.kind==="component"?t.id:null,n=new Set(Re().map(f=>f.id)),l=er(D,{filter:e,folded:ke}).map(so);for(const f of l){const C=f.kind==="page"&&f.id===a,B=f.kind==="page"&&(n.has(f.id)||!K.get(f.id)?.loaded&&xe({kind:"page",id:f.id})),fe=ke.has(f.id);f.active.peek()!==C&&(f.active.value=C),f.dirty.peek()!==B&&(f.dirty.value=B),f.folded.peek()!==fe&&(f.folded.value=fe)}const g=Jn(ie,e).map(so),$=f=>{const C=L.get(f);return C?de(C):Ae.has(f)||xe({kind:"block",id:f})};for(const f of g){const C=f.id===s,B=$(f.id);f.active.peek()!==C&&(f.active.value=C),f.dirty.peek()!==B&&(f.dirty.value=B)}const G=Yn(Je,e).map(so),Te=f=>{const C=N.get(f);return C?he(C):xe({kind:"component",id:f})};for(const f of G){const C=f.id===r,B=Te(f.id);f.active.peek()!==C&&(f.active.value=C),f.dirty.peek()!==B&&(f.dirty.value=B)}const Co=m?Fn(kt,Kt,be):[],za=(f,C,B)=>(no.has(f)||no.set(f,{key:f,id:C,label:B,kindText:"",title:"",active:M.observable(!1),dirty:M.observable(!1)}),no.get(f)),xo=Co.map(f=>{const C=za(`block:${f.name}`,f.name,f.name);C.kindText=f.footer?"Footer":"Block",C.title=`${f.name} - ${f.footer?"in the footer, on every page":"a block on this page"}`;const B=f.name===s,fe=$(f.name);return C.active.peek()!==B&&(C.active.value=B),C.dirty.peek()!==fe&&(C.dirty.value=fe),C});for(const f of ta){const C=za(`component:${f}`,f,f);C.kindText="Component",C.title=`<dm-${f}> - a component on this page`;const B=f===r,fe=Te(f);C.active.peek()!==B&&(C.active.value=B),C.dirty.peek()!==fe&&(C.dirty.value=fe),xo.push(C)}const jt=(f,C)=>f.map(B=>B.key).join("|")===C.map(B=>B.key).join("|");jt(l,o.pageRows.peek())||(o.pageRows.value=l),jt(g,o.blockRows.peek())||(o.blockRows.value=g),jt(G,o.compRows.peek())||(o.compRows.value=G),jt(xo,o.thisPage.peek())||(o.thisPage.value=xo)},ha=async()=>{const e=await h.pages.list().catch(()=>null);!c()||!Array.isArray(e)||(D=e,z(),q())},te=()=>{const e=I(o.active.peek()),t=e?es(e):"/pages/new",a=window.location.hash.replace(/^#/,"");j.address=a.split("?")[0]===t?a:t,a.split("?")[0]!==t?history.replaceState({pe:1},"","#"+t):history.state?.pe||history.replaceState({pe:1},"",window.location.hash)},zs=async e=>{if(e.loading)return e.loading;e.loading=(async()=>{let t=null;if(e.isEdit){if(t=await h.pages.get(e.id).catch(()=>null),!c())return!1;if(!t)return E.toast(`Page ${e.id} not found.`,{type:"error"}),!1}e.page=t;const a=la(t,e.id);e.state=a,e.base=W(a),e.savedAdminTags=JSON.stringify(a.adminTags),e.loaded=!0;let s=null;try{s=S.get(ze(e.id))}catch{}const r=An(s),n=$o({kind:"page",id:e.id});if(r){J(ze(e.id));const l=W(r.state)!==e.base,g=On(r,e.base),$={...a,...r.state,adminTags:a.adminTags};if(l&&n&&!g)e.state=$,E.toast(`Your unsaved changes to ${e.id||"the new page"} are back.`,{type:"info"});else if(l){const G=r.at?` (${qe(r.at)})`:"",Te=g?" 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 ${e.id||"a new page"}${G}. Restore them?${Te}`)&&c()&&(e.state=$)}}return!0})();try{return await e.loading}finally{e.loading=null}},ya=e=>(K.has(e)||K.set(e,{kind:"page",id:e,isEdit:!!e,loaded:!1,page:null,state:null,base:"",savedAdminTags:"[]",at:0}),K.get(e)),ue=async e=>{const t=X({kind:"page",id:e});({ids:P}=Bo(P,t)),o.active.value=t,o.blockTab.value="",vo();const a=ya(e);if(q(),!a.loaded){o.previewStatus.value=`Opening ${e||"a new page"}\u2026`;const s=await zs(a);if(!c()||!P.includes(t)||K.get(e)!==a)return;if(!s){ka(t);return}if(o.active.peek()!==t){q(),z();return}}da(a),te(),q(),z(),U(),Q.refresh(),V.focus()};w=async(e,t)=>{if(j.address=t,e.kind==="page"){ue(e.id);return}if(!e.id){(e.kind==="block"?Nt:nt)({project:zt(t)||""});return}const a=e.kind==="block"?be:le;if(a.has(e.id)||await(e.kind==="block"?Vo:_o)(),!!c()){if(!a.has(e.id)){E.toast(`There is no ${e.kind} called "${e.id}".`,{type:"warning"}),te(),z();return}e.kind==="block"?Be(e.id):st(e.id)}};const ka=e=>{const t=o.active.peek(),a=Wn(P,e,t);P=a.ids,Ne.delete(e);const s=I(e),r=a.active!==t?I(a.active):null;if(s.kind==="page"){if(K.delete(s.id),m?.id===s.id){const n=[...K.values()].filter(l=>l.loaded&&l.id!==s.id).sort((l,g)=>g.at-l.at)[0];n?da(n):Ds()}}else s.kind==="component"?(N.delete(s.id),o.compTab.peek()===s.id&&vo()):(L.delete(s.id),o.blockTab.peek()===s.id&&(o.blockTab.value="",o.blockReady.value=!1));if(o.active.value=a.active,r?.kind==="page"){ue(r.id);return}if(r?.kind==="block"){Be(r.id);return}if(r?.kind==="component"){st(r.id);return}te(),Xe(),Le(),ye(),q(),z(),U()},et=e=>{const t=I(e);if(!t||!P.includes(e))return;let a="";try{if(t.kind==="page"){const s=K.get(t.id);s&&Yt(s)&&(S.set(ze(s.id),Ka(s===m?_():s.state,s.base)),Ao({kind:"page",id:s.id}),a=fa(s))}else if(t.kind==="component"){const s=N.get(t.id);s&&he(s)&&(S.set(Ve(t.id),pa(s,new Date().toISOString())),Ao({kind:"component",id:t.id}),a=t.id)}else{const s=L.get(t.id);s&&de(s)&&(S.set(He(t.id),{form:{...s.form},base:s.base,at:new Date().toISOString()}),Ao({kind:"block",id:t.id}),a=t.id)}}catch{}ka(e),a&&E.toast(`Changes to "${a}" kept as a draft - back when you open it again.`,{type:"info"})},xt=e=>{const t=I(e);t&&(t.kind==="page"?ue(t.id):t.kind==="component"?st(t.id):Be(t.id))},wa=new Set,qs=async e=>{const t=[];for(const a of e){const s=L.get(a);if(!s)continue;const r={...s.form};try{const n=Za(r,s.block?.meta);await h.blocks.put(a,n),s.block={...s.block,meta:n.meta},s.saved=r,s.base=Do(r),vt.set(a,new Date().toISOString()),c()&&J(He(a)),t.push(a)}catch(n){E.toast(`Block "${a}" not saved: ${n.message||"Unknown error"}`,{type:"error"})}}return t.forEach(a=>wa.add(a)),t.length&&(Le(),pt("#/blocks")),t},Hs=async e=>{const t=e===m?_():e.state,a=Po(t.seoSchema).error;if(a)return E.toast(`${e.id||"The new page"} not saved - structured data: ${a}`,{type:"error"}),e===m&&(o.seoSchemaNote.value=a,o.dockOn.value=!0,o.dockTab.value="seo"),!1;const s=Gt(t,e,Xt(t)),r=e.id;try{if(e.isEdit){const n={frontmatter:s,body:t.body};t.urlPath!==e.id&&(n.newUrlPath=t.urlPath),await h.pages.update(e.id,n)}else await h.pages.create({urlPath:t.urlPath,frontmatter:s,body:t.body})}catch(n){return E.toast(`${e.id||"The new page"} not saved: ${n.message||"Unknown error"}`,{type:"error"}),!1}if(!c())return!0;if(e.savedAdminTags=JSON.stringify(t.adminTags),e.base=W(t),e===m?o.base.value=e.base:e.state=t,J(ze(r)),!e.isEdit||t.urlPath!==e.id){K.delete(r),e.id=t.urlPath,e.isEdit=!0,K.set(e.id,e);const n=X({kind:"page",id:r}),l=X({kind:"page",id:e.id});Ne.delete(n),{ids:P}=ar(P,n,l,o.active.peek()),o.active.peek()===n&&(o.active.value=l),e===m&&(o.curId.value=e.id,te())}return!0},Vs=async e=>{const t=[];for(const a of e){const s=N.get(a);if(!s||s.readOnly)continue;if($t===s?(clearTimeout(At),$t=null,ye(),at(s)):s.state||at(s),s.compiling&&await s.compiling,!c())return t;if(s.state!=="ok"){E.toast(`Component "${a}" not saved: ${s.state==="error"?"it does not compile - fix the errors first.":"it has not compiled yet - try again in a moment."}`,{type:"warning"});continue}const r={...s.form},n={...s.meta||{}};delete n.bundled,r.project?n.project=r.project:delete n.project;try{await h.components.put(a,{source:r.source,bundled:r.bundled,meta:n}),s.meta=n,s.saved=r,s.base=Fo({name:a,...r});const l=Je.find(g=>g.name===a);l&&(l.bundled=r.bundled,l.meta=n),c()&&J(Ve(a)),t.push(a)}catch(l){E.toast(`Component "${a}" not saved: ${l.message||"Unknown error"}`,{type:"error"})}}return t.length&&(ye(),pt("#/components")),t};let ro=!1;const io=async(e=!1)=>{if(o.saving.peek()||ro)return;ro=!0;let t,a,s=[];try{if(await Ea(),!c())return;const n=I(o.active.peek());if(ur().formatOnSave&&vs(n),e)t=Re(),a=ge(),s=Ye();else if(n?.kind==="block")t=[],a=L.has(n.id)&&de(L.get(n.id))?[n.id]:[];else if(n?.kind==="component")t=[],a=[],s=N.has(n.id)&&he(N.get(n.id))?[n.id]:[];else if(n?.kind==="page"&&m)a=ge().filter(wt),t=!m.isEdit||Wt()||!a.length?[m]:[];else return;if(!t.length&&!a.length&&!s.length){E.toast("Nothing to save.",{type:"info"});return}for(const g of t){const $=Ro(g===m?_():g.state);if($.length){E.toast(`${g.id||"New page"}: ${$[0].text}`,{type:"warning"}),g!==m&&await ue(g.id),o.dockOn.value=!0,o.dockTab.value=$[0].field==="dconfig"?"dconfig":"details",Ke("dock",!0);return}}const l=Vn(a,Object.fromEntries(a.map(g=>[g,Qa(Ue.get(g),m?.id||"")])),wa);if(l&&(!await E.confirm(l)||!c()))return}finally{ro=!1}const r=t.length>0&&yt();o.saving.value=!0;try{let n=0;for(const $ of t)await Hs($)&&n++;if(!c())return;if(r){const $=p.css.peek();await h.settings.saveCustomCss($),ee.value=$,J(ft)}const l=await qs(a);if(!c())return;const g=await Vs(s);if((n||l.length||g.length)&&E.toast(_n({pages:n,css:r,blocks:l,components:g}),{type:"success"}),Xe(),!c())return;q(),z(),n&&(pt("#/pages"),Ct(),ha())}catch(n){E.toast(`Save failed: ${n.message||"Unknown error"}`,{type:"error"})}finally{o.saving.value=!1}};let oe=null,me=null;const De=new Map,je=new Map,Sa=()=>{const e=L.get(o.blockTab.peek());!e||!oe||(o.blockReady.value=!1,oe.setValue(e.form.content),me.setValue(e.form.css),o.blockProject.value=e.form.project,qo(O("#block-project"),e.form.project),o.blockBundled.value=e.form.bundled,o.blockWhere.value=Dn({usage:Ue.get(e.form.name)})||"Where it is used could not be read.",o.blockNote.value="",o.blockReady.value=!0,uo())},_s=e=>{const t=L.get(e);if(!t)return{};const a=t.form.content;return Object.fromEntries(ts(Ga(a),No(a),t.samples||{}).map(s=>[s.name,s.value]))};i(M.effect(()=>{const e=o.blockProject.value,t=o.blockBundled.value,a=L.get(o.blockTab.peek());!a||!o.blockReady.peek()||a.form.project===e&&a.form.bundled===t||(a.form.project=e,a.form.bundled=t,Le())}));const lo=async(e,{quiet:t=!1}={})=>{for(;De.has(e);)if(await De.get(e),L.has(e)||t)return L.get(e)||null;if(L.has(e))return L.get(e);const a=(async()=>{try{const s=await h.blocks.get(e);if(!c()||!t&&!P.includes(X({kind:"block",id:e})))return null;const r=Xa({...s,name:e}),n={block:s,saved:r,base:Do(r),form:{...r},samples:{}};let l=null;try{l=S.get(He(e))}catch{}const g=Bn(l,n.base);if(t&&g?.stale)return null;if($o({kind:"block",id:e}),g){const $=g.at?` (${qe(g.at)})`:"",G=!g.stale||await E.confirm(`You left unsaved changes to "${e}"${$}, but the block has been saved since. Restore your version anyway?`);if(!c())return null;G&&(n.form={...n.form,...g.form,name:e},g.stale||E.toast(`Your unsaved changes to "${e}" are back.`,{type:"info"}))}return l&&J(He(e)),L.set(e,n),Le(),n}catch(s){return c()&&o.blockTab.peek()===e&&(o.blockNote.value=`Could not open "${e}": ${s.message||"unknown error"}`),null}finally{De.delete(e)}})();return De.set(e,a),a},Ea=async()=>{for(;De.size||je.size;)await Promise.all([...De.values(),...je.values()])},Be=async e=>{if(!e||!be.has(e))return;const t=X({kind:"block",id:e});({ids:P}=Bo(P,t)),o.active.value=t,vo(),o.cssMode.peek()&&(o.cssMode.value=!1),o.viewMode.peek()==="preview"&&(o.viewMode.value="split"),o.blockTab.peek()!==e&&(o.blockReady.value=!1),o.blockTab.value=e,o.blockUses.value=m&&wt(e)?Kn(Qa(Ue.get(e),m.id||"")):zn(Ue.get(e)),te(),q(),z();let a=L.get(e);a||(o.blockReady.value=!1,o.blockNote.value=`Opening ${e}\u2026`,a=await lo(e)),!(!a||!c()||o.blockTab.peek()!==e)&&(Sa(),q(),z(),Zt=e,U(),(o.blockPart.peek()==="css"?me:oe)?.focus())};let co=null;i(()=>clearTimeout(co));const Ma=(e,t)=>{const a=L.get(o.blockTab.peek());!a||!o.blockReady.peek()||(a.form[e]=t,clearTimeout(co),co=setTimeout(()=>{Le(),e==="content"&&uo()},120),U())},we=O("#pe-block-samples"),Ta=e=>{we.replaceChildren();const t=document.createElement("p");t.className="pe-dock-none",t.textContent=e,we.appendChild(t)};let tt=[],po=null;function uo(){const e=L.get(o.blockTab.peek());if(!e){tt=[],po=null,Ta("Open a block to see its placeholders.");return}const t=ts(Ga(e.form.content),No(e.form.content),e.samples);if(!(po===e&&t.map(a=>a.name).join("|")===tt.join("|"))){if(tt=t.map(a=>a.name),po=e,!t.length){Ta("No {{placeholders}} in the template yet.");return}we.replaceChildren();for(const a of t){const s=document.createElement("div");s.className="pe-comp-prop",s.tabIndex=0,s.dataset.sample=a.name;const r=document.createElement("label");r.className="pe-comp-prop-label",r.textContent=a.name,r.title=a.raw?`{{{${a.name}}}} - raw markup`:`{{${a.name}}}`;const n=document.createElement("input");n.type="text",n.className="form-input form-input--sm pe-comp-prop-input",n.value=a.value,n.setAttribute("aria-label",`Sample value for ${a.name}`),n.addEventListener("input",()=>{e.samples[a.name]=n.value,U()});const l=document.createElement("button");l.type="button",l.className="pe-kebab",l.setAttribute("aria-label",`Actions for ${a.name}`),l.title="Actions",l.textContent="\u22EE",s.append(r,n,l),we.appendChild(s)}}}const mo=(e,t)=>No(e.form.content).has(t)?`{{{${t}}}}`:`{{${t}}}`,Ks=e=>{const t=L.get(o.blockTab.peek());return!t||!tt.includes(e)?[]:[{header:mo(t,e)},{label:"Insert into the template",icon:"corner-down-right",action:()=>{const a=oe?.textarea;a&&(o.blockPart.value="html",a.focus(),a.setRangeText(mo(t,e),a.selectionStart,a.selectionEnd,"end"),a.dispatchEvent(new Event("input",{bubbles:!0})))}},{label:"Copy the placeholder",icon:"copy",action:()=>Ie(mo(t,e),"Placeholder")},{type:"divider"},{label:"Reset the sample",icon:"rotate-ccw",action:()=>{delete t.samples[e],tt=[],uo(),U()}}]};{const e=E.contextMenu(we,{cursor:"glyph",match:".pe-comp-prop",inherit:!1,density:"compact",items:t=>Ks(t.dataset.sample)});i(()=>e?.destroy?.()),we.addEventListener("click",t=>{const a=t.target.closest(".pe-kebab");a&&Ce(a)}),we.addEventListener("keydown",t=>{const a=t.target.closest(".pe-comp-prop");a&&t.key==="F10"&&t.shiftKey&&(t.preventDefault(),Ce(a))})}const ae={},Se=O("#component-preview"),Pt=e=>{try{Se?.contentWindow?.postMessage(e,"*")}catch{}};let fo=Se.contentDocument?.readyState==="complete"&&/component-preview/.test(Se.contentDocument?.URL||""),Ot=!1,ot=null;const Ca=()=>{fo=!0,ot&&c()&&(Pt({type:"mount",payload:ot}),Ot=!0),ot=null};Se.addEventListener("load",Ca),i(()=>Se.removeEventListener("load",Ca));const Us=e=>{if(!fo){ot=e;return}if(!Ot){Ot=!0,Pt({type:"mount",payload:e});return}ot=e,fo=!1,Ot=!1,Se.src=Se.src};let Rt="";const bo=(e=!1)=>{const t=N.get(o.compTab.peek());if(!(!t||t.state!=="ok"||!t.js)){if(o.viewMode.peek()==="write"){t.previewStale=!0;return}!e&&Rt===t.name&&!t.previewStale||(t.previewStale=!1,Rt=t.name,Us({compiledJs:t.js,tagName:`dm-${t.name}`,props:t.previewProps}))}},at=e=>{const t=++e.seq;return e.state="compiling",o.compTab.peek()===e.name&&(o.compState.value="compiling"),e.compiling=(async()=>{let a;try{a=await h.components.compile(e.name,e.form.source)}catch(s){a={errors:[{type:"request",message:s.message||"Compile request failed."}]}}if(!(t!==e.seq||!c())){if(a.errors?.length?(e.state="error",e.errors=a.errors.map(s=>`[${s.type}] ${s.message}`).join(`
140
+ `),e.js=null):(e.state="ok",e.errors="",e.js=a.js),o.compTab.peek()!==e.name){e.previewStale=!0;return}o.compState.value=e.state,o.compErrors.value=e.errors,e.state==="ok"&&(ko(),bo(!0))}})().finally(()=>{e.compiling&&t===e.seq&&(e.compiling=null)}),e.compiling};let At=null,$t=null;i(()=>clearTimeout(At));const xa=()=>{const e=N.get(o.compTab.peek());if(!e||!ae.template)return;o.compReady.value=!1;const t=ut(e.form.source);for(const a of qt)ae[a].setValue(t[a]),ae[a].textarea.readOnly=e.readOnly;o.compReadOnly.value=e.readOnly,o.compProject.value=e.form.project,qo(O("#comp-project"),e.form.project),o.compBundled.value=e.form.bundled,o.compState.value=e.state,o.compErrors.value=e.errors,o.compNote.value="",o.compReady.value=!0,ko(),e.state==="ok"?bo():e.state||at(e)},vo=()=>{o.compTab.peek()&&(o.compTab.value="",o.compReady.value=!1)},Pa={page:"details",block:"details",component:"details"};let Lt="";i(M.effect(()=>{const e=Qo.value;e!==Lt&&(Lt&&(Pa[Lt]=o.dockTab.peek()),Lt=e,e&&(o.dockTab.value=Pa[e]||"details",e==="page"&&o.dockTab.peek()==="history"&&o.dockOn.peek()&&m?.isEdit&&!Qe&&pe()))}));const go=async(e,{quiet:t=!1}={})=>{if(je.has(e))return je.get(e);if(N.has(e))return N.get(e);const a=(async()=>{try{const s=await h.components.get(e);if(!c()||!P.includes(X({kind:"component",id:e})))return null;const r=s.readOnly===!0||s.origin==="plugin",n={project:s.meta?.project||"",bundled:!!s.bundled,source:os(ut(s.source))},l={name:e,comp:s,saved:n,base:Fo({name:e,...n}),form:{...n},meta:s.meta||{},readOnly:r,state:"",errors:"",js:null,seq:0,compiling:null,previewProps:{},previewStale:!1};let g=null;try{g=S.get(Ve(e))}catch{}const $=cr(g,l.base);if(t&&(!$.ok||$.stale||r))return null;const G=$o({kind:"component",id:e});if(t&&!G)return null;if($.ok&&!r){const Te=g.at?` (${qe(g.at)})`:"",Co=G&&!$.stale||await E.confirm($.stale?`You left unsaved changes to the component "${e}"${Te}, but it has been saved since. Restore your version anyway?`:`You left unsaved changes to the component "${e}"${Te}. Restore them?`);if(!c())return null;Co&&(l.form={project:String(g.project??""),bundled:g.bundled===!0,source:String(g.source)},G&&!$.stale&&E.toast(`Your unsaved changes to the component "${e}" are back.`,{type:"info"}))}return g&&J(Ve(e)),N.set(e,l),ye(),l}catch(s){return c()&&o.compTab.peek()===e&&(o.compNote.value=`Could not open <dm-${e}>: ${s.message||"unknown error"}`),null}finally{je.delete(e)}})();return je.set(e,a),a},st=async e=>{if(!e||!le.has(e))return;const t=X({kind:"component",id:e});({ids:P}=Bo(P,t)),o.active.value=t,o.blockTab.value="",o.cssMode.peek()&&(o.cssMode.value=!1),o.viewMode.peek()==="preview"&&(o.viewMode.value="split"),o.compTab.value=e,te(),q(),z();let a=N.get(e);a||(o.compReady.value=!1,o.compReadOnly.value=!1,o.compState.value="",o.compNote.value=`Opening <dm-${e}>\u2026`,a=await go(e)),!(!a||!c()||o.compTab.peek()!==e)&&(xa(),q(),z(),ae[o.compPart.peek()]?.focus())},Js=(e,t)=>{const a=N.get(o.compTab.peek());if(!a||!o.compReady.peek()||a.readOnly)return;const s=ut(a.form.source);s[e]=t,a.form.source=os(s),clearTimeout(At),$t=a,At=setTimeout(()=>{$t=null,ye(),at(a)},300)};i(M.effect(()=>{const e=o.compProject.value,t=o.compBundled.value,a=N.get(o.compTab.peek());!a||!o.compReady.peek()||a.readOnly||a.form.project===e&&a.form.bundled===t||(a.form.project=e,a.form.bundled=t,ye())}));const Ee=O("#pe-comp-props");let ho=[];const yo=e=>{Ee.replaceChildren();const t=document.createElement("p");t.className="pe-dock-none",t.textContent=e,Ee.appendChild(t)};function ko(){const e=N.get(o.compTab.peek());if(!e){ho=[],yo("Open a component to try its props.");return}const{rows:t,error:a}=as(ut(e.form.source).props,e.previewProps);if(ho=t,a){yo("The <props> block is not valid JSON - fix it to see the props here.");return}if(!t.length){e.previewProps={},yo("No props declared. Add them in the <props> block.");return}e.previewProps=Object.fromEntries(t.map(s=>[s.name,s.value])),Ee.replaceChildren();for(const s of t){const r=document.createElement("div");r.className="pe-comp-prop",r.tabIndex=0,r.dataset.prop=s.name;const n=document.createElement("label");n.className="pe-comp-prop-label",n.textContent=s.label,n.title=`${s.name} (${s.type})`;const l=s.type==="array"||s.type==="object"?document.createElement("textarea"):document.createElement("input");s.type==="boolean"?(l.type="checkbox",l.className="form-check",l.checked=ss(s.type,s.value)):(l.tagName==="INPUT"?l.type=s.type==="number"?"number":"text":l.rows=2,l.className="form-input form-input--sm pe-comp-prop-input",l.value=ss(s.type,s.value)),l.setAttribute("aria-label",s.label);const g=()=>{e.previewProps[s.name]=pr(s.type,s.type==="boolean"?l.checked:l.value),Rt===e.name&&Pt({type:"update",payload:{props:e.previewProps}})};l.addEventListener("input",g),l.addEventListener("change",g);const $=document.createElement("button");$.type="button",$.className="pe-kebab",$.setAttribute("aria-label",`Actions for ${s.label}`),$.title="Actions",$.textContent="\u22EE",r.append(n,l,$),Ee.appendChild(r)}}const Ie=async(e,t)=>{try{await navigator.clipboard.writeText(e),E.toast(`${t} copied.`,{type:"success"})}catch{E.toast(e,{type:"info",duration:8e3})}},Ws=e=>{const t=N.get(o.compTab.peek()),a=ho.find(n=>n.name===e);if(!t||!a)return[];const s=lr(a.name,a.type,t.previewProps[a.name]),r=`dm-${t.name}`;return[{header:a.label},{label:"Reset to its default",icon:"rotate-ccw",action:()=>{delete t.previewProps[a.name];const n=as(ut(t.form.source).props,{}).rows.find(l=>l.name===a.name);t.previewProps[a.name]=n?n.value:null,ko(),Rt===t.name&&Pt({type:"update",payload:{props:t.previewProps}})}},{label:"Copy as an attribute",icon:"copy",disabled:!s,action:()=>Ie(s,"Attribute")},{label:"Copy the tag with this value",icon:"code",action:()=>Ie(`<${r}${s?` ${s}`:""}></${r}>`,"Tag")},{label:"Copy the prop name",icon:"copy",action:()=>Ie(a.name,"Name")},{type:"divider"},{label:"Edit in <props>",icon:"edit",action:()=>{o.compPart.value="props";const n=ae.props?.textarea;if(!n)return;const l=n.value.indexOf(`"${a.name}"`);n.focus(),l>=0&&n.setSelectionRange(l,l+a.name.length+2)}}]};{const e=E.contextMenu(Ee,{cursor:"glyph",match:".pe-comp-prop",inherit:!1,density:"compact",items:t=>Ws(t.dataset.prop)});i(()=>e?.destroy?.()),Ee.addEventListener("click",t=>{const a=t.target.closest(".pe-kebab");a&&Ce(a)}),Ee.addEventListener("keydown",t=>{const a=t.target.closest(".pe-comp-prop");a&&t.key==="F10"&&t.shiftKey&&(t.preventDefault(),Ce(a))})}let Fe=!1;const Oa=()=>zt()||"",Nt=async({project:e=Oa(),seed:t="",content:a=wr,css:s=""}={})=>{if(!Fe){Fe=!0;try{const n=await ls({kind:"block",projects:se,taken:[...be],project:e,name:t,check:Nn,register:i,create:async(l,g)=>{await h.blocks.put(l,Za({name:l,project:g,bundled:!1,content:a,css:s}))}});if(!c())return;if(!n){te();return}if(await Vo(),!c())return;pt("#/blocks"),E.toast(`Created the block "${n}".`,{type:"success"}),Be(n)}finally{Fe=!1}}},nt=async({name:e="",source:t=ir,project:a=Oa()}={})=>{if(!Fe){Fe=!0;try{const s=await ls({kind:"component",projects:se,taken:[...le],project:a,name:e,register:i,check:(r,n)=>dr(r,{isNew:!0,taken:n}),create:async(r,n)=>{await h.components.put(r,{source:t,bundled:!1,meta:n?{project:n}:{}})}});if(!c())return;if(!s){te();return}if(await _o(),!c())return;pt("#/components"),E.toast(`Created the component "${s}".`,{type:"success"}),st(s)}finally{Fe=!1}}},Ra=y.querySelector(".dm-plugin-body")||y,Ys=M.computed(()=>{o.blockRev.value,o.compRev.value,o.docRev.value,W(_()),o.base.value;const e=I(o.active.value),t=[...Re().map(s=>X({kind:"page",id:s.id})),...ge().map(s=>X({kind:"block",id:s})),...Ye().map(s=>X({kind:"component",id:s}))];let a=[];return e?.kind==="block"||e?.kind==="component"?a=[o.active.value]:e?.kind==="page"&&m&&(a=[o.active.value,...ge().filter(wt).map(s=>X({kind:"block",id:s}))]),sr(t,a)}),Gs={...p,...o,dirty:ys,pageDirty:gs,activeDirty:ks,cssUnsaved:hs,hasPage:ws,activeKind:Xo,canView:Zo,viewHref:Ss,problem:Es,dconfigNoteRows:Ms,statusText:Ts,saveAll:Ys,dockKind:Qo,blockTagText:Cs,compStateText:xs,compTagText:Ps,anySelected:Os,allSelected:Rs,someSelected:As},rt=(e,t)=>Ke(e,t),wo={save:()=>io(!1),saveAllOpen:()=>io(!0),discard:async()=>{if(await Ea(),!c())return;const e=I(o.active.peek());if(e?.kind==="block"){const t=L.get(e.id);if(!t||!de(t)||!await E.confirm(`Discard the changes to "${e.id}" you have not saved?`))return;t.form={...t.saved},J(He(e.id)),Sa(),Le()}else if(e?.kind==="component"){const t=N.get(e.id);if(!t||!he(t)||!await E.confirm(`Discard the changes to the component "${e.id}" you have not saved?`))return;t.form={...t.saved},t.state="",J(Ve(e.id)),xa(),ye()}else{if(!m||e?.kind==="page"&&e.id!==m.id||!(Wt()||yt())||!await E.confirm("Discard the changes to this page you have not saved?"))return;Ze(JSON.parse(o.base.peek())),p.cssOpened.peek()&&(p.css.value=ee.peek()),J(ze(m.id)),J(ft),Xe()}q(),z(),U()},newPage:()=>ue(""),newBlock:()=>Nt(),newComponent:()=>nt(),toggleSection:e=>{const t={here:"secHere",pages:"secPages",blocks:"secBlocks",components:"secComps"}[e];t&&(o[t].value=!o[t].peek(),rt(t,o[t].peek()))},toggleExplorer:()=>{o.explorerOn.value=!o.explorerOn.peek(),rt("explorer",o.explorerOn.peek())},toggleDock:()=>{o.dockOn.value=!o.dockOn.peek(),rt("dock",o.dockOn.peek()),o.dockOn.peek()&&o.dockTab.peek()==="history"&&!Qe&&pe()},showDock:e=>{o.dockTab.value=e,e==="history"&&m?.isEdit&&!Qe&&pe()},schemaChanged:()=>{o.seoSchemaNote.value=Po(p.seoSchema.peek()).error},insertSchemaExample:async e=>{const t=e?.target,a=t?.value||"";if(t&&(t.value=""),!a||p.seoSchema.peek().trim()&&!await E.confirm("Replace the structured data with the example?"))return;const s=p.urlPath.peek().trim()||m?.id||"/";p.seoSchema.value=fn(a,{title:p.seoTitle.peek().trim()||p.title.peek().trim(),description:p.seoDesc.peek().trim()||p.description.peek().trim(),url:`${location.origin}${s}`,siteName:Y?.title||Y?.seo?.defaultTitle||""}),o.seoSchemaNote.value=""},setBlockPart:e=>{o.blockPart.value=e==="css"?"css":"html",(e==="css"?me:oe)?.focus()},formatBlock:()=>{const e=o.blockPart.peek()==="css",t=e?me:oe;!t||!o.blockReady.peek()||Uo(_e(t.textarea,e?"css":"html"))},copyShortcode:async()=>{const e=o.blockTab.peek();e&&await Ie(In(e),"Shortcode")},setCompPart:e=>{o.compPart.value=qt.includes(e)?e:"template",ae[o.compPart.peek()]?.focus()},copyComponent:()=>{const e=N.get(o.compTab.peek());e&&nt({name:Lo(e.name,[...le]),source:e.form.source})},setMode:e=>{o.cssMode.peek()&&(o.cssMode.value=!1),o.viewMode.value=jo(e),rt("viewMode",o.viewMode.peek()),e!=="write"&&(U(!0),bo())},toggleFullscreen:()=>{o.fullscreen.value=!o.fullscreen.peek(),rt("fullscreen",o.fullscreen.peek())},toggleCss:()=>{o.blockTab.peek()||o.compTab.peek()||(o.cssMode.peek()?(o.cssMode.value=!1,o.viewMode.value=jo(Pe().viewMode),Q.refresh()):(ia(),o.cssMode.value=!0,o.viewMode.value="split"))},formatMarkdown:()=>{Jt(),Uo(_e(V,"md"))},toggleFold:()=>{o.folded.peek()?Q.unfoldAll():Q.foldAll(),o.folded.value=!o.folded.peek(),We.paint()},setWidth:e=>{o.liveWidth.value=e},refreshPreview:()=>{if(o.compTab.peek()){const e=N.get(o.compTab.peek());e&&at(e)}else U(!0)},share:async()=>{if(!m?.isEdit){E.toast("Save the page first - a share link needs a page to point at.",{type:"warning"});return}await yr(m.id)},toggleAll:e=>{const t=!!e?.target?.checked;o.versions.peek().forEach(a=>{a.checked.value=t})},deleteSelected:async()=>{const e=o.versions.peek().filter(a=>a.checked.peek()).map(a=>a.filename),t=e.length;if(!(!t||!await E.confirm(`Delete ${t} version${t>1?"s":""}? This cannot be undone.`)))try{await h.versions.bulkDelete(m.id,e),E.toast(`${t} version${t>1?"s":""} deleted.`,{type:"success"}),await pe()}catch(a){E.toast("Delete failed: "+a.message,{type:"error"})}},saveNamed:async()=>{if(!m?.isEdit)return;const e=m;await kr(e.id)&&c()&&m===e&&await pe()},closeCompare:()=>{o.compare.value=null,Tt=null},restoreCompared:()=>ma(Tt)};Ge.querySelectorAll("[data-tip]").forEach(e=>E.tooltip(e,{content:e.getAttribute("data-tip"),position:"top"}));const Xs=M.applyBindings(Gs,Ra,{methods:wo});i(()=>Xs.dispose()),oe=zo(O('.pe-block-edit[data-part="html"]'),{ariaLabel:"Block template HTML",language:"html",onChange:e=>Ma("content",e)}),me=zo(O('.pe-block-edit[data-part="css"]'),{ariaLabel:"Block CSS",language:"css",placeholder:`/* Scoped to this block - e.g.
141
141
  color: var(--dm-primary);
142
- h3 { font-size: 1.25rem; } */`,onChange:e=>Ta("css",e)}),i(()=>{oe.destroy(),me.destroy()});for(const e of zt)ae[e]=zo(O(`.pe-comp-edit[data-part="${e}"]`),{ariaLabel:`Component <${e}> block`,language:{template:"html",props:"json",script:"js",style:"css"}[e],onChange:t=>Us(e,t)});i(()=>{for(const e of zt)ae[e].destroy()});const Te=O(".pe-tabs-list"),Nt=e=>e.target.closest(".pe-tab")?.dataset.id||"",Ra=e=>{const t=Nt(e);t&&(e.target.closest(".pe-tab-close")?et(t):Ct(t))},$a=e=>{e.button===1&&Nt(e)&&(e.preventDefault(),et(Nt(e)))},La=e=>{const t=Nt(e);!t||e.target.closest(".pe-tab-close")||(e.key==="Enter"||e.key===" "?(e.preventDefault(),Ct(t)):e.key==="Delete"?(e.preventDefault(),et(t)):e.key==="F10"&&e.shiftKey&&(e.preventDefault(),Ce(e.target.closest(".pe-tab"))))};Te.addEventListener("click",Ra),Te.addEventListener("auxclick",$a),Te.addEventListener("keydown",La),i(()=>{Te.removeEventListener("click",Ra),Te.removeEventListener("auxclick",$a),Te.removeEventListener("keydown",La)});const So=e=>{for(const t of e)et(t)},Xs=async e=>{const t=I(e);if(t?.id)if(t.kind==="page")a.active.peek()!==e&&await ue(t.id),c()&&m?.id===t.id&&Ba();else if(t.kind==="block"){const s=(L.get(t.id)||await lo(t.id,{quiet:!0}))?.form||Xa(await h.blocks.get(t.id).catch(()=>null));c()&&Lt({seed:Lo(t.id,[...be]),content:s.content,css:s.css})}else{const s=(N.get(t.id)||await go(t.id,{quiet:!0}))?.form.source??(await h.components.get(t.id).catch(()=>null))?.source??"";c()&&nt({name:Lo(t.id,[...le]),source:s})}},Zs=e=>{const t=I(e);if(!t||!P.includes(e))return[];const o=P.indexOf(e),s=Ne.get(e)?.label.peek()||t.id,r=n=>{P=Wn(P,e,n),q()};return[{header:s},{label:"Close",icon:"x",action:()=>et(e)},{label:"Close others",icon:"x-circle",disabled:P.length<2,action:()=>So(Io(P,e,"others"))},{label:"Close to the right",icon:"chevrons-right",disabled:o>=P.length-1,action:()=>So(Io(P,e,"right"))},{label:"Close all",icon:"layers",action:()=>So(Io(P,e,"all"))},{type:"divider"},{label:"Move left",icon:"arrow-left",disabled:o===0,action:()=>r(-1)},{label:"Move right",icon:"arrow-right",disabled:o>=P.length-1,action:()=>r(1)},{type:"divider"},{label:t.kind==="page"?"Clone page\u2026":`Duplicate ${t.kind}\u2026`,icon:"copy",disabled:!t.id,action:()=>Xs(e)},{label:"Copy link",icon:"link",disabled:!t.id,action:()=>Ie(`${location.origin}${location.pathname}#${es(t)}`,"Link")}]};{const e=E.contextMenu(Te,{cursor:"glyph",match:".pe-tab",inherit:!1,density:"compact",items:t=>Zs(t.dataset.id)});i(()=>e?.destroy?.())}const Na=O(".pe-ex-scroll"),Da=e=>{const t=e.target.closest(".pe-ex-item"),o=t?.dataset.id||"";if(!o)return;const s=o.indexOf(":"),r=o.slice(0,s),n=o.slice(s+1),l=()=>{ye.has(n)?ye.delete(n):ye.add(n);try{S.set(us,[...ye])}catch{}z()};if(r==="folder"){l();return}if(r==="page"&&e.target.closest(".pe-ex-chev")&&t.classList.contains("is-folder")){l();return}r==="page"?ue(n):r==="block"?Be(n):r==="component"&&st(n)};Na.addEventListener("click",Da),i(()=>Na.removeEventListener("click",Da));let Eo=null;i(()=>clearTimeout(Eo)),V.addEventListener("input",()=>{Q.refresh(),ce.scrollTop=V.scrollTop,!gt&&(clearTimeout(Eo),Eo=setTimeout(ra,120),U())}),V.addEventListener("scroll",()=>{ce.scrollTop=V.scrollTop}),ve.addEventListener("scroll",()=>{ce.scrollTop=ve.scrollTop}),i(M.effect(()=>{for(const e of Object.keys(u))e!=="css"&&e!=="cssOpened"&&u[e].value;a.bodyRev.value,U()})),i(M.effect(()=>{a.bodyRev.value,a.docRev.value;const e=m?Ut():"";kt=m?$n(e,bt.map(t=>t.name),bt.filter(t=>t.shortTag).map(t=>t.name)):[],ta=m?Jn(e,le):[],wt(),z()})),i(M.effect(()=>{a.blockRev.value,a.compRev.value,a.docRev.value,a.active.value,a.filter.value,u.title.value,q(),z()})),i(M.effect(()=>{ce.hidden=!!(a.blockTab.value||a.compTab.value)}));let To=null;i(()=>clearTimeout(To)),i(M.effect(()=>{const e=u.css.value;a.cssMode.value&&(Kt.paint(),Cr(ce,e,ve),clearTimeout(To),To=setTimeout(oa,400))}));{const e=O(".pe-version-list"),t=E.contextMenu(e,{cursor:"glyph",match:"tr[data-file]",inherit:!1,density:"compact",items:o=>{const s=oo(o.dataset.file);return s?[{header:rs(s)},{label:"Show beside the editor",icon:"columns",action:()=>ao(s)},{label:"Restore this version\u2026",icon:"rotate-ccw",action:()=>ma(s.filename)},{type:"divider"},{label:"Delete\u2026",icon:"trash",danger:!0,action:()=>js(s)}]:[]}});i(()=>t?.destroy?.()),e.addEventListener("click",o=>{const s=o.target.closest("tr[data-file]");if(!s||o.target.matches("input"))return;const r=o.target.closest(".pe-kebab");if(r){Ce(r);return}const n=oo(s.dataset.file);n&&ao(n)}),e.addEventListener("keydown",o=>{const s=o.target.closest("tr[data-file]");if(s){if(o.key==="F10"&&o.shiftKey)o.preventDefault(),Ce(s);else if(o.key==="Enter"&&o.target===s){const r=oo(s.dataset.file);r&&ao(r)}}})}xr(O("#editor-body"),O("#editor-divider"),i),ln({image:e=>(a.cssMode.value=!1,Pr(e)),scribe:e=>pn(e),card:e=>en.open(e,{onMediaBrowse:()=>h.media.list().catch(()=>[])}),timeline:e=>tn.open(e,{onPreview:async t=>{try{return await h.pages.preview(t)}catch{return null}},onListCollections:()=>h.collections.list().catch(()=>[]),onGetCollection:t=>h.collections.get(t).catch(()=>null)})}),to.onEffects(e=>nn.open(e)),to.onHelp(()=>Ha()),to.onTutorial(e=>un(e));const ja=e=>{if(!c())return;const t=or(e);t&&(e.preventDefault(),t==="save"?io(!1):t==="layout"?wo.setMode(Yn(a.viewMode.peek())):wo.toggleExplorer())};document.addEventListener("keydown",ja),i(()=>document.removeEventListener("keydown",ja));const it=k.querySelector(".dm-plugin-banner-name");i(M.effect(()=>{const e=a.curId.value,t=Xo.value,o=a.blockTab.value||a.compTab.value,s=t==="block"?"Blocks":t==="component"?"Components":"Pages",r=t==="block"||t==="component"?o:e===null?"Editor":Tn(!!e,u.title.value,e);if(!c()||(document.title=`${r} - Domma CMS`,!it))return;const n=it.querySelector(".dm-plugin-banner-parent"),l=it.lastChild;n&&l&&l.nodeType===3&&it.querySelector(".dm-plugin-banner-sep")?(n.textContent=s,l.textContent=r):it.textContent=`${s} \u203A ${r}`})),dt(d,{id:"page-editor-back",icon:"arrow-left",title:"Back to Pages",onClick:()=>R.navigate("/pages")}),dt(d,{id:"page-editor-help",icon:"help-circle",title:"Editor reference",onClick:()=>Ha()});const Qs=dt(d,{id:"page-editor-view",icon:"external-link",title:"View on the site",onClick:()=>{m?.isEdit&&window.open(u.urlPath.peek().trim()||m.id,"_blank","noopener")}}),Ba=()=>{if(!m?.isEdit||a.saving.peek()||!c())return;const e=m,t=_(),o=Ao({...t,urlPath:e.id});if(o.length){E.toast(o[0].text,{type:"warning"});return}const s=vn({page:e.page,frontmatter:{...Gt(t,e,Xt(t)),adminTags:t.adminTags},body:t.body,source:e.id,pages:D,onCloned:async r=>{c()&&(await ha(),c()&&ue(r))}});i(()=>s.close())},Mo=dt(d,{id:"page-editor-clone",icon:"copy",title:"Clone page",onClick:Ba});i(M.effect(()=>{const e=Zo.value;for(const t of[Qs,Mo])t&&(t.disabled=!e);Mo&&(Mo.title=e?"Clone page":"Open a saved page to clone it")})),dt(d,{id:"page-editor-settings",icon:"settings",title:"Editor settings - font, size, spacing",onClick:()=>{Yo=fr(Jo,Wo)}}),i(qa(Aa,{position:"bottom"})),Domma.icons.scan();let Ia={ids:[],active:""};try{Ia=Zn(S.get(ps))}catch{}const lt=Ua(b),ct=tr(lt,Ia,history.state?.pe===1);P=ct.ids.filter(e=>{const t=I(e);return t.kind==="page"||(t.kind==="component"?le:be).has(t.id)}),ba=!1;for(const e of P){const t=I(e);t.kind==="page"&&ka(t.id)}q(),z(),wt();for(const e of Re)lo(e,{quiet:!0}).then(()=>{c()&&(q(),z())});for(const e of P){const t=I(e);t.kind==="component"&&e!==ct.active&&xe(t)&&go(t.id,{quiet:!0}).then(()=>{c()&&(q(),z())})}const Fa=lt&&!lt.id&&lt.kind!=="page";ct.active&&P.includes(ct.active)?await Ct(ct.active):P.length?await Ct(P[0]):Fa||te(),Fa&&c()&&(await(lt.kind==="block"?Lt:nt)({project:Ft(b)||""}),c()&&te())}};function qo(d,b){!d||typeof b!="string"||!b||[...d.options].some(v=>v.value===b)||(d.append(Object.assign(document.createElement("option"),{value:b,textContent:`${b} (custom)`})),d.value=b)}function Cr(d,b,v){d.replaceChildren(...String(b).split(`
143
- `).map((i,y)=>{const p=document.createElement("span");p.className="editor-line-number-row";const w=document.createElement("span");w.className="fold-toggle fold-toggle--empty";const k=document.createElement("span");return k.className="editor-line-num",k.textContent=String(y+1),p.append(w,k),p})),d.scrollTop=v.scrollTop}function xr(d,b,v){if(!d||!b)return;const i=15,y=85,p=c=>Math.min(y,Math.max(i,c));let w=p(parseFloat(Pe().splitRatio)||50);const k=c=>{d.style.setProperty("--dm-editor-split",w+"%"),b.setAttribute("aria-valuenow",String(Math.round(w))),c&&Ke("splitRatio",w)};k(!1);const x=c=>{const A=d.getBoundingClientRect();A.width&&(w=p((c.clientX-A.left)/A.width*100)),k(!1)},j=()=>{document.removeEventListener("pointermove",x),document.removeEventListener("pointerup",j),d.classList.remove("is-resizing"),b.classList.remove("is-dragging"),k(!0)};v(j),b.addEventListener("pointerdown",c=>{window.matchMedia("(max-width: 768px)").matches||(c.preventDefault(),d.classList.add("is-resizing"),b.classList.add("is-dragging"),document.addEventListener("pointermove",x),document.addEventListener("pointerup",j))}),b.addEventListener("dblclick",()=>{w=50,k(!0)}),b.addEventListener("keydown",c=>{const A=c.shiftKey?10:2;let H=w;if(c.key==="ArrowLeft")H=w-A;else if(c.key==="ArrowRight")H=w+A;else if(c.key==="Home")H=i;else if(c.key==="End")H=y;else if(c.key==="Enter"||c.key===" ")H=50;else return;c.preventDefault(),w=p(H),k(!0)})}async function Pr(d){const b=d.selectionStart,v=d.selectionEnd,i=await bn({title:"Upload or insert an image"});if(!i||!d.isConnected)return;let y=i.split("/").pop().split("?")[0];try{y=decodeURIComponent(y)}catch{}const p=y.replace(/[\\[\]]/g,"\\$&"),w=i.replace(/\(/g,"%28").replace(/\)/g,"%29").replace(/ /g,"%20");d.setSelectionRange(b,v),sn(d,`![${p}](${w})`),d.dispatchEvent(new Event("input",{bubbles:!0}))}function Or(d,b,v){const i=Object.entries(b||{});return d?(d.replaceChildren(...i.map(([y,p])=>new Option(p?.label||y,y))),i.some(([y])=>y===v)?v:i[0]?.[0]||v):v}async function Ar(d,b){if(!d)return;let v=[];try{const x=await h.get("/collections/roles/entries?limit=100");v=Array.isArray(x)?x:x?.entries||[]}catch{}const i=v.map(x=>({name:x.data?.name,label:x.data?.label||x.data?.name,level:x.data?.level??99})).filter(x=>x.name&&x.level!==0).sort((x,j)=>j.level-x.level),y=(x,j)=>Object.assign(document.createElement("option"),{value:x,textContent:j}),p=()=>{typeof b=="string"&&b&&![...d.options].some(x=>x.value===b)&&d.append(y(b,`${b} (custom)`))};if(!i.length)return p();const w=document.createElement("optgroup");w.label="Role and above",i.forEach(x=>w.append(y(x.name,`${x.label} and above`)));const k=document.createElement("optgroup");k.label="Role only",i.forEach(x=>k.append(y(`=${x.name}`,`${x.label} only`))),d.replaceChildren(y("public","Public - everyone"),w,k,y("private","Private - super-admin only")),p()}
142
+ h3 { font-size: 1.25rem; } */`,onChange:e=>Ma("css",e)}),i(()=>{oe.destroy(),me.destroy()});for(const e of qt)ae[e]=zo(O(`.pe-comp-edit[data-part="${e}"]`),{ariaLabel:`Component <${e}> block`,language:{template:"html",props:"json",script:"js",style:"css"}[e],onChange:t=>Js(e,t)});i(()=>{for(const e of qt)ae[e].destroy()});const Me=O(".pe-tabs-list"),Dt=e=>e.target.closest(".pe-tab")?.dataset.id||"",Aa=e=>{const t=Dt(e);t&&(e.target.closest(".pe-tab-close")?et(t):xt(t))},$a=e=>{e.button===1&&Dt(e)&&(e.preventDefault(),et(Dt(e)))},La=e=>{const t=Dt(e);!t||e.target.closest(".pe-tab-close")||(e.key==="Enter"||e.key===" "?(e.preventDefault(),xt(t)):e.key==="Delete"?(e.preventDefault(),et(t)):e.key==="F10"&&e.shiftKey&&(e.preventDefault(),Ce(e.target.closest(".pe-tab"))))};Me.addEventListener("click",Aa),Me.addEventListener("auxclick",$a),Me.addEventListener("keydown",La),i(()=>{Me.removeEventListener("click",Aa),Me.removeEventListener("auxclick",$a),Me.removeEventListener("keydown",La)});const So=e=>{for(const t of e)et(t)},Zs=async e=>{const t=I(e);if(t?.id)if(t.kind==="page")o.active.peek()!==e&&await ue(t.id),c()&&m?.id===t.id&&Ba();else if(t.kind==="block"){const s=(L.get(t.id)||await lo(t.id,{quiet:!0}))?.form||Xa(await h.blocks.get(t.id).catch(()=>null));c()&&Nt({seed:Lo(t.id,[...be]),content:s.content,css:s.css})}else{const s=(N.get(t.id)||await go(t.id,{quiet:!0}))?.form.source??(await h.components.get(t.id).catch(()=>null))?.source??"";c()&&nt({name:Lo(t.id,[...le]),source:s})}},Qs=e=>{const t=I(e);if(!t||!P.includes(e))return[];const a=P.indexOf(e),s=Ne.get(e)?.label.peek()||t.id,r=n=>{P=Zn(P,e,n),q()};return[{header:s},{label:"Close",icon:"x",action:()=>et(e)},{label:"Close others",icon:"x-circle",disabled:P.length<2,action:()=>So(Io(P,e,"others"))},{label:"Close to the right",icon:"chevrons-right",disabled:a>=P.length-1,action:()=>So(Io(P,e,"right"))},{label:"Close all",icon:"layers",action:()=>So(Io(P,e,"all"))},{type:"divider"},{label:"Move left",icon:"arrow-left",disabled:a===0,action:()=>r(-1)},{label:"Move right",icon:"arrow-right",disabled:a>=P.length-1,action:()=>r(1)},{type:"divider"},{label:t.kind==="page"?"Clone page\u2026":`Duplicate ${t.kind}\u2026`,icon:"copy",disabled:!t.id,action:()=>Zs(e)},{label:"Copy link",icon:"link",disabled:!t.id,action:()=>Ie(`${location.origin}${location.pathname}#${es(t)}`,"Link")}]};{const e=E.contextMenu(Me,{cursor:"glyph",match:".pe-tab",inherit:!1,density:"compact",items:t=>Qs(t.dataset.id)});i(()=>e?.destroy?.())}const Na=O(".pe-ex-scroll"),Da=e=>{const t=e.target.closest(".pe-ex-item"),a=t?.dataset.id||"";if(!a)return;const s=a.indexOf(":"),r=a.slice(0,s),n=a.slice(s+1),l=()=>{ke.has(n)?ke.delete(n):ke.add(n);try{S.set(us,[...ke])}catch{}z()};if(r==="folder"){l();return}if(r==="page"&&e.target.closest(".pe-ex-chev")&&t.classList.contains("is-folder")){l();return}r==="page"?ue(n):r==="block"?Be(n):r==="component"&&st(n)};Na.addEventListener("click",Da),i(()=>Na.removeEventListener("click",Da));let Eo=null;i(()=>clearTimeout(Eo)),V.addEventListener("input",()=>{Q.refresh(),ce.scrollTop=V.scrollTop,!gt&&(clearTimeout(Eo),Eo=setTimeout(ra,120),U())}),V.addEventListener("scroll",()=>{ce.scrollTop=V.scrollTop}),ve.addEventListener("scroll",()=>{ce.scrollTop=ve.scrollTop}),i(M.effect(()=>{for(const e of Object.keys(p))e!=="css"&&e!=="cssOpened"&&p[e].value;o.bodyRev.value,U()})),i(M.effect(()=>{o.bodyRev.value,o.docRev.value;const e=m?ht():"";kt=m?jn(e,bt.map(t=>t.name),bt.filter(t=>t.shortTag).map(t=>t.name)):[],ta=m?Xn(e,le):[],St(),z()})),i(M.effect(()=>{o.blockRev.value,o.compRev.value,o.docRev.value,o.active.value,o.filter.value,p.title.value,q(),z()})),i(M.effect(()=>{ce.hidden=!!(o.blockTab.value||o.compTab.value)}));let Mo=null;i(()=>clearTimeout(Mo)),i(M.effect(()=>{const e=p.css.value;o.cssMode.value&&(Ut.paint(),Lr(ce,e,ve),clearTimeout(Mo),Mo=setTimeout(oa,400))}));{const e=O(".pe-version-list"),t=E.contextMenu(e,{cursor:"glyph",match:"tr[data-file]",inherit:!1,density:"compact",items:a=>{const s=oo(a.dataset.file);return s?[{header:rs(s)},{label:"Show beside the editor",icon:"columns",action:()=>ao(s)},{label:"Restore this version\u2026",icon:"rotate-ccw",action:()=>ma(s.filename)},{type:"divider"},{label:"Delete\u2026",icon:"trash",danger:!0,action:()=>Bs(s)}]:[]}});i(()=>t?.destroy?.()),e.addEventListener("click",a=>{const s=a.target.closest("tr[data-file]");if(!s||a.target.matches("input"))return;const r=a.target.closest(".pe-kebab");if(r){Ce(r);return}const n=oo(s.dataset.file);n&&ao(n)}),e.addEventListener("keydown",a=>{const s=a.target.closest("tr[data-file]");if(s){if(a.key==="F10"&&a.shiftKey)a.preventDefault(),Ce(s);else if(a.key==="Enter"&&a.target===s){const r=oo(s.dataset.file);r&&ao(r)}}})}Nr(O("#editor-body"),O("#editor-divider"),i),cn({image:e=>(o.cssMode.value=!1,Dr(e)),scribe:e=>un(e),card:e=>tn.open(e,{onMediaBrowse:()=>h.media.list().catch(()=>[])}),timeline:e=>on.open(e,{onPreview:async t=>{try{return await h.pages.preview(t)}catch{return null}},onListCollections:()=>h.collections.list().catch(()=>[]),onGetCollection:t=>h.collections.get(t).catch(()=>null)})}),to.onEffects(e=>rn.open(e)),to.onHelp(()=>Ha()),to.onTutorial(e=>mn(e));const ja=e=>{if(!c())return;const t=rr(e);t&&(e.preventDefault(),t==="save"?io(!1):t==="layout"?wo.setMode(Qn(o.viewMode.peek())):wo.toggleExplorer())};document.addEventListener("keydown",ja),i(()=>document.removeEventListener("keydown",ja));const it=y.querySelector(".dm-plugin-banner-name");i(M.effect(()=>{const e=o.curId.value,t=Xo.value,a=o.blockTab.value||o.compTab.value,s=t==="block"?"Blocks":t==="component"?"Components":"Pages",r=t==="block"||t==="component"?a:e===null?"Editor":Pn(!!e,p.title.value,e);if(!c()||(document.title=`${r} - Domma CMS`,!it))return;const n=it.querySelector(".dm-plugin-banner-parent"),l=it.lastChild;n&&l&&l.nodeType===3&&it.querySelector(".dm-plugin-banner-sep")?(n.textContent=s,l.textContent=r):it.textContent=`${s} \u203A ${r}`})),dt(d,{id:"page-editor-back",icon:"arrow-left",title:"Back to Pages",onClick:()=>R.navigate("/pages")}),dt(d,{id:"page-editor-help",icon:"help-circle",title:"Editor reference",onClick:()=>Ha()});const en=dt(d,{id:"page-editor-view",icon:"external-link",title:"View on the site",onClick:()=>{m?.isEdit&&window.open(p.urlPath.peek().trim()||m.id,"_blank","noopener")}}),Ba=()=>{if(!m?.isEdit||o.saving.peek()||!c())return;const e=m,t=_(),a=Ro({...t,urlPath:e.id});if(a.length){E.toast(a[0].text,{type:"warning"});return}const s=gn({page:e.page,frontmatter:{...Gt(t,e,Xt(t)),adminTags:t.adminTags},body:t.body,source:e.id,pages:D,onCloned:async r=>{c()&&(await ha(),c()&&ue(r))}});i(()=>s.close())},To=dt(d,{id:"page-editor-clone",icon:"copy",title:"Clone page",onClick:Ba});i(M.effect(()=>{const e=Zo.value;for(const t of[en,To])t&&(t.disabled=!e);To&&(To.title=e?"Clone page":"Open a saved page to clone it")})),dt(d,{id:"page-editor-settings",icon:"settings",title:"Editor settings - font, size, spacing",onClick:()=>{Yo=hr(Jo,Wo)}}),i(qa(Ra,{position:"bottom"})),Domma.icons.scan();let Ia={ids:[],active:""};try{Ia=or(S.get(ps))}catch{}const lt=Ua(b),ct=nr(lt,Ia,history.state?.pe===1);P=ct.ids.filter(e=>{const t=I(e);return t.kind==="page"||(t.kind==="component"?le:be).has(t.id)}),ba=!1;for(const e of P){const t=I(e);t.kind==="page"&&ya(t.id)}q(),z(),St();for(const e of Ae)lo(e,{quiet:!0}).then(()=>{c()&&(q(),z())});for(const e of P){const t=I(e);t.kind==="component"&&e!==ct.active&&xe(t)&&go(t.id,{quiet:!0}).then(()=>{c()&&(q(),z())})}const Fa=lt&&!lt.id&&lt.kind!=="page";ct.active&&P.includes(ct.active)?await xt(ct.active):P.length?await xt(P[0]):Fa||te(),Fa&&c()&&(await(lt.kind==="block"?Nt:nt)({project:zt(b)||""}),c()&&te())}};function qo(d,b){!d||typeof b!="string"||!b||[...d.options].some(v=>v.value===b)||(d.append(Object.assign(document.createElement("option"),{value:b,textContent:`${b} (custom)`})),d.value=b)}function Lr(d,b,v){d.replaceChildren(...String(b).split(`
143
+ `).map((i,k)=>{const u=document.createElement("span");u.className="editor-line-number-row";const w=document.createElement("span");w.className="fold-toggle fold-toggle--empty";const y=document.createElement("span");return y.className="editor-line-num",y.textContent=String(k+1),u.append(w,y),u})),d.scrollTop=v.scrollTop}function Nr(d,b,v){if(!d||!b)return;const i=15,k=85,u=c=>Math.min(k,Math.max(i,c));let w=u(parseFloat(Pe().splitRatio)||50);const y=c=>{d.style.setProperty("--dm-editor-split",w+"%"),b.setAttribute("aria-valuenow",String(Math.round(w))),c&&Ke("splitRatio",w)};y(!1);const x=c=>{const A=d.getBoundingClientRect();A.width&&(w=u((c.clientX-A.left)/A.width*100)),y(!1)},j=()=>{document.removeEventListener("pointermove",x),document.removeEventListener("pointerup",j),d.classList.remove("is-resizing"),b.classList.remove("is-dragging"),y(!0)};v(j),b.addEventListener("pointerdown",c=>{window.matchMedia("(max-width: 768px)").matches||(c.preventDefault(),d.classList.add("is-resizing"),b.classList.add("is-dragging"),document.addEventListener("pointermove",x),document.addEventListener("pointerup",j))}),b.addEventListener("dblclick",()=>{w=50,y(!0)}),b.addEventListener("keydown",c=>{const A=c.shiftKey?10:2;let H=w;if(c.key==="ArrowLeft")H=w-A;else if(c.key==="ArrowRight")H=w+A;else if(c.key==="Home")H=i;else if(c.key==="End")H=k;else if(c.key==="Enter"||c.key===" ")H=50;else return;c.preventDefault(),w=u(H),y(!0)})}async function Dr(d){const b=d.selectionStart,v=d.selectionEnd,i=await vn({title:"Upload or insert an image"});if(!i||!d.isConnected)return;let k=i.split("/").pop().split("?")[0];try{k=decodeURIComponent(k)}catch{}const u=k.replace(/[\\[\]]/g,"\\$&"),w=i.replace(/\(/g,"%28").replace(/\)/g,"%29").replace(/ /g,"%20");d.setSelectionRange(b,v),nn(d,`![${u}](${w})`),d.dispatchEvent(new Event("input",{bubbles:!0}))}function jr(d,b,v){const i=Object.entries(b||{});return d?(d.replaceChildren(...i.map(([k,u])=>new Option(u?.label||k,k))),i.some(([k])=>k===v)?v:i[0]?.[0]||v):v}async function Br(d,b){if(!d)return;let v=[];try{const x=await h.get("/collections/roles/entries?limit=100");v=Array.isArray(x)?x:x?.entries||[]}catch{}const i=v.map(x=>({name:x.data?.name,label:x.data?.label||x.data?.name,level:x.data?.level??99})).filter(x=>x.name&&x.level!==0).sort((x,j)=>j.level-x.level),k=(x,j)=>Object.assign(document.createElement("option"),{value:x,textContent:j}),u=()=>{typeof b=="string"&&b&&![...d.options].some(x=>x.value===b)&&d.append(k(b,`${b} (custom)`))};if(!i.length)return u();const w=document.createElement("optgroup");w.label="Role and above",i.forEach(x=>w.append(k(x.name,`${x.label} and above`)));const y=document.createElement("optgroup");y.label="Role only",i.forEach(x=>y.append(k(`=${x.name}`,`${x.label} only`))),d.replaceChildren(k("public","Public - everyone"),w,y,k("private","Private - super-admin only")),u()}
@@ -447,6 +447,10 @@ You can use multiple `[dconfig]` blocks on one page. All valid blocks are merged
447
447
  ### Notes
448
448
 
449
449
  - Invalid JSON is silently dropped (no output, no error)
450
+ - The page editor checks DConfig against Domma's types (domma-js 0.59.0 and later): the DConfig tab lists a misspelt
451
+ key, an unknown component, an option the component does not have or a value of the wrong kind - in the field and in
452
+ every `[dconfig]` block in the body - with the likely name when it is a near miss. It is advice; Save is only refused
453
+ for JSON that is not an object
450
454
  - The `[dconfig]` shortcode is processed first in the pipeline, before all other shortcodes
451
455
  - `$.setup()` config can also be set per-page in the page editor's **DConfig** card (stored as `dconfig` in frontmatter)
452
456
  - Window-level `__CMS_DCONFIG__` (from frontmatter) and inline `dm-page-config` divs are merged at page load, with inline blocks taking precedence
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "domma-cms",
3
- "version": "1.10.23",
3
+ "version": "1.10.25",
4
4
  "description": "File-based CMS powered by Domma and Fastify. Run npx domma-cms my-site to create a new project.",
5
5
  "type": "module",
6
6
  "main": "server/server.js",
@@ -86,7 +86,7 @@
86
86
  "bcryptjs": "^3.0.3",
87
87
  "css-select": "^7.0.0",
88
88
  "dom-serializer": "^3.1.1",
89
- "domma-js": "0.58.2",
89
+ "domma-js": "0.60.0",
90
90
  "dotenv": "^17.2.3",
91
91
  "fastify": "5.12.7",
92
92
  "gray-matter": "^4.0.3",