domma-cms 1.6.9 → 1.6.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +1 -1
- package/admin/js/lib/hotkeys.js +1 -1
- package/admin/js/lib/layouts-arrange.js +1 -1
- package/admin/js/lib/menu-editor-arrange.js +2 -2
- package/admin/js/lib/menu-rows.js +1 -1
- package/admin/js/lib/menu-tree.js +1 -1
- package/admin/js/lib/shortcode-registry.js +1 -1
- package/admin/js/lib/sidebar-grouping.js +1 -1
- package/admin/js/lib/sidebar-renderer.js +1 -1
- package/admin/js/templates/docs/usage-navigation.html +1 -1
- package/admin/js/templates/docs/usage-shortcodes.html +4 -0
- package/admin/js/templates/layouts.html +2 -1
- package/admin/js/templates/menu-editor.html +1 -0
- package/admin/js/views/layouts.js +8 -4
- package/admin/js/views/menu-editor.js +20 -15
- package/package.json +1 -1
- package/public/css/site.css +1 -1
- package/public/css/theme-switcher.css +1 -1
- package/public/js/site.js +1 -1
- package/public/js/theme-switcher.js +1 -1
- package/server/routes/api/layouts.js +1 -0
- package/server/services/markdown.js +49 -1
- package/server/services/menuRender.js +4 -0
- package/server/services/menus.js +19 -1
- package/server/services/renderer.js +28 -8
- package/server/templates/page.html +3 -3
package/public/js/site.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{decodeBase64Json as N}from"/public/js/utf8-base64.mjs";import{makeBadgeEl as B,applyColour as j,applyPill as Y,applyFloat as G,applyHighlight as O,applyItemHighlight as U,itemHighlightAttrs as K,isCurrentItem as R,menuAlign as Q,applyClasses as D,cssClasses as P}from"/public/js/menu-decor.mjs?v=20261009-hover-darken";import{initFloatingMenus as Z}from"/public/js/menu-float.js?v=20260829-float-panel";import{enhancePickerFields as V,markInvalidFields as W,showValidationPopup as J}from"/public/js/forms.js?v=20261009-form-classes";import{buildWizardSteps as ee}from"/public/js/form-steps.mjs";import{applyFormClasses as X,applySubmitButtons as te,applyWizardButtons as ae}from"/public/js/form-submit.mjs";$(()=>{const x=window.__CMS_NAV__||{},h=window.__CMS_SITE__||{};if(h.autoTheme?.enabled){let t=function(e){const r=(e||"07:00").split(":");return+r[0]*60+(+r[1]||0)},o=function(){const e=new Date,r=e.getHours()*60+e.getMinutes();return r>=t(a.dayStart)&&r<t(a.nightStart)?a.dayTheme:a.nightTheme},n=function(e){const r=a.apply&&a.apply[e]||{theme:e,custom:""};Domma.theme.set(r.theme);for(const l of[...document.body.classList])l.startsWith("dm-custom-")&&document.body.classList.remove(l);r.custom&&document.body.classList.add(r.custom)};const a=h.autoTheme;n(o()),setInterval(()=>n(o()),6e4)}const A=$("#site-navbar");if(A.length&&x.brand){let o=function(c,y=0){return Array.isArray(c)?c.filter(i=>!(i&&i.type==="spacer")).filter(i=>!(i&&i.type==="separator"&&y===0)).map(i=>i&&i.type==="separator"?{divider:!0}:Array.isArray(i?.items)?{...i,items:o(i.items,y+1)}:i):c},n=function(c){return Array.isArray(c)?c.filter(y=>!(y&&(y.type==="separator"||y.type==="spacer"))):[]};const a={...x.brand},t=a.size&&a.size!=="md"?` navbar-brand-${a.size}`:"";if(a.logo||a.icon||a.tagline){let c="";a.logo?c+=`<img src="${a.logo}" class="navbar-brand-logo" alt="${a.text||""}">`:a.icon&&(c+=`<span data-icon="${a.icon}" style="width:1.1em;height:1.1em;margin-right:.35em;vertical-align:middle;"></span>`),a.text&&(c+=`<span class="navbar-brand-text${t}">${a.text}</span>`),a.tagline&&(c+=`<small class="navbar-brand-tagline">${a.tagline}</small>`),a.html=c}else t&&a.text&&(a.html=`<span class="navbar-brand-text${t}">${a.text}</span>`);const e=x.position==="floating",r=x.orientation==="vertical";Domma.elements.navbar("#site-navbar",{brand:a,items:o(x.items||[]),variant:x.variant||"dark",position:e?"static":x.position||"sticky",collapsible:!0,appearOnHover:!!x.appearOnHover}),Domma.icons.scan("#site-navbar");const l=A.get(0);l.classList.add(`dm-nav-align-${Q(x)||"centre"}`),r&&A.get(0).classList.add("dm-nav-vertical",x.side==="right"?"dm-nav-vertical-right":"dm-nav-vertical-left"),O(l,x),D(l,x.class),e&&(G(A.get(0),x),Z(A.get(0).parentNode||document));const f=l.querySelector(".navbar-toggle"),p=l.querySelector(".navbar-collapse");if(f&&p){let c=null;const y=()=>{p.classList.contains("show")&&f.click()},i=()=>{c&&(c.remove(),c=null),document.body.classList.remove("dm-drawer-open")},s=()=>{c||(c=document.createElement("div"),c.className="dm-navbar-backdrop",c.addEventListener("click",y),document.body.appendChild(c),document.body.classList.add("dm-drawer-open"))};f.addEventListener("click",()=>{requestAnimationFrame(()=>{p.classList.contains("show")?s():i()})}),p.addEventListener("click",u=>{u.target.closest("a")&&requestAnimationFrame(i)}),document.addEventListener("keydown",u=>{u.key==="Escape"&&p.classList.contains("show")&&y()})}const m=l.querySelector(".navbar-nav");if(m){const c=Array.from(m.children);let y=0;for(const i of x.items||[])if(!(i&&i.type==="separator")){if(i&&i.type==="spacer"){const s=document.createElement("li"),u=["xs","sm","md","lg","xl","flex"].includes(i.size)?i.size:"md";s.className=`dm-menu-spacer dm-menu-spacer--${u}`,s.setAttribute("aria-hidden","true"),m.insertBefore(s,c[y]||null);continue}y++}}const b=n(x.items||[]);l.querySelectorAll(".navbar-link[data-index], .navbar-dropdown-item[data-index]").forEach(c=>{const y=b[parseInt(c.dataset.index,10)];if(!y)return;const i=c.dataset.subindex!=null,s=i&&Array.isArray(y.items)?y.items[parseInt(c.dataset.subindex,10)]:y;if(!s)return;s.colour&&j(c,s.colour),s.pill&&!i&&Y(c,s.pill),U(c,s),D(c.closest("li"),s.class);const u=B(s.badge);u&&c.appendChild(u),R(s.url,location.pathname)&&(c.classList.add("active"),c.setAttribute("aria-current","page"))})}const C=$("#site-footer");if(C.length){let e=function(s){return String(s??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")},r=function(s){return e(s).replace(/'/g,"'")},l=function(s){if(s&&s.type==="separator")return'<li class="footer-sep"><hr></li>';if(s&&s.type==="spacer")return`<li class="dm-menu-spacer dm-menu-spacer--${["xs","sm","md","lg","xl","flex"].includes(s.size)?s.size:"md"}" aria-hidden="true"></li>`;const u=r(s.url||"#"),d=e(s.text||""),w=Array.isArray(s.items)&&s.items.length?`<ul>${s.items.map(l).join("")}</ul>`:"",v=K(s),q=[v.hover&&` data-menu-item-hover="${r(v.hover)}"`,v.active&&` data-menu-item-active="${r(v.active)}"`].filter(Boolean).join(""),M=v.accent?` style="--dm-menu-highlight:${r(v.accent)}"`:"",k=P(s.class).join(" ");return`<li${k?` class="${r(k)}"`:""}><a href="${u}"${q}${M}>${d}</a>${w}</li>`},f=function(s,u){return(s||[]).forEach(d=>{d&&(d.type==="separator"||d.type==="spacer")||(u.push(d),Array.isArray(d.items)&&d.items.length&&f(d.items,u))}),u};const a=h.social||{},t={twitter:{label:"X / Twitter",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.742l7.73-8.835L1.254 2.25H8.08l4.259 5.629L18.244 2.25zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>'},facebook:{label:"Facebook",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/></svg>'},instagram:{label:"Instagram",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z"/></svg>'},linkedin:{label:"LinkedIn",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>'},github:{label:"GitHub",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>'},youtube:{label:"YouTube",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M23.495 6.205a3.007 3.007 0 00-2.088-2.088c-1.87-.501-9.396-.501-9.396-.501s-7.507-.01-9.396.501A3.007 3.007 0 00.527 6.205a31.247 31.247 0 00-.522 5.805 31.247 31.247 0 00.522 5.783 3.007 3.007 0 002.088 2.088c1.868.502 9.396.502 9.396.502s7.506 0 9.396-.502a3.007 3.007 0 002.088-2.088 31.247 31.247 0 00.5-5.783 31.247 31.247 0 00-.5-5.805zM9.609 15.601V8.408l6.264 3.602z"/></svg>'}};let o='<div class="footer-inner container">';const n=window.__CMS_FOOTER__||{primary:[],legal:[],copyright:""};if(n.copyright&&(o+=`<p>${e(n.copyright)}</p>`),n.primary.length&&(o+=`<nav class="footer-nav footer-nav--primary"><ul>${n.primary.map(l).join("")}</ul></nav>`),n.legal.length&&(o+=`<nav class="footer-nav footer-nav--legal"><ul>${n.legal.map(l).join("")}</ul></nav>`),h.footer){const s=Object.keys(t).filter(d=>a[d]),u=P(h.footer.socialClass).join(" ");s.length&&(o+='<div class="footer-social">',s.forEach(d=>{const{label:w,svg:v}=t[d];o+=`<a href="${a[d]}" target="_blank" rel="noopener noreferrer" aria-label="${w}" class="footer-social-link${u?` ${r(u)}`:""}">${v}</a>`}),o+="</div>")}o+="</div>",C.html(o),D(C.get(0),h.footer?.class);const p=[...f(n.primary,[]),...f(n.legal,[])];C.get(0).querySelectorAll(".footer-nav a").forEach((s,u)=>{const d=p[u];if(!d)return;d.colour&&j(s,d.colour);const w=B(d.badge);w&&s.appendChild(w),R(d.url,location.pathname)&&(s.classList.add("is-active"),s.setAttribute("aria-current","page"))}),O(C.get(0).querySelector(".footer-nav--primary"),{highlight:n.primaryHighlight}),O(C.get(0).querySelector(".footer-nav--legal"),{highlight:n.legalHighlight}),D(C.get(0).querySelector(".footer-nav--primary"),n.primaryClass),D(C.get(0).querySelector(".footer-nav--legal"),n.legalClass);const b=h.footer?.showMotionToggle!==!1,c=S.get("reduced_motion"),y=c!==null?!!c:!!(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches),i=C.get(0).querySelector(".footer-inner");if(b&&i){const s=document.createElement("input");s.type="checkbox",s.className="form-switch-input",s.id="dm-motion-switch",s.checked=y,s.addEventListener("change",function(){S.set("reduced_motion",this.checked),window.location.reload()});const u=document.createElement("span");u.className="form-switch-label",u.textContent="Reduce motion";const d=document.createElement("label");d.className="form-switch footer-motion-switch",d.title="Reduce motion",d.appendChild(s),d.appendChild(u),i.appendChild(d)}}if($("#site-sidebar").length){const a=document.querySelector(".site-content"),t=l=>!l.closest(".hero, .card, .accordion, .tabs, figure, #site-sidebar"),o=l=>a?[...a.querySelectorAll(l)].filter(t):[],n=o("h2").length?o("h2"):o("h3"),e=new Set([...document.querySelectorAll("[id]")].map(l=>l.id)),r=[];for(const l of n){if(!l.id){const f=(l.textContent||"").toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"section";let p=f;for(let m=2;e.has(p);m++)p=`${f}-${m}`;e.add(p),l.id=p}r.push({text:l.textContent.trim(),url:`#${l.id}`,section:l.id})}r.length?Domma.elements.sidebar("#site-sidebar",{items:r,fixed:!1,push:!1,collapsible:!1,variant:"theme",scrollSpy:!0}):document.querySelector(".site-main.with-sidebar")?.classList.add("no-sidebar-items")}Domma.icons.scan(),Domma.syntax?.scan&&Domma.syntax.scan();const g=$(".page-body");if(g.length){g.find(".accordion").each(function(){Domma.elements.accordion(this,{allowMultiple:this.dataset.multi==="true"})}),g.find(".tabs").each(function(){Domma.elements.tabs(this)}),g.find(".carousel").each(function(){const a={autoplay:this.dataset.autoplay==="true",interval:parseInt(this.dataset.interval,10)||5e3,loop:this.dataset.loop!=="false",animation:this.dataset.animation||"slide"};if(this.dataset.animationDuration){const t=parseInt(this.dataset.animationDuration,10);Number.isFinite(t)&&(a.animationDuration=t)}this.dataset.animationEasing&&(a.animationEasing=this.dataset.animationEasing),this.dataset.ctx&&(this._dmCtxSlides=Array.from(this.querySelectorAll(".carousel-slide")).map(t=>t.cloneNode(!0)),this._dmCarouselOpts=a),this._dmCarousel=Domma.elements.carousel(this,a)}),g.find(".dm-countdown").each(function(){const a={autoStart:!0},t=String(this.dataset.format||"").trim(),o=String(this.dataset.to||"").trim(),n=/^(\d{4})-(\d{2})-(\d{2})$/.exec(o),e=n?new Date(+n[1],+n[2]-1,+n[3]).getTime():o?new Date(o).getTime():NaN;Number.isFinite(e)?a.duration=Math.max(0,e-Date.now()):this.dataset.duration&&(a.duration=(parseInt(this.dataset.duration,10)||0)*1e3);const r=/^dd:/i.test(t);a.format=r?"hh:mm:ss":t||(a.duration>=36e5?"hh:mm:ss":"mm:ss");const l=this,f=m=>String(m).padStart(2,"0"),p=m=>{const b=Math.max(0,Math.floor(m/1e3)),c=l.querySelector(".dm-timer-time");c&&(c.textContent=`${f(Math.floor(b/86400))}:${f(Math.floor(b%86400/3600))}:${f(Math.floor(b%3600/60))}:${f(b%60)}`)};r&&(a.onTick=p),Domma.elements.timer(this,a),r&&p(a.duration||0)}),g.find("[data-tooltip]").each(function(){Domma.elements.tooltip(this,{content:$(this).data("tooltip"),position:$(this).data("tooltip-position")||"top"})}),g.find(".dm-progression").each(function(){const a=Array.from(this.querySelectorAll(".dm-progression-item")).map(n=>{const e={title:n.querySelector(".dm-progression-item-title")?.textContent?.trim()||"",description:n.querySelector(".dm-progression-item-body")?.innerHTML?.trim()||""};return n.dataset.date&&(e.date=n.dataset.date),n.dataset.status&&(e.status=n.dataset.status),n.dataset.entryId&&(e._entryId=n.dataset.entryId),e}),t=this.dataset.layout==="centred"?"centered":this.dataset.layout||"vertical",o=Domma.elements.progression(this,{layout:t,theme:this.dataset.theme||"minimal",mode:this.dataset.mode||"timeline",statusIcons:!0,allowHtml:!0,...a.length?{items:a}:{}});a.length&&(this._dmCtx={instance:o,items:a})});try{Domma.effects.reveal(".page-body .hero",{animation:"slide-up",duration:480,threshold:.06,stagger:60,once:!1})}catch{}document.querySelectorAll(".page-body .row[data-reveal]").forEach(a=>{const t=a.dataset.revealMode||"stagger",o=a.dataset.revealAnimation||"slide-up",n=parseInt(a.dataset.revealDuration,10)||400,e=parseInt(a.dataset.revealStagger,10)||60,r=parseInt(a.dataset.revealDelay,10)||0,l=a.dataset.revealDirection==="rtl",f=Array.from(a.children),p={"slide-up":"translateY(30px)","slide-down":"translateY(-30px)","slide-left":"translateX(30px)","slide-right":"translateX(-30px)",zoom:"scale(0.85)",flip:"perspective(600px) rotateX(15deg)"};f.forEach((m,b)=>{m.style.opacity="0",m.style.transform=p[o]||"",m.style.transition=`opacity ${n}ms ease, transform ${n}ms ease`;const c=l?f.length-1-b:b;m.style.transitionDelay=t==="stagger"?`${r+c*e}ms`:`${r}ms`}),requestAnimationFrame(()=>requestAnimationFrame(()=>{const m=new IntersectionObserver(b=>{b.forEach(c=>{c.isIntersecting&&(c.target.offsetWidth,c.target.style.opacity="1",c.target.style.transform="none",m.unobserve(c.target))})},{threshold:.1});f.forEach(b=>m.observe(b))}))}),g.find(".card[data-collapsible]").each(function(){const a=this.querySelector(".card-header");a&&a.addEventListener("click",()=>this.classList.toggle("is-collapsed"))}),g.find(".dm-so-trigger").each(function(){this.addEventListener("click",()=>{const a=this.dataset.soTarget,t=document.getElementById(a);if(!t)return;const o=E.slideover({title:t.dataset.soTitle||"",size:t.dataset.soSize||"md",position:t.dataset.soPosition||"right"});t.style.display="",o.setContent(t),o.open()})})}if(typeof $.setup=="function"){const a=Object.assign({},window.__CMS_DCONFIG__||{});if(document.querySelectorAll(".dm-page-config[data-config]").forEach(t=>{try{const o=N(t.dataset.config);Object.assign(a,o)}catch{}}),Object.keys(a).length>0){const t={};for(const[o,n]of Object.entries(a)){const e=n?.events?.click,{confirm:r,toast:l,alert:f,prompt:p,...m}=e||{};r||l||f||p?($(o).on("click",async function(c){if(c.preventDefault(),r&&!await E.confirm(r))return;let y=null;if(!(p&&(y=await E.prompt(p,{inputPlaceholder:m.promptPlaceholder||"",inputValue:m.promptDefault||""}),y===null))){if(m.target){const i=$(m.target);m.toggleClass&&i.toggleClass(m.toggleClass),m.addClass&&i.addClass(m.addClass),m.removeClass&&i.removeClass(m.removeClass),y!==null&&(m.setText&&i.text(y),m.setVal&&i.val(y),m.setAttr&&i.attr(m.setAttr,y))}m.href&&(window.location.href=m.href),l&&E.toast(l,{type:m.toastType||"success"}),f&&E.alert(f)}}),Object.keys(m).length&&(t[o]={...n,events:{...n.events,click:m}})):t[o]=n}$.setup(t)}}g.length&&I(g.get(0))}),window.wireCTAButtons=I;function I(x){x.querySelectorAll(".dm-cta-trigger").forEach(h=>{h.__ctaWired||(h.__ctaWired=!0,h.addEventListener("click",async()=>{const A=h.dataset.action,C=h.dataset.entry,_=h.dataset.confirm;let g=S.get("auth_token");if(!g){E.toast("Please log in to perform this action.",{type:"warning"});return}if(_&&!await E.confirm(_))return;const a=Array.from(h.childNodes).map(o=>o.cloneNode(!0));h.disabled=!0,h.textContent="Running\u2026";const t=o=>fetch(`/api/actions/${A}/public`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify(h.dataset.scope?{entryId:C,scope:h.dataset.scope}:{entryId:C})});try{let o=await t(g);if(o.status===401){const e=S.get("auth_refresh_token");if(e){const r=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e})});if(r.ok){const{token:l}=await r.json();S.set("auth_token",l),g=l,o=await t(g)}}}const n=await o.json().catch(()=>({}));if(!o.ok)throw new Error(n.error||n.message||`Error ${o.status}`);E.toast(n.message||"Action completed.",{type:"success"})}catch(o){E.toast(o.message||"Action failed.",{type:"error"})}finally{h.disabled=!1,h.textContent="",a.forEach(o=>h.appendChild(o)),Domma.icons.scan(h)}}))})}(function(){const h=document.querySelectorAll('.dm-collection-hydrate[data-collection-scope="mine"]');if(!h.length)return;const A=S.get("auth_token");function C(g,a){const t=document.createElement("div");t.className="dm-collection-display dm-collection-empty";const o=document.createElement("p");if(a){o.appendChild(document.createTextNode("Please "));const n=document.createElement("a");n.href="/login",n.textContent="sign in",o.appendChild(n),o.appendChild(document.createTextNode(" to view your entries."))}else o.textContent=g;return t.appendChild(o),t}function _(g,a){const t=document.createElement("template");t.innerHTML=a||"",g.replaceWith(t.content)}h.forEach(async g=>{const a=g.dataset.collectionAttrs;if(!a)return;if(!A){g.replaceChildren(C("",!0));return}const t=o=>fetch("/api/collections/render-scope",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify({attrs:a})});try{let o=A,n=await t(o);if(n.status===401){const r=S.get("auth_refresh_token");if(r){const l=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:r})});if(l.ok){const{token:f}=await l.json();S.set("auth_token",f),o=f,n=await t(o)}}}if(!n.ok){const{error:r}=await n.json().catch(()=>({}));g.replaceChildren(C(r||"Unable to load entries.",!1));return}const{html:e}=await n.json();_(g,e),window.DommaCollectionBrowser?.hydrate&&window.DommaCollectionBrowser.hydrate(document)}catch{g.replaceChildren(C("Unable to load entries.",!1))}}),setTimeout(()=>{typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(),typeof Domma<"u"&&Domma.syntax?.scan&&Domma.syntax.scan(),I(document.body)},100)})(),(function(){const h=document.querySelectorAll("[data-collection-table]");!h.length||typeof T>"u"||!T.create||h.forEach(A=>{let C;try{C=N(A.dataset.payload)}catch{return}const{columns:_,rows:g,search:a,sortable:t,exportable:o,pageSize:n,empty:e,ctaConfig:r,slug:l,exportCfg:f}=C;if(!_?.length)return;if(r){const b=_.findIndex(c=>c.key==="_cta");b!==-1&&(_[b]={key:"_cta",title:"",render:(c,y)=>{const i=document.createElement("button");if(i.className=`btn btn-${r.style||"primary"} dm-cta-trigger`,i.dataset.action=r.action||"",r.scope&&(i.dataset.scope=r.scope),i.dataset.entry=y._entryId||"",r.confirm&&(i.dataset.confirm=r.confirm),r.icon){const s=document.createElement("span");s.dataset.icon=r.icon,i.appendChild(s),i.appendChild(document.createTextNode(" "))}return i.appendChild(document.createTextNode(r.label||"Run")),i}})}const p="col-table-"+Math.random().toString(36).slice(2,7),m=document.createElement("div");m.id=p,A.replaceChildren(m),T.create("#"+p,{data:g,columns:_,search:a,sortable:t,exportable:o,pageSize:n,emptyMessage:e}),r&&I(m),A._dmTable={columns:_,rows:g,slug:l,exportCfg:f,render(b){T.create("#"+p,{data:b,columns:_,search:a,sortable:t,exportable:o,pageSize:n,emptyMessage:e}),r&&I(m)}}})})(),(function(){const h=document.querySelectorAll("[data-form-inline]");if(!h.length||typeof F>"u")return;function A(t){const o=t&&t.logic;return!!(o&&(o.visibility||o.requirement))}function C(t,o){const n={};return(t||[]).forEach(e=>{if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const r=e.type==="chooser"||!!(e.variant&&["select","radio","checkbox-group"].includes(e.type)),l=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":r?"chooser":e.type,f={...e.formConfig||{}};f.span==="full"&&o&&(f.span=o);const p={type:l,required:A(e)?!1:e.required,label:e.label,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{hint:e.helper},...e.tooltip&&{tooltip:e.tooltip},...f}};e.minLength!==void 0&&(p.minLength=e.minLength),e.maxLength!==void 0&&(p.maxLength=e.maxLength),e.min!==void 0&&(p.min=e.min),e.max!==void 0&&(p.max=e.max),r&&(e.variant&&(p.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(p.multiple=!0),e.density&&(p.density=e.density),e.columns&&(p.columns=e.columns),e.accent&&(p.accent=e.accent),e.accentStyle&&(p.accentStyle=e.accentStyle),e.glow&&(p.glow=!0),e.glowColour&&(p.glowColour=e.glowColour),e.shadow&&(p.shadow=e.shadow),e.shadowColour&&(p.shadowColour=e.shadowColour)),n[e.name]=p}),n}function _(t){const o={};return(t||[]).forEach(n=>{if(!(!n.name||n.type==="page-break"||n.type==="spacer")&&(n.type==="select"||n.type==="multiselect")&&n.required){const e=(n.options||[])[0];e&&(o[n.name]=typeof e=="object"?e.value:e)}}),o}function g(t,o){(o||[]).forEach(n=>{if(n.type!=="date"||!n.name)return;const e=t.querySelector(`[name="${n.name}"]`);e&&e.type!=="date"&&(e.type="date")})}function a(t,o,n){let e=t.querySelector(".cms-form-message");e||(e=document.createElement("p"),e.className="cms-form-message",t.appendChild(e)),e.textContent=o,e.style.cssText=n?"color:var(--dm-danger);margin-top:.75rem;":"color:var(--dm-success);margin-top:.75rem;"}h.forEach(t=>{let o;try{o=N(t.dataset.formInline)}catch{return}const n=o.fields||[],e=o.settings||{},r=Number(e.columns)===3?3:2,l=e.layout||"grid",f=n.some(i=>i.type==="page-break"),p=async i=>{if(t.dataset.triggerBlocked==="true"){const s=t._formLogicRuntime,u=s&&s.submitBlock?s.submitBlock().reasons:[];a(t,u.join(" ")||"This form cannot be submitted yet.",!0);const d=new Error("Blocked by a form trigger");throw d.formSubmitFailed=!0,d}try{const s=t.querySelector(".fb-form-honeypot"),u=s?.querySelector('input[type="text"]')||null,d=s?.querySelector('[name="_t"]')||null,w=Object.assign({},i);delete w._t,s?.dataset.hpName&&delete w[s.dataset.hpName],u!==null&&(w._hp=u.value),d!==null&&(w._t=d.value);const v=await H.post(`/api/forms/submit/${o.slug}`,w);if(v&&v.error){a(t,v.error,!0);const q=new Error(v.error);throw q.formSubmitFailed=!0,q}if(v?.redirect){window.location.href=v.redirect;return}for(;t.firstChild;)t.removeChild(t.firstChild);a(t,v?.message||e.successMessage||"Thank you for your submission.",!1)}catch(s){throw s.formSubmitFailed||a(t,s.message||"Submission failed. Please try again.",!0),s}},m=Date.now();function b(i){const s=i.querySelector("form");if(!s||s.querySelector(".fb-form-honeypot"))return;const u=document.createElement("div");u.className="fb-form-honeypot",u.setAttribute("aria-hidden","true");const d=document.createElement("input");d.name=s.querySelector('[name="website"]')?"_website":"website",u.dataset.hpName=d.name,d.type="text",d.tabIndex=-1,d.autocomplete="url",d.placeholder="https://",u.appendChild(d);const w=document.createElement("input");w.name="_t",w.type="hidden",w.value=m,u.appendChild(w),s.appendChild(u)}function c(i){if(!window.FormLogicEngine||!n.some(u=>u.logic||Array.isArray(u.triggers)&&u.triggers.length))return null;const s=new window.FormLogicEngine.FormLogicRuntime(o,t,i?{baseValues:i}:void 0);if(s.init(),t._formLogicRuntime=s,t._formLogicObserved)return s;if(t._formLogicObserved=!0,t.parentNode&&typeof MutationObserver<"u"){const u=new MutationObserver(function(d){for(const w of d)for(const v of w.removedNodes)if(v===t||v.nodeType===1&&v.contains&&v.contains(t)){t._formLogicRuntime&&t._formLogicRuntime.destroy(),u.disconnect();return}});u.observe(t.parentNode,{childList:!0,subtree:!1}),t._formLogicObserver=u}return s}let y=!1;if(t.addEventListener("dm-form-end",i=>{const s=i.detail?.validation;if(s&&!s.valid){W(t,s.missing),J(s);return}y||(y=!0,p(i.detail?.values||{}).catch(()=>{}).finally(()=>{y=!1}))}),f&&F.wizard){const i=ee(n,o.title),s=i.map(k=>({title:k.title,description:k.description,fields:C(k.fields,r)})),u=i.map(k=>k.fields);let d=0,w=null,v=null;const q=k=>{const L=window.FormLogicEngine;if(!L||!L.validateFields)return;const z=L.validateFields(t,u[d]||[]);z.valid||(k.preventDefault(),k.stopImmediatePropagation(),W(t,z.missing),J(z))},M=()=>{const k=u[d]||n;ae(t,e),X(t,e,k),g(t,k),V(t,k),e.honeypot!==!1&&b(t),w&&w.destroy(),w=c(v?.getStepData?v.getStepData():void 0),t.querySelectorAll(".wizard-next, .wizard-submit").forEach(L=>L.addEventListener("click",q,!0))};v=F.wizard(t,{schema:{steps:s},layout:l,columns:r,finishText:e.submitText||"Finish",onSubmit:p,onStepChange:k=>{d=k,setTimeout(M,0)}}),t.addEventListener("dm-form-trigger",k=>{if(k.detail?.type!=="goto-step"||!v?.goToStep)return;const L=Number(k.detail.action.step);!Number.isFinite(L)||L<0||L>=s.length||L!==d&&v.goToStep(L)}),Promise.resolve(v).then(M)}else if(F.render){const i=F.render(t,C(n,r),_(n),{submitText:e.submitText||"Submit",layout:l,columns:r,onSubmit:p});Promise.resolve(i).then(function(){te(t,e,l),X(t,e,n),g(t,n),V(t,n),e.honeypot!==!1&&b(t),c()})}}),$(document).on("click",".dm-banner__dismiss",function(){$(this).closest(".dm-banner").remove()})})();
|
|
1
|
+
import{decodeBase64Json as N}from"/public/js/utf8-base64.mjs";import{makeBadgeEl as O,applyColour as j,applyPill as Y,applyFloat as G,applyHighlight as B,applyItemHighlight as U,itemHighlightAttrs as K,isCurrentItem as R,menuAlign as Q,applyClasses as D,cssClasses as P}from"/public/js/menu-decor.mjs?v=20261009-hover-darken";import{initFloatingMenus as Z}from"/public/js/menu-float.js?v=20260829-float-panel";import{enhancePickerFields as V,markInvalidFields as W,showValidationPopup as J}from"/public/js/forms.js?v=20261009-form-classes";import{buildWizardSteps as ee}from"/public/js/form-steps.mjs";import{applyFormClasses as X,applySubmitButtons as te,applyWizardButtons as ae}from"/public/js/form-submit.mjs";$(()=>{const x=window.__CMS_NAV__||{},g=window.__CMS_SITE__||{};if(g.autoTheme?.enabled){let t=function(e){const r=(e||"07:00").split(":");return+r[0]*60+(+r[1]||0)},n=function(){const e=new Date,r=e.getHours()*60+e.getMinutes();return r>=t(o.dayStart)&&r<t(o.nightStart)?o.dayTheme:o.nightTheme},s=function(e){const r=o.apply&&o.apply[e]||{theme:e,custom:""};Domma.theme.set(r.theme);for(const d of[...document.body.classList])d.startsWith("dm-custom-")&&document.body.classList.remove(d);r.custom&&document.body.classList.add(r.custom)};const o=g.autoTheme;s(n()),setInterval(()=>s(n()),6e4)}const A=$("#site-navbar");if(A.length&&x.brand){let n=function(c,f=0){return Array.isArray(c)?c.filter(i=>!(i&&(i.type==="spacer"||i.type==="theme-switcher"))).filter(i=>!(i&&i.type==="separator"&&f===0)).map(i=>i&&i.type==="separator"?{divider:!0}:Array.isArray(i?.items)?{...i,items:n(i.items,f+1)}:i):c},s=function(c){return Array.isArray(c)?c.filter(f=>!(f&&(f.type==="separator"||f.type==="spacer"||f.type==="theme-switcher"))):[]};const o={...x.brand},t=o.size&&o.size!=="md"?` navbar-brand-${o.size}`:"";if(o.logo||o.icon||o.tagline){let c="";o.logo?c+=`<img src="${o.logo}" class="navbar-brand-logo" alt="${o.text||""}">`:o.icon&&(c+=`<span data-icon="${o.icon}" style="width:1.1em;height:1.1em;margin-right:.35em;vertical-align:middle;"></span>`),o.text&&(c+=`<span class="navbar-brand-text${t}">${o.text}</span>`),o.tagline&&(c+=`<small class="navbar-brand-tagline">${o.tagline}</small>`),o.html=c}else t&&o.text&&(o.html=`<span class="navbar-brand-text${t}">${o.text}</span>`);const e=x.position==="floating",r=x.orientation==="vertical";Domma.elements.navbar("#site-navbar",{brand:o,items:n(x.items||[]),variant:x.variant||"dark",position:e?"static":x.position||"sticky",collapsible:!0,appearOnHover:!!x.appearOnHover}),Domma.icons.scan("#site-navbar");const d=A.get(0);d.classList.add(`dm-nav-align-${Q(x)||"centre"}`),r&&A.get(0).classList.add("dm-nav-vertical",x.side==="right"?"dm-nav-vertical-right":"dm-nav-vertical-left"),B(d,x),D(d,x.class),e&&(G(A.get(0),x),Z(A.get(0).parentNode||document));const h=d.querySelector(".navbar-toggle"),p=d.querySelector(".navbar-collapse");if(h&&p){let c=null;const f=()=>{p.classList.contains("show")&&h.click()},i=()=>{c&&(c.remove(),c=null),document.body.classList.remove("dm-drawer-open")},a=()=>{c||(c=document.createElement("div"),c.className="dm-navbar-backdrop",c.addEventListener("click",f),document.body.appendChild(c),document.body.classList.add("dm-drawer-open"))};h.addEventListener("click",()=>{requestAnimationFrame(()=>{p.classList.contains("show")?a():i()})}),p.addEventListener("click",l=>{l.target.closest("a")&&requestAnimationFrame(i)}),document.addEventListener("keydown",l=>{l.key==="Escape"&&p.classList.contains("show")&&f()})}const m=d.querySelector(".navbar-nav");if(m){const c=Array.from(m.children);let f=0;for(const i of x.items||[])if(!(i&&i.type==="separator")){if(i&&i.type==="spacer"){const a=document.createElement("li"),l=["xs","sm","md","lg","xl","flex"].includes(i.size)?i.size:"md";a.className=`dm-menu-spacer dm-menu-spacer--${l}`,a.setAttribute("aria-hidden","true"),m.insertBefore(a,c[f]||null);continue}if(i&&i.type==="theme-switcher"){const a=document.createElement("li");a.className="dm-menu-theme-switcher";const l=document.createElement("span");l.dataset.themeSwitcher="menu",l.dataset.position="inline",a.appendChild(l),m.insertBefore(a,c[f]||null);continue}f++}window.CMSThemeSwitcher?.scan(m)}const b=s(x.items||[]);d.querySelectorAll(".navbar-link[data-index], .navbar-dropdown-item[data-index]").forEach(c=>{const f=b[parseInt(c.dataset.index,10)];if(!f)return;const i=c.dataset.subindex!=null,a=i&&Array.isArray(f.items)?f.items[parseInt(c.dataset.subindex,10)]:f;if(!a)return;a.colour&&j(c,a.colour),a.pill&&!i&&Y(c,a.pill),U(c,a),D(c.closest("li"),a.class);const l=O(a.badge);l&&c.appendChild(l),R(a.url,location.pathname)&&(c.classList.add("active"),c.setAttribute("aria-current","page"))})}const w=$("#site-footer");if(w.length){let e=function(a){return String(a??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")},r=function(a){return e(a).replace(/'/g,"'")},d=function(a){if(a&&a.type==="separator")return'<li class="footer-sep"><hr></li>';if(a&&a.type==="spacer")return`<li class="dm-menu-spacer dm-menu-spacer--${["xs","sm","md","lg","xl","flex"].includes(a.size)?a.size:"md"}" aria-hidden="true"></li>`;if(a&&a.type==="theme-switcher")return'<li class="dm-menu-theme-switcher"><span data-theme-switcher="menu" data-position="inline"></span></li>';const l=r(a.url||"#"),u=e(a.text||""),C=Array.isArray(a.items)&&a.items.length?`<ul>${a.items.map(d).join("")}</ul>`:"",v=K(a),q=[v.hover&&` data-menu-item-hover="${r(v.hover)}"`,v.active&&` data-menu-item-active="${r(v.active)}"`].filter(Boolean).join(""),M=v.accent?` style="--dm-menu-highlight:${r(v.accent)}"`:"",k=P(a.class).join(" ");return`<li${k?` class="${r(k)}"`:""}><a href="${l}"${q}${M}>${u}</a>${C}</li>`},h=function(a,l){return(a||[]).forEach(u=>{u&&(u.type==="separator"||u.type==="spacer"||u.type==="theme-switcher")||(l.push(u),Array.isArray(u.items)&&u.items.length&&h(u.items,l))}),l};const o=g.social||{},t={twitter:{label:"X / Twitter",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.742l7.73-8.835L1.254 2.25H8.08l4.259 5.629L18.244 2.25zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>'},facebook:{label:"Facebook",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/></svg>'},instagram:{label:"Instagram",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z"/></svg>'},linkedin:{label:"LinkedIn",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>'},github:{label:"GitHub",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>'},youtube:{label:"YouTube",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M23.495 6.205a3.007 3.007 0 00-2.088-2.088c-1.87-.501-9.396-.501-9.396-.501s-7.507-.01-9.396.501A3.007 3.007 0 00.527 6.205a31.247 31.247 0 00-.522 5.805 31.247 31.247 0 00.522 5.783 3.007 3.007 0 002.088 2.088c1.868.502 9.396.502 9.396.502s7.506 0 9.396-.502a3.007 3.007 0 002.088-2.088 31.247 31.247 0 00.5-5.783 31.247 31.247 0 00-.5-5.805zM9.609 15.601V8.408l6.264 3.602z"/></svg>'}};let n='<div class="footer-inner container">';const s=window.__CMS_FOOTER__||{primary:[],legal:[],copyright:""};if(s.copyright&&(n+=`<p>${e(s.copyright)}</p>`),s.primary.length&&(n+=`<nav class="footer-nav footer-nav--primary"><ul>${s.primary.map(d).join("")}</ul></nav>`),s.legal.length&&(n+=`<nav class="footer-nav footer-nav--legal"><ul>${s.legal.map(d).join("")}</ul></nav>`),g.footer){const a=Object.keys(t).filter(u=>o[u]),l=P(g.footer.socialClass).join(" ");a.length&&(n+='<div class="footer-social">',a.forEach(u=>{const{label:C,svg:v}=t[u];n+=`<a href="${o[u]}" target="_blank" rel="noopener noreferrer" aria-label="${C}" class="footer-social-link${l?` ${r(l)}`:""}">${v}</a>`}),n+="</div>")}n+="</div>",w.html(n),window.CMSThemeSwitcher?.scan(w.get(0)),D(w.get(0),g.footer?.class);const p=[...h(s.primary,[]),...h(s.legal,[])];w.get(0).querySelectorAll(".footer-nav a").forEach((a,l)=>{const u=p[l];if(!u)return;u.colour&&j(a,u.colour);const C=O(u.badge);C&&a.appendChild(C),R(u.url,location.pathname)&&(a.classList.add("is-active"),a.setAttribute("aria-current","page"))}),B(w.get(0).querySelector(".footer-nav--primary"),{highlight:s.primaryHighlight}),B(w.get(0).querySelector(".footer-nav--legal"),{highlight:s.legalHighlight}),D(w.get(0).querySelector(".footer-nav--primary"),s.primaryClass),D(w.get(0).querySelector(".footer-nav--legal"),s.legalClass);const b=g.footer?.showMotionToggle!==!1,c=S.get("reduced_motion"),f=c!==null?!!c:!!(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches),i=w.get(0).querySelector(".footer-inner");if(b&&i){const a=document.createElement("input");a.type="checkbox",a.className="form-switch-input",a.id="dm-motion-switch",a.checked=f,a.addEventListener("change",function(){S.set("reduced_motion",this.checked),window.location.reload()});const l=document.createElement("span");l.className="form-switch-label",l.textContent="Reduce motion";const u=document.createElement("label");u.className="form-switch footer-motion-switch",u.title="Reduce motion",u.appendChild(a),u.appendChild(l),i.appendChild(u)}}if($("#site-sidebar").length){const o=document.querySelector(".site-content"),t=d=>!d.closest(".hero, .card, .accordion, .tabs, figure, #site-sidebar"),n=d=>o?[...o.querySelectorAll(d)].filter(t):[],s=n("h2").length?n("h2"):n("h3"),e=new Set([...document.querySelectorAll("[id]")].map(d=>d.id)),r=[];for(const d of s){if(!d.id){const h=(d.textContent||"").toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"section";let p=h;for(let m=2;e.has(p);m++)p=`${h}-${m}`;e.add(p),d.id=p}r.push({text:d.textContent.trim(),url:`#${d.id}`,section:d.id})}r.length?Domma.elements.sidebar("#site-sidebar",{items:r,fixed:!1,push:!1,collapsible:!1,variant:"theme",scrollSpy:!0,position:document.querySelector(".site-main.sidebar-right")?"right":"left"}):document.querySelector(".site-main.with-sidebar")?.classList.add("no-sidebar-items")}Domma.icons.scan(),Domma.syntax?.scan&&Domma.syntax.scan();const y=$(".page-body");if(y.length){y.find(".accordion").each(function(){Domma.elements.accordion(this,{allowMultiple:this.dataset.multi==="true"})}),y.find(".tabs").each(function(){Domma.elements.tabs(this)}),y.find(".carousel").each(function(){const o={autoplay:this.dataset.autoplay==="true",interval:parseInt(this.dataset.interval,10)||5e3,loop:this.dataset.loop!=="false",animation:this.dataset.animation||"slide"};if(this.dataset.animationDuration){const t=parseInt(this.dataset.animationDuration,10);Number.isFinite(t)&&(o.animationDuration=t)}this.dataset.animationEasing&&(o.animationEasing=this.dataset.animationEasing),this.dataset.ctx&&(this._dmCtxSlides=Array.from(this.querySelectorAll(".carousel-slide")).map(t=>t.cloneNode(!0)),this._dmCarouselOpts=o),this._dmCarousel=Domma.elements.carousel(this,o)}),y.find(".dm-countdown").each(function(){const o={autoStart:!0},t=String(this.dataset.format||"").trim(),n=String(this.dataset.to||"").trim(),s=/^(\d{4})-(\d{2})-(\d{2})$/.exec(n),e=s?new Date(+s[1],+s[2]-1,+s[3]).getTime():n?new Date(n).getTime():NaN;Number.isFinite(e)?o.duration=Math.max(0,e-Date.now()):this.dataset.duration&&(o.duration=(parseInt(this.dataset.duration,10)||0)*1e3);const r=/^dd:/i.test(t);o.format=r?"hh:mm:ss":t||(o.duration>=36e5?"hh:mm:ss":"mm:ss");const d=this,h=m=>String(m).padStart(2,"0"),p=m=>{const b=Math.max(0,Math.floor(m/1e3)),c=d.querySelector(".dm-timer-time");c&&(c.textContent=`${h(Math.floor(b/86400))}:${h(Math.floor(b%86400/3600))}:${h(Math.floor(b%3600/60))}:${h(b%60)}`)};r&&(o.onTick=p),Domma.elements.timer(this,o),r&&p(o.duration||0)}),y.find("[data-tooltip]").each(function(){Domma.elements.tooltip(this,{content:$(this).data("tooltip"),position:$(this).data("tooltip-position")||"top"})}),y.find(".dm-progression").each(function(){const o=Array.from(this.querySelectorAll(".dm-progression-item")).map(s=>{const e={title:s.querySelector(".dm-progression-item-title")?.textContent?.trim()||"",description:s.querySelector(".dm-progression-item-body")?.innerHTML?.trim()||""};return s.dataset.date&&(e.date=s.dataset.date),s.dataset.status&&(e.status=s.dataset.status),s.dataset.entryId&&(e._entryId=s.dataset.entryId),e}),t=this.dataset.layout==="centred"?"centered":this.dataset.layout||"vertical",n=Domma.elements.progression(this,{layout:t,theme:this.dataset.theme||"minimal",mode:this.dataset.mode||"timeline",statusIcons:!0,allowHtml:!0,...o.length?{items:o}:{}});o.length&&(this._dmCtx={instance:n,items:o})});try{Domma.effects.reveal(".page-body .hero",{animation:"slide-up",duration:480,threshold:.06,stagger:60,once:!1})}catch{}document.querySelectorAll(".page-body .row[data-reveal]").forEach(o=>{const t=o.dataset.revealMode||"stagger",n=o.dataset.revealAnimation||"slide-up",s=parseInt(o.dataset.revealDuration,10)||400,e=parseInt(o.dataset.revealStagger,10)||60,r=parseInt(o.dataset.revealDelay,10)||0,d=o.dataset.revealDirection==="rtl",h=Array.from(o.children),p={"slide-up":"translateY(30px)","slide-down":"translateY(-30px)","slide-left":"translateX(30px)","slide-right":"translateX(-30px)",zoom:"scale(0.85)",flip:"perspective(600px) rotateX(15deg)"};h.forEach((m,b)=>{m.style.opacity="0",m.style.transform=p[n]||"",m.style.transition=`opacity ${s}ms ease, transform ${s}ms ease`;const c=d?h.length-1-b:b;m.style.transitionDelay=t==="stagger"?`${r+c*e}ms`:`${r}ms`}),requestAnimationFrame(()=>requestAnimationFrame(()=>{const m=new IntersectionObserver(b=>{b.forEach(c=>{c.isIntersecting&&(c.target.offsetWidth,c.target.style.opacity="1",c.target.style.transform="none",m.unobserve(c.target))})},{threshold:.1});h.forEach(b=>m.observe(b))}))}),y.find(".card[data-collapsible]").each(function(){const o=this.querySelector(".card-header");o&&o.addEventListener("click",()=>this.classList.toggle("is-collapsed"))}),y.find(".dm-so-trigger").each(function(){this.addEventListener("click",()=>{const o=this.dataset.soTarget,t=document.getElementById(o);if(!t)return;const n=E.slideover({title:t.dataset.soTitle||"",size:t.dataset.soSize||"md",position:t.dataset.soPosition||"right"});t.style.display="",n.setContent(t),n.open()})})}if(typeof $.setup=="function"){const o=Object.assign({},window.__CMS_DCONFIG__||{});if(document.querySelectorAll(".dm-page-config[data-config]").forEach(t=>{try{const n=N(t.dataset.config);Object.assign(o,n)}catch{}}),Object.keys(o).length>0){const t={};for(const[n,s]of Object.entries(o)){const e=s?.events?.click,{confirm:r,toast:d,alert:h,prompt:p,...m}=e||{};r||d||h||p?($(n).on("click",async function(c){if(c.preventDefault(),r&&!await E.confirm(r))return;let f=null;if(!(p&&(f=await E.prompt(p,{inputPlaceholder:m.promptPlaceholder||"",inputValue:m.promptDefault||""}),f===null))){if(m.target){const i=$(m.target);m.toggleClass&&i.toggleClass(m.toggleClass),m.addClass&&i.addClass(m.addClass),m.removeClass&&i.removeClass(m.removeClass),f!==null&&(m.setText&&i.text(f),m.setVal&&i.val(f),m.setAttr&&i.attr(m.setAttr,f))}m.href&&(window.location.href=m.href),d&&E.toast(d,{type:m.toastType||"success"}),h&&E.alert(h)}}),Object.keys(m).length&&(t[n]={...s,events:{...s.events,click:m}})):t[n]=s}$.setup(t)}}y.length&&I(y.get(0))}),window.wireCTAButtons=I;function I(x){x.querySelectorAll(".dm-cta-trigger").forEach(g=>{g.__ctaWired||(g.__ctaWired=!0,g.addEventListener("click",async()=>{const A=g.dataset.action,w=g.dataset.entry,_=g.dataset.confirm;let y=S.get("auth_token");if(!y){E.toast("Please log in to perform this action.",{type:"warning"});return}if(_&&!await E.confirm(_))return;const o=Array.from(g.childNodes).map(n=>n.cloneNode(!0));g.disabled=!0,g.textContent="Running\u2026";const t=n=>fetch(`/api/actions/${A}/public`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify(g.dataset.scope?{entryId:w,scope:g.dataset.scope}:{entryId:w})});try{let n=await t(y);if(n.status===401){const e=S.get("auth_refresh_token");if(e){const r=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e})});if(r.ok){const{token:d}=await r.json();S.set("auth_token",d),y=d,n=await t(y)}}}const s=await n.json().catch(()=>({}));if(!n.ok)throw new Error(s.error||s.message||`Error ${n.status}`);E.toast(s.message||"Action completed.",{type:"success"})}catch(n){E.toast(n.message||"Action failed.",{type:"error"})}finally{g.disabled=!1,g.textContent="",o.forEach(n=>g.appendChild(n)),Domma.icons.scan(g)}}))})}(function(){const g=document.querySelectorAll('.dm-collection-hydrate[data-collection-scope="mine"]');if(!g.length)return;const A=S.get("auth_token");function w(y,o){const t=document.createElement("div");t.className="dm-collection-display dm-collection-empty";const n=document.createElement("p");if(o){n.appendChild(document.createTextNode("Please "));const s=document.createElement("a");s.href="/login",s.textContent="sign in",n.appendChild(s),n.appendChild(document.createTextNode(" to view your entries."))}else n.textContent=y;return t.appendChild(n),t}function _(y,o){const t=document.createElement("template");t.innerHTML=o||"",y.replaceWith(t.content)}g.forEach(async y=>{const o=y.dataset.collectionAttrs;if(!o)return;if(!A){y.replaceChildren(w("",!0));return}const t=n=>fetch("/api/collections/render-scope",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify({attrs:o})});try{let n=A,s=await t(n);if(s.status===401){const r=S.get("auth_refresh_token");if(r){const d=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:r})});if(d.ok){const{token:h}=await d.json();S.set("auth_token",h),n=h,s=await t(n)}}}if(!s.ok){const{error:r}=await s.json().catch(()=>({}));y.replaceChildren(w(r||"Unable to load entries.",!1));return}const{html:e}=await s.json();_(y,e),window.DommaCollectionBrowser?.hydrate&&window.DommaCollectionBrowser.hydrate(document)}catch{y.replaceChildren(w("Unable to load entries.",!1))}}),setTimeout(()=>{typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(),typeof Domma<"u"&&Domma.syntax?.scan&&Domma.syntax.scan(),I(document.body)},100)})(),(function(){const g=document.querySelectorAll("[data-collection-table]");!g.length||typeof T>"u"||!T.create||g.forEach(A=>{let w;try{w=N(A.dataset.payload)}catch{return}const{columns:_,rows:y,search:o,sortable:t,exportable:n,pageSize:s,empty:e,ctaConfig:r,slug:d,exportCfg:h}=w;if(!_?.length)return;if(r){const b=_.findIndex(c=>c.key==="_cta");b!==-1&&(_[b]={key:"_cta",title:"",render:(c,f)=>{const i=document.createElement("button");if(i.className=`btn btn-${r.style||"primary"} dm-cta-trigger`,i.dataset.action=r.action||"",r.scope&&(i.dataset.scope=r.scope),i.dataset.entry=f._entryId||"",r.confirm&&(i.dataset.confirm=r.confirm),r.icon){const a=document.createElement("span");a.dataset.icon=r.icon,i.appendChild(a),i.appendChild(document.createTextNode(" "))}return i.appendChild(document.createTextNode(r.label||"Run")),i}})}const p="col-table-"+Math.random().toString(36).slice(2,7),m=document.createElement("div");m.id=p,A.replaceChildren(m),T.create("#"+p,{data:y,columns:_,search:o,sortable:t,exportable:n,pageSize:s,emptyMessage:e}),r&&I(m),A._dmTable={columns:_,rows:y,slug:d,exportCfg:h,render(b){T.create("#"+p,{data:b,columns:_,search:o,sortable:t,exportable:n,pageSize:s,emptyMessage:e}),r&&I(m)}}})})(),(function(){const g=document.querySelectorAll("[data-form-inline]");if(!g.length||typeof F>"u")return;function A(t){const n=t&&t.logic;return!!(n&&(n.visibility||n.requirement))}function w(t,n){const s={};return(t||[]).forEach(e=>{if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const r=e.type==="chooser"||!!(e.variant&&["select","radio","checkbox-group"].includes(e.type)),d=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":r?"chooser":e.type,h={...e.formConfig||{}};h.span==="full"&&n&&(h.span=n);const p={type:d,required:A(e)?!1:e.required,label:e.label,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{hint:e.helper},...e.tooltip&&{tooltip:e.tooltip},...h}};e.minLength!==void 0&&(p.minLength=e.minLength),e.maxLength!==void 0&&(p.maxLength=e.maxLength),e.min!==void 0&&(p.min=e.min),e.max!==void 0&&(p.max=e.max),r&&(e.variant&&(p.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(p.multiple=!0),e.density&&(p.density=e.density),e.columns&&(p.columns=e.columns),e.accent&&(p.accent=e.accent),e.accentStyle&&(p.accentStyle=e.accentStyle),e.glow&&(p.glow=!0),e.glowColour&&(p.glowColour=e.glowColour),e.shadow&&(p.shadow=e.shadow),e.shadowColour&&(p.shadowColour=e.shadowColour)),s[e.name]=p}),s}function _(t){const n={};return(t||[]).forEach(s=>{if(!(!s.name||s.type==="page-break"||s.type==="spacer")&&(s.type==="select"||s.type==="multiselect")&&s.required){const e=(s.options||[])[0];e&&(n[s.name]=typeof e=="object"?e.value:e)}}),n}function y(t,n){(n||[]).forEach(s=>{if(s.type!=="date"||!s.name)return;const e=t.querySelector(`[name="${s.name}"]`);e&&e.type!=="date"&&(e.type="date")})}function o(t,n,s){let e=t.querySelector(".cms-form-message");e||(e=document.createElement("p"),e.className="cms-form-message",t.appendChild(e)),e.textContent=n,e.style.cssText=s?"color:var(--dm-danger);margin-top:.75rem;":"color:var(--dm-success);margin-top:.75rem;"}g.forEach(t=>{let n;try{n=N(t.dataset.formInline)}catch{return}const s=n.fields||[],e=n.settings||{},r=Number(e.columns)===3?3:2,d=e.layout||"grid",h=s.some(i=>i.type==="page-break"),p=async i=>{if(t.dataset.triggerBlocked==="true"){const a=t._formLogicRuntime,l=a&&a.submitBlock?a.submitBlock().reasons:[];o(t,l.join(" ")||"This form cannot be submitted yet.",!0);const u=new Error("Blocked by a form trigger");throw u.formSubmitFailed=!0,u}try{const a=t.querySelector(".fb-form-honeypot"),l=a?.querySelector('input[type="text"]')||null,u=a?.querySelector('[name="_t"]')||null,C=Object.assign({},i);delete C._t,a?.dataset.hpName&&delete C[a.dataset.hpName],l!==null&&(C._hp=l.value),u!==null&&(C._t=u.value);const v=await H.post(`/api/forms/submit/${n.slug}`,C);if(v&&v.error){o(t,v.error,!0);const q=new Error(v.error);throw q.formSubmitFailed=!0,q}if(v?.redirect){window.location.href=v.redirect;return}for(;t.firstChild;)t.removeChild(t.firstChild);o(t,v?.message||e.successMessage||"Thank you for your submission.",!1)}catch(a){throw a.formSubmitFailed||o(t,a.message||"Submission failed. Please try again.",!0),a}},m=Date.now();function b(i){const a=i.querySelector("form");if(!a||a.querySelector(".fb-form-honeypot"))return;const l=document.createElement("div");l.className="fb-form-honeypot",l.setAttribute("aria-hidden","true");const u=document.createElement("input");u.name=a.querySelector('[name="website"]')?"_website":"website",l.dataset.hpName=u.name,u.type="text",u.tabIndex=-1,u.autocomplete="url",u.placeholder="https://",l.appendChild(u);const C=document.createElement("input");C.name="_t",C.type="hidden",C.value=m,l.appendChild(C),a.appendChild(l)}function c(i){if(!window.FormLogicEngine||!s.some(l=>l.logic||Array.isArray(l.triggers)&&l.triggers.length))return null;const a=new window.FormLogicEngine.FormLogicRuntime(n,t,i?{baseValues:i}:void 0);if(a.init(),t._formLogicRuntime=a,t._formLogicObserved)return a;if(t._formLogicObserved=!0,t.parentNode&&typeof MutationObserver<"u"){const l=new MutationObserver(function(u){for(const C of u)for(const v of C.removedNodes)if(v===t||v.nodeType===1&&v.contains&&v.contains(t)){t._formLogicRuntime&&t._formLogicRuntime.destroy(),l.disconnect();return}});l.observe(t.parentNode,{childList:!0,subtree:!1}),t._formLogicObserver=l}return a}let f=!1;if(t.addEventListener("dm-form-end",i=>{const a=i.detail?.validation;if(a&&!a.valid){W(t,a.missing),J(a);return}f||(f=!0,p(i.detail?.values||{}).catch(()=>{}).finally(()=>{f=!1}))}),h&&F.wizard){const i=ee(s,n.title),a=i.map(k=>({title:k.title,description:k.description,fields:w(k.fields,r)})),l=i.map(k=>k.fields);let u=0,C=null,v=null;const q=k=>{const L=window.FormLogicEngine;if(!L||!L.validateFields)return;const z=L.validateFields(t,l[u]||[]);z.valid||(k.preventDefault(),k.stopImmediatePropagation(),W(t,z.missing),J(z))},M=()=>{const k=l[u]||s;ae(t,e),X(t,e,k),y(t,k),V(t,k),e.honeypot!==!1&&b(t),C&&C.destroy(),C=c(v?.getStepData?v.getStepData():void 0),t.querySelectorAll(".wizard-next, .wizard-submit").forEach(L=>L.addEventListener("click",q,!0))};v=F.wizard(t,{schema:{steps:a},layout:d,columns:r,finishText:e.submitText||"Finish",onSubmit:p,onStepChange:k=>{u=k,setTimeout(M,0)}}),t.addEventListener("dm-form-trigger",k=>{if(k.detail?.type!=="goto-step"||!v?.goToStep)return;const L=Number(k.detail.action.step);!Number.isFinite(L)||L<0||L>=a.length||L!==u&&v.goToStep(L)}),Promise.resolve(v).then(M)}else if(F.render){const i=F.render(t,w(s,r),_(s),{submitText:e.submitText||"Submit",layout:d,columns:r,onSubmit:p});Promise.resolve(i).then(function(){te(t,e,d),X(t,e,s),y(t,s),V(t,s),e.honeypot!==!1&&b(t),c()})}}),$(document).on("click",".dm-banner__dismiss",function(){$(this).closest(".dm-banner").remove()})})();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(){"use strict";var
|
|
1
|
+
(function(){"use strict";var o=window.__CMS_THEME_SWITCHER__;if(!o||!Array.isArray(o.themes)||!o.themes.length)return;var E=["top-left","top-right","left-center","right-center","bottom-left","bottom-right"],h=[],u=null;function S(t){if(!t)return o.themes;var e=String(t).split(",").map(function(n){return n.trim()}).filter(Boolean),a=o.themes.filter(function(n){return e.indexOf(n.id)!==-1});return a.length?a:o.themes}function b(t){var e=t.themes||o.themes,a=t.position==="inline",n=E.indexOf(t.position)!==-1?t.position:"right-center",d=n==="left-center"||n==="bottom-left"||n==="top-left",m=n==="bottom-left"||n==="bottom-right",l=n==="top-left"||n==="top-right",y=t.offsetX!=null?t.offsetX:32,x=t.offsetY!=null?t.offsetY:32,f=document.createElement("div");f.className="dm-theme-switcher"+(a?" dm-ts-inline dm-ts-left dm-ts-top":(d?" dm-ts-left":"")+(l?" dm-ts-top":"")),f.setAttribute("role","navigation"),f.setAttribute("aria-label","Theme switcher");var r=document.createElement("button");r.type="button",r.className="dm-ts-trigger",r.setAttribute("data-tooltip","Switch theme"),r.setAttribute("aria-label","Switch theme"),r.setAttribute("aria-haspopup","true"),r.setAttribute("aria-expanded","false");var w=360/e.length;r.style.background="conic-gradient("+e.map(function(s,i){return(s.from||"#888")+" "+(i*w).toFixed(2)+"deg "+((i+1)*w).toFixed(2)+"deg"}).join(", ")+")",r.addEventListener("click",function(){var s=r.getAttribute("aria-expanded")==="true";r.setAttribute("aria-expanded",String(!s))});var p=document.createElement("div");return p.className="dm-ts-options",p.setAttribute("role","menu"),e.forEach(function(s){var i=document.createElement("button");i.type="button",i.className="dm-ts-dot",i.dataset.theme=s.id,i.setAttribute("data-tooltip",s.label),i.setAttribute("aria-label",s.label),i.setAttribute("role","menuitem"),i.style.background="linear-gradient(135deg, "+(s.from||"#888")+", "+(s.to||s.from||"#888")+")",i.addEventListener("click",function(){C(i.dataset.theme)}),p.appendChild(i),h.push(i)}),f.appendChild(r),f.appendChild(p),a||Object.assign(f.style,{right:d?"auto":y+"px",left:d?y+"px":"auto",top:l?x+"px":m?"auto":"50vh",bottom:m?x+"px":"auto",transform:l||m?"none":"translateY(-50%)"}),c(),f}function v(t){var e=(t||document).querySelectorAll("[data-theme-switcher]:not([data-ts-mounted])");Array.prototype.forEach.call(e,function(a){a.setAttribute("data-ts-mounted","");var n=function(m){var l=parseInt(m,10);return isFinite(l)?l:null},d=b({position:a.dataset.position||"inline",offsetX:n(a.dataset.offsetX),offsetY:n(a.dataset.offsetY),themes:S(a.dataset.themes)});d.classList.contains("dm-ts-inline")?a.appendChild(d):document.body.appendChild(d)})}function C(t){u&&(u.set(t),document.body.className=document.body.className.split(" ").filter(function(e){return e.indexOf("dm-custom-")!==0}).join(" "),c())}function c(){if(u){var t=u.get();h.forEach(function(e){e.classList.toggle("active",e.dataset.theme===t)})}}function g(t,e){typeof Domma<"u"&&Domma.theme?t(Domma.theme):e>0&&setTimeout(function(){g(t,e-1)},100)}g(function(t){u=t,t.onChange(c),c()},30),window.CMSThemeSwitcher={scan:v};function A(){o.floating!==!1&&document.body.appendChild(b({position:o.position,offsetX:o.offsetX,offsetY:o.offsetY})),v(document)}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",A):A()})();
|
|
@@ -76,6 +76,7 @@ function sanitisePreset(data) {
|
|
|
76
76
|
navbar: data.navbar !== false,
|
|
77
77
|
footer: data.footer !== false,
|
|
78
78
|
sidebar: data.sidebar === true,
|
|
79
|
+
sidebarSide: data.sidebarSide === 'right' ? 'right' : 'left',
|
|
79
80
|
width: VALID_WIDTHS.has(data.width) ? data.width : 'normal',
|
|
80
81
|
bgColor: data.bgColor && BG_COLOR_RE.test(data.bgColor) ? data.bgColor : '',
|
|
81
82
|
bgImage: typeof data.bgImage === 'string' ? data.bgImage.trim() : '',
|
|
@@ -3596,6 +3596,53 @@ function processSpacerBlocks(markdown) {
|
|
|
3596
3596
|
));
|
|
3597
3597
|
}
|
|
3598
3598
|
|
|
3599
|
+
/**
|
|
3600
|
+
* [theme-switcher] - the site's theme dots, placed by the page.
|
|
3601
|
+
*
|
|
3602
|
+
* Syntax:
|
|
3603
|
+
* [theme-switcher /] inline, where the tag stands
|
|
3604
|
+
* [theme-switcher position="bottom-left" offset-x="24" offset-y="24" /]
|
|
3605
|
+
* [theme-switcher themes="charcoal-dark,charcoal-light" /]
|
|
3606
|
+
*
|
|
3607
|
+
* Supported attributes:
|
|
3608
|
+
* position - inline (default) | top-left | top-right | left-center |
|
|
3609
|
+
* right-center | bottom-left | bottom-right (pinned to the window)
|
|
3610
|
+
* offset-x, offset-y - distance from the window's edges when pinned (0-400 px, default 32)
|
|
3611
|
+
* themes - a comma list narrowing the themes chosen under Appearance >
|
|
3612
|
+
* Theme switcher (the site's list when absent or none match)
|
|
3613
|
+
*
|
|
3614
|
+
* Leaves a slot that public/js/theme-switcher.js mounts. The renderer loads
|
|
3615
|
+
* that script when the slot is present, with the floating switcher off or on,
|
|
3616
|
+
* and a page with the tag shows it instead of the floating one.
|
|
3617
|
+
*
|
|
3618
|
+
* @param {string} markdown
|
|
3619
|
+
* @returns {string}
|
|
3620
|
+
*/
|
|
3621
|
+
export const THEME_SWITCHER_POSITIONS = ['inline', 'top-left', 'top-right', 'left-center', 'right-center', 'bottom-left', 'bottom-right'];
|
|
3622
|
+
|
|
3623
|
+
function processThemeSwitcherBlocks(markdown) {
|
|
3624
|
+
const {scrubbed, restore} = scrubCodeRegions(markdown);
|
|
3625
|
+
return restore(scrubbed.replace(
|
|
3626
|
+
/\[theme-switcher([^\]]*?)\/?\]/gi,
|
|
3627
|
+
(_, attrStr) => {
|
|
3628
|
+
const attrs = parseShortcodeAttrs(attrStr || '');
|
|
3629
|
+
const position = THEME_SWITCHER_POSITIONS.includes(attrs.position) ? attrs.position : 'inline';
|
|
3630
|
+
const offset = (v) => {
|
|
3631
|
+
const n = parseInt(v, 10);
|
|
3632
|
+
return Number.isFinite(n) ? Math.min(400, Math.max(0, n)) : null;
|
|
3633
|
+
};
|
|
3634
|
+
const themes = String(attrs.themes || '').split(',').map(t => t.trim()).filter(t => /^[a-z0-9-]+$/.test(t)).join(',');
|
|
3635
|
+
const data = [`data-theme-switcher="page"`, `data-position="${position}"`];
|
|
3636
|
+
if (position !== 'inline') {
|
|
3637
|
+
if (offset(attrs['offset-x']) !== null) data.push(`data-offset-x="${offset(attrs['offset-x'])}"`);
|
|
3638
|
+
if (offset(attrs['offset-y']) !== null) data.push(`data-offset-y="${offset(attrs['offset-y'])}"`);
|
|
3639
|
+
}
|
|
3640
|
+
if (themes) data.push(`data-themes="${themes}"`);
|
|
3641
|
+
return `<span class="dm-theme-switcher-slot" ${data.join(' ')}></span>`;
|
|
3642
|
+
}
|
|
3643
|
+
));
|
|
3644
|
+
}
|
|
3645
|
+
|
|
3599
3646
|
/**
|
|
3600
3647
|
* Pre-process [center]...[/center] shortcodes before running through marked.
|
|
3601
3648
|
*
|
|
@@ -4423,7 +4470,8 @@ export async function parseMarkdown(raw, opts = {}) {
|
|
|
4423
4470
|
const withTimeline = processTimelineBlocks(withCountdown);
|
|
4424
4471
|
const withListGroup = processListGroupBlocks(withTimeline);
|
|
4425
4472
|
const withSpacer = processSpacerBlocks(withListGroup);
|
|
4426
|
-
const
|
|
4473
|
+
const withSwitcher = processThemeSwitcherBlocks(withSpacer);
|
|
4474
|
+
const withCenter = processCenterBlocks(withSwitcher);
|
|
4427
4475
|
const withIcon = processIconBlocks(withCenter);
|
|
4428
4476
|
const withDemo = processDemoBlocks(withIcon);
|
|
4429
4477
|
const withEmbed = processEmbedBlocks(withDemo);
|
|
@@ -47,6 +47,10 @@ export function renderMenuItemsAsUl(items, currentPath = '') {
|
|
|
47
47
|
if (it && it.type === 'spacer') {
|
|
48
48
|
return `<li class="dm-menu-spacer dm-menu-spacer--${esc(spacerSize(it))}" aria-hidden="true"></li>`;
|
|
49
49
|
}
|
|
50
|
+
// The site's theme dots, mounted by theme-switcher.js.
|
|
51
|
+
if (it && it.type === 'theme-switcher') {
|
|
52
|
+
return '<li class="dm-menu-theme-switcher"><span data-theme-switcher="menu" data-position="inline"></span></li>';
|
|
53
|
+
}
|
|
50
54
|
const href = esc(it.url || '#');
|
|
51
55
|
const text = esc(it.text || '');
|
|
52
56
|
const child = Array.isArray(it.items) && it.items.length ? renderMenuItemsAsUl(it.items, currentPath) : '';
|
package/server/services/menus.js
CHANGED
|
@@ -248,6 +248,21 @@ export function spacerSize(item) {
|
|
|
248
248
|
return SPACER_SIZES.has(item?.size) ? item.size : SPACER_DEFAULT_SIZE;
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
+
// ---------------------------------------------------------------------------
|
|
252
|
+
// Theme switcher items - `{type: 'theme-switcher'}`, the site's theme dots
|
|
253
|
+
// placed among a menu's links. Like a spacer it has no text or url; it shows
|
|
254
|
+
// the themes chosen under Appearance > Theme switcher, whether or not the
|
|
255
|
+
// floating switcher itself is on.
|
|
256
|
+
// ---------------------------------------------------------------------------
|
|
257
|
+
|
|
258
|
+
/** Items that hold no link: they are drawn, not navigated. */
|
|
259
|
+
export const isStructuralItem = (it) => !!it && (it.type === 'separator' || it.type === 'spacer' || it.type === 'theme-switcher');
|
|
260
|
+
|
|
261
|
+
/** True when a menu (at any depth) carries a theme switcher item. */
|
|
262
|
+
export function hasThemeSwitcherItem(items) {
|
|
263
|
+
return (items || []).some(it => it && (it.type === 'theme-switcher' || hasThemeSwitcherItem(it.items)));
|
|
264
|
+
}
|
|
265
|
+
|
|
251
266
|
export const ORIENTATIONS = new Set(['horizontal', 'vertical']);
|
|
252
267
|
export const SIDES = new Set(['left', 'right']);
|
|
253
268
|
|
|
@@ -315,7 +330,7 @@ export async function resolveMenuDecorations(items, opts = {}) {
|
|
|
315
330
|
|
|
316
331
|
async function walk(list) {
|
|
317
332
|
return Promise.all((list || []).map(async (it) => {
|
|
318
|
-
if (!it || it
|
|
333
|
+
if (!it || isStructuralItem(it)) return it;
|
|
319
334
|
const next = {...it};
|
|
320
335
|
if (it.badge && it.badge.countFrom) {
|
|
321
336
|
try {
|
|
@@ -751,6 +766,9 @@ export function validateMenu(menu) {
|
|
|
751
766
|
// Renderers translate them into <hr> / structural breaks.
|
|
752
767
|
if (item && item.type === 'separator') return;
|
|
753
768
|
|
|
769
|
+
// A theme switcher has nothing to point at either.
|
|
770
|
+
if (item && item.type === 'theme-switcher') return;
|
|
771
|
+
|
|
754
772
|
// Spacers are blank room, likewise with nothing to point at.
|
|
755
773
|
if (item && item.type === 'spacer') {
|
|
756
774
|
if (item.size != null && !SPACER_SIZES.has(item.size)) {
|
|
@@ -8,7 +8,7 @@ import {fileURLToPath} from 'url';
|
|
|
8
8
|
import {getConfig} from '../config.js';
|
|
9
9
|
import {getInjectionSnippets} from './plugins.js';
|
|
10
10
|
import {applyTransforms} from './hooks.js';
|
|
11
|
-
import {resolveLocation, resolveMenuDecorations, resolveOverlaysForPage} from './menus.js';
|
|
11
|
+
import {hasThemeSwitcherItem, resolveLocation, resolveMenuDecorations, resolveOverlaysForPage} from './menus.js';
|
|
12
12
|
import {buildMenuNav} from './menuRender.js';
|
|
13
13
|
import {getProjectForPage} from './projects.js';
|
|
14
14
|
import {resolveContextMenusForPage} from './contextMenus.js';
|
|
@@ -77,7 +77,7 @@ function buildSearchAssets() {
|
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
const THEME_SWITCHER_ASSET_V = '
|
|
80
|
+
const THEME_SWITCHER_ASSET_V = '20261011-ts-inline';
|
|
81
81
|
const ANALYTICS_ASSET_V = '20260922-analytics';
|
|
82
82
|
|
|
83
83
|
/**
|
|
@@ -112,11 +112,23 @@ function buildAnalyticsTag() {
|
|
|
112
112
|
* Both render paths need this, the same standing trap buildThemeView() and
|
|
113
113
|
* buildSearchAssets() carry.
|
|
114
114
|
*
|
|
115
|
-
*
|
|
115
|
+
* A switcher is also placed by a `{type: 'theme-switcher'}` menu item or the
|
|
116
|
+
* `[theme-switcher]` tag, which need the script and the theme list even with
|
|
117
|
+
* the floating disc off - so the page's html and its menus are passed in. A
|
|
118
|
+
* page with the tag shows that one instead of the floating disc.
|
|
119
|
+
*
|
|
120
|
+
* @param {object} themeCfg
|
|
121
|
+
* @param {{html?: string, menus?: Array<Array>}} [page] The page's rendered
|
|
122
|
+
* html (body and overlay menus) and the item lists of its navbar and footers
|
|
123
|
+
* @returns {{headTag: string, bodyTag: string}} Empty strings when nothing needs it
|
|
116
124
|
*/
|
|
117
|
-
function buildThemeSwitcherAssets(themeCfg) {
|
|
118
|
-
const sw = themeCfg?.switcher;
|
|
119
|
-
|
|
125
|
+
function buildThemeSwitcherAssets(themeCfg, page = {}) {
|
|
126
|
+
const sw = themeCfg?.switcher || {};
|
|
127
|
+
const html = page.html || '';
|
|
128
|
+
const pageTag = html.includes('data-theme-switcher="page"');
|
|
129
|
+
const inMenu = html.includes('data-theme-switcher="menu"') || (page.menus || []).some(hasThemeSwitcherItem);
|
|
130
|
+
const floating = sw.enabled === true && !pageTag;
|
|
131
|
+
if (!floating && !pageTag && !inMenu) return {headTag: '', bodyTag: ''};
|
|
120
132
|
|
|
121
133
|
let ids;
|
|
122
134
|
try {
|
|
@@ -140,6 +152,7 @@ function buildThemeSwitcherAssets(themeCfg) {
|
|
|
140
152
|
});
|
|
141
153
|
|
|
142
154
|
const payload = {
|
|
155
|
+
floating,
|
|
143
156
|
position: sw.position || 'right-center',
|
|
144
157
|
offsetX: sw.offsetX ?? 32,
|
|
145
158
|
offsetY: sw.offsetY ?? 32,
|
|
@@ -321,7 +334,10 @@ export async function renderPage(page, opts = {}) {
|
|
|
321
334
|
|
|
322
335
|
const themeView = await buildThemeView(page);
|
|
323
336
|
const searchAssets = buildSearchAssets();
|
|
324
|
-
const switcherAssets = buildThemeSwitcherAssets(themeView.cfg
|
|
337
|
+
const switcherAssets = buildThemeSwitcherAssets(themeView.cfg, {
|
|
338
|
+
html: `${page.html || ''}${overlayMenus}`,
|
|
339
|
+
menus: [navItemsDecorated, footerPrimaryDecorated, footerLegalDecorated]
|
|
340
|
+
});
|
|
325
341
|
const {fontLink, fontStyleTag, autoTheme, activeTheme, dommaTheme, customThemeClass} = themeView;
|
|
326
342
|
|
|
327
343
|
const {navbarFontLink, navbarStyleTag} = buildNavbarStyleTag(navigation);
|
|
@@ -391,6 +407,7 @@ export async function renderPage(page, opts = {}) {
|
|
|
391
407
|
showNavbar: preset.navbar !== false,
|
|
392
408
|
showFooter: preset.footer !== false,
|
|
393
409
|
showSidebar: preset.sidebar === true || page.sidebar === true,
|
|
410
|
+
sidebarRight: (page.sidebarSide || preset.sidebarSide) === 'right',
|
|
394
411
|
navJson: JSON.stringify(filterHiddenNavItems(navigation)).replace(/<\/script>/gi, '<\\/script>'),
|
|
395
412
|
footerScript: footerJson ? `window.__CMS_FOOTER__ = ${footerJson};` : '',
|
|
396
413
|
ctxMenusScript: ctxMenusScript,
|
|
@@ -1042,7 +1059,10 @@ export async function renderBlogPage(templatePath, data = {}, seoMeta = {}) {
|
|
|
1042
1059
|
// other is the standing trap in this file.
|
|
1043
1060
|
const themeView = await buildThemeView({});
|
|
1044
1061
|
const searchAssets = buildSearchAssets();
|
|
1045
|
-
const switcherAssets = buildThemeSwitcherAssets(themeView.cfg
|
|
1062
|
+
const switcherAssets = buildThemeSwitcherAssets(themeView.cfg, {
|
|
1063
|
+
html: `${renderedFragment || ''}${overlayMenus}`,
|
|
1064
|
+
menus: [navItemsDecorated, footerPrimaryDecorated, footerLegalDecorated]
|
|
1065
|
+
});
|
|
1046
1066
|
const {fontLink, fontStyleTag, activeTheme, dommaTheme, customThemeClass} = themeView;
|
|
1047
1067
|
const {navbarFontLink, navbarStyleTag} = buildNavbarStyleTag(navigation);
|
|
1048
1068
|
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
<link rel="stylesheet" href="/dist/domma/themes/domma-themes.css">
|
|
26
26
|
|
|
27
27
|
<!-- Site CSS -->
|
|
28
|
-
<link rel="stylesheet" href="/public/css/site.css?v=
|
|
28
|
+
<link rel="stylesheet" href="/public/css/site.css?v=20261011-sidebar-right">
|
|
29
29
|
<link rel="stylesheet" href="/public/css/forms.css?v=20260927-submit-btn-css">
|
|
30
30
|
<!-- Menu item hover / current-page effects. Loaded after site.css so a
|
|
31
31
|
menu's own highlight wins over the blanket link styling there. -->
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
<nav id="site-navbar" class="{{navbarClass}}"></nav>
|
|
47
47
|
{{/if}}
|
|
48
48
|
|
|
49
|
-
<main class="site-main {{#if showSidebar}}with-sidebar{{/if}}">
|
|
49
|
+
<main class="site-main {{#if showSidebar}}with-sidebar{{/if}} {{#if sidebarRight}}sidebar-right{{/if}}">
|
|
50
50
|
{{#if showSidebar}}
|
|
51
51
|
<aside id="site-sidebar" class="site-sidebar"></aside>
|
|
52
52
|
{{/if}}
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
</script>
|
|
138
138
|
|
|
139
139
|
<!-- Site initialisation -->
|
|
140
|
-
<script src="/public/js/site.js?v=
|
|
140
|
+
<script src="/public/js/site.js?v=20261011-theme-switcher-item" type="module"></script>
|
|
141
141
|
<script src="/public/js/collection-context.js?v=20261010-utf8-payloads" type="module"></script>
|
|
142
142
|
{{ctxMenusModule}}
|
|
143
143
|
|