domma-cms 1.6.16 → 1.6.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/admin/dist/domma/domma-tools.css +3 -3
- package/admin/dist/domma/domma-tools.min.js +3 -3
- package/admin/js/lib/effects-builder.js +2 -2
- package/admin/js/lib/page-editor-reference.js +3 -3
- package/admin/js/lib/scribe-composer.js +1 -1
- package/admin/js/lib/scribe-model.js +1 -1
- package/admin/js/lib/site-settings-arrange.js +1 -1
- package/admin/js/templates/effects.html +10 -4
- package/admin/js/templates/settings.html +14 -0
- package/package.json +2 -2
- package/public/css/site.css +1 -1
- package/public/js/effects.js +1 -1
- package/public/js/site.js +1 -1
- package/server/services/markdown.js +1 -1
- package/server/templates/page.html +3 -3
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Domma Tools CSS v0.51.
|
|
2
|
+
* Domma Tools CSS v0.51.9
|
|
3
3
|
* Dynamic Object Manipulation & Modeling API
|
|
4
4
|
* (c) 2026 Darryl Waterhouse & DCBW-IT
|
|
5
|
-
* Built: 2026-10-
|
|
6
|
-
* Commit:
|
|
5
|
+
* Built: 2026-10-11T10:14:37.692Z
|
|
6
|
+
* Commit: c708495
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
/*!
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Domma Tools v0.51.
|
|
2
|
+
* Domma Tools v0.51.9
|
|
3
3
|
* Developer tools: Theme Roller & Page Roller
|
|
4
4
|
* (c) 2026 Darryl Waterhouse & DCBW-IT
|
|
5
|
-
* Built: 2026-10-
|
|
6
|
-
* Commit:
|
|
5
|
+
* Built: 2026-10-11T10:14:22.712Z
|
|
6
|
+
* Commit: c708495
|
|
7
7
|
*
|
|
8
8
|
* Requires: domma.min.js
|
|
9
9
|
*/
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{EFFECTS as
|
|
1
|
+
import{EFFECTS as R,effectsByCategory as L,effectsInjectableInto as j,getEffect as u,getEffectAttrs as g}from"./effect-defs.js";import{scribeLoop as O}from"./scribe-model.js";import{insertAtCursor as N,replaceRange as C}from"./markdown-toolbar.js";let h=null,x=null;function B(e,t,n=14){e.textContent="";const o=document.createElement("span");return o.setAttribute("data-icon",t),o.setAttribute("data-icon-size",String(n)),o.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;",e.appendChild(o),I.scan(e),e}function q(e,t,n,o=14){return B(e,t,o),e.appendChild(document.createTextNode(" "+n)),e}export const EffectsBuilder={open(e){if(h)return;const t={textarea:e,activeEffect:S.get("effects-builder-last")||"reveal",scope:"standalone",host:null,editing:null,fieldValues:{}};if(t.host=M(e),t.host&&j(t.host.name).map(r=>r.name).includes(t.activeEffect)&&!(t.activeEffect in t.host.attrs)&&(t.scope="inject"),t.editing=H(e),t.editing){t.activeEffect=t.editing.name,t.scope="standalone";const l=u(t.editing.name);for(const r of g(l,t.fieldValues))if(r.name in t.editing.attrs){const s=t.editing.attrs[r.name];r.type==="number"?t.fieldValues[r.name]=Number(s):r.type==="checkbox"?t.fieldValues[r.name]=s==="true":t.fieldValues[r.name]=s}}const n=E.slideover({title:"Effects",size:"lg",position:"right",onClose:()=>{x?.destroy(),x=null,h=null}}),o=P(t,n);n.element.appendChild(o),n.open(),I.scan(o),h={state:t,slideover:n}},close(){h&&(h.slideover.close(),h=null)}};function P(e,t){const n=document.createElement("div");n.style.cssText="display:grid;grid-template-columns:170px 1fr;height:100%;min-height:520px;";const o=document.createElement("div");o.className="effects-rail",o.style.cssText="background:var(--dm-background-alt,#15152a);border-right:1px solid var(--dm-border,#2a2a40);padding:.5rem .35rem;font-size:.8rem;overflow-y:auto;";const l=document.createElement("div");l.className="effects-pane",l.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;overflow-y:auto;";function r(){W(l,e,t)}return k(o,e,r),r(),n.appendChild(o),n.appendChild(l),n}function k(e,t,n){e.replaceChildren();for(const o of L()){const l=document.createElement("div");l.style.cssText="color:var(--dm-text-muted,#888);text-transform:uppercase;font-size:.65rem;letter-spacing:.05em;margin:.4rem .35rem .25rem;",l.textContent=o.category,e.appendChild(l);for(const r of o.effects){const s=document.createElement("button");s.type="button",s.dataset.effect=r.name,s.style.cssText="display:block;width:100%;text-align:left;padding:.3rem .5rem;border:none;background:transparent;color:var(--dm-text,#ddd);border-radius:3px;font-size:.8rem;cursor:pointer;margin-bottom:.1rem;",s.textContent=r.label,r.name===t.activeEffect&&(s.style.background="var(--dm-primary,#4338ca)",s.style.color="var(--dm-primary-text,#fff)"),s.addEventListener("click",()=>{t.activeEffect=r.name,S.set("effects-builder-last",r.name),t.fieldValues={},k(e,t,n),n()}),e.appendChild(s)}}}function F(e,t){if(e.type==="select"){const o=document.createElement("select");o.style.cssText="width:100%;padding:.35rem .5rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:3px;color:var(--dm-text,#eee);font-size:.85rem;";for(const[l,r]of e.options){const s=document.createElement("option");s.value=l,s.textContent=r,o.appendChild(s)}return o.value=t??e.default??"",o}if(e.type==="checkbox"){const o=document.createElement("input");return o.type="checkbox",o.checked=t??e.default??!1,o}const n=document.createElement("input");return n.type=e.type==="number"?"number":e.type==="colour"?"color":"text",n.value=t??e.default??"",e.placeholder&&(n.placeholder=e.placeholder),e.type==="number"&&(e.min!=null&&(n.min=e.min),e.max!=null&&(n.max=e.max),e.step!=null&&(n.step=e.step)),n.style.cssText="width:100%;padding:.35rem .5rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:3px;color:var(--dm-text,#eee);font-size:.85rem;",n}function T(e,t){return t.type==="checkbox"?e.checked:t.type==="number"?e.value===""?"":Number(e.value):e.value}function v(e,t,n){const o=u(t.activeEffect);if(e.replaceChildren(),o.attrs.length===0){const r=document.createElement("div");r.style.cssText="color:var(--dm-text-muted,#888);font-size:.8rem;font-style:italic;",r.textContent="This effect takes no parameters.",e.appendChild(r);return}const l=document.createElement("div");l.style.cssText="display:grid;grid-template-columns:1fr 1fr;gap:.6rem .7rem;";for(const r of g(o,t.fieldValues)){const s=document.createElement("div"),d=document.createElement("label");d.style.cssText="display:block;color:var(--dm-text-muted,#888);font-size:.7rem;text-transform:uppercase;letter-spacing:.05em;margin-bottom:.2rem;",d.textContent=r.label,s.appendChild(d);const i=F(r,t.fieldValues[r.name]);if(i.addEventListener("input",()=>{t.fieldValues[r.name]=T(i,r),n(),r.name==="theme"&&v(e,t,n)}),i.addEventListener("change",()=>{t.fieldValues[r.name]=T(i,r),n(),r.name==="theme"&&v(e,t,n)}),s.appendChild(i),r.hint){const c=document.createElement("div");c.style.cssText="color:var(--dm-text-muted,#666);font-size:.7rem;margin-top:.15rem;",c.textContent=r.hint,s.appendChild(c)}l.appendChild(s)}e.appendChild(l)}function $(e){const t={},n=/(\w[\w-]*)(?:\s*=\s*"([^"]*)"|\s*=\s*'([^']*)'|\s*=\s*(\S+))?/g;for(const o of e.matchAll(n)){const l=o[1],r=o[2]??o[3]??o[4]??"";t[l]=r}return t}const D=R.filter(e=>!e.selfClosing).map(e=>e.name);function H(e){const t=e.value,n=e.selectionStart;for(const o of D){const l=new RegExp(`\\[${o}([^\\]]*)\\]`,"g"),r=new RegExp(`\\[/${o}\\]`,"g"),s=[];for(const c of t.matchAll(l)){if(c.index>=n)break;s.push({type:"open",start:c.index,end:c.index+c[0].length,attrStr:c[1]})}for(const c of t.matchAll(r)){if(c.index>=n)break;s.push({type:"close",start:c.index,end:c.index+c[0].length})}s.sort((c,a)=>c.start-a.start);let d=0,i=null;for(const c of s)c.type==="open"?(d++,i=c):(d--,d<0&&(d=0,i=null));if(d>0&&i){const c=new RegExp(`\\[/${o}\\]`,"g"),a=t.slice(n),m=a.match(c);if(m){const f=n+a.indexOf(m[0]);return{name:o,blockStart:i.start,blockEnd:f+m[0].length,openTagEnd:i.end,attrs:$(i.attrStr)}}}}return null}const K=["card","box","hero","banner","col","button"];function M(e){const t=e.value,n=e.selectionStart;for(const o of K){const l=new RegExp(`\\[${o}([^\\]]*)\\]`,"g"),r=new RegExp(`\\[/${o}\\]`,"g"),s=[];for(const c of t.matchAll(l)){if(c.index>=n)break;s.push({type:"open",start:c.index,end:c.index+c[0].length,attrStr:c[1]})}for(const c of t.matchAll(r)){if(c.index>=n)break;s.push({type:"close",start:c.index,end:c.index+c[0].length})}s.sort((c,a)=>c.start-a.start);let d=0,i=null;for(const c of s)c.type==="open"?(d++,i=c):(d--,d<0&&(d=0,i=null));if(d>0&&i){const c=new RegExp(`\\[/${o}\\]`,"g"),a=t.slice(n),m=a.match(c);if(m){const f=n+a.indexOf(m[0]);return{name:o,openTagStart:i.start,openTagEnd:i.end,closeTagStart:f,closeTagEnd:f+m[0].length,attrs:$(i.attrStr)}}}}return null}function w(e,t){const n=[];for(const o of g(t,e.fieldValues)){const l=e.fieldValues[o.name];l===void 0||l===""||l===null||l===o.default&&!o.always||(o.type==="checkbox"?n.push(`${o.name}="${l?"true":"false"}"`):n.push(`${o.name}="${String(l).replace(/"/g,""")}"`))}return n.join(" ")}function _(e){const t=u(e.activeEffect),n=w(e,t),o=n?" ":"";if(e.scope==="inject"&&e.host){const l=e.host.attrs,r=t.name,s=[];for(const d of Object.keys(l)){if(d===r||d.startsWith(r+"-"))continue;const i=l[d];s.push(i===""?d:`${d}="${String(i).replace(/"/g,""")}"`)}s.push(r);for(const d of g(t,e.fieldValues)){const i=e.fieldValues[d.name];if(i===void 0||i===""||i===null||i===d.default)continue;const c=d.type==="checkbox"?i?"true":"false":String(i).replace(/"/g,""");s.push(`${r}-${d.name}="${c}"`)}return`[${e.host.name} ${s.join(" ")}]\u2026[/${e.host.name}]`}return t.selfClosing?`[${t.name}${o}${n} /]`:`[${t.name}${o}${n}]
|
|
2
2
|
Content
|
|
3
|
-
[/${t.name}]`}function
|
|
3
|
+
[/${t.name}]`}function z(e,t){e.replaceChildren();const n=document.createElement("div");n.style.cssText="color:var(--dm-text-muted,#888);font-size:.7rem;text-transform:uppercase;letter-spacing:.05em;margin-bottom:.25rem;",n.textContent="Shortcode (live)",e.appendChild(n);const o=document.createElement("pre");o.style.cssText="background:var(--dm-code-bg,#000);border:1px solid var(--dm-border,#333);padding:.5rem .65rem;border-radius:3px;font-family:var(--dm-font-mono,monospace);font-size:.75rem;color:var(--dm-code-text,#7c6af7);line-height:1.5;white-space:pre-wrap;word-break:break-all;margin:0;",o.textContent=_(t),e.appendChild(o)}function U(e,t,n){if(e.replaceChildren(),t.editing)return;const o=u(t.activeEffect),l=t.host&&o.hosts.includes(t.host.name),r=document.createElement("div");r.style.cssText="background:var(--dm-background-alt,#15152a);border:1px solid var(--dm-border,#2a2a40);border-radius:4px;padding:.5rem .6rem;";const s=document.createElement("div");if(s.style.cssText="color:var(--dm-text-muted,#888);text-transform:uppercase;font-size:.65rem;letter-spacing:.05em;margin-bottom:.3rem;",s.textContent="Apply as",r.appendChild(s),!l){const c=document.createElement("div");c.style.cssText="color:var(--dm-text-muted,#888);font-size:.75rem;font-style:italic;",t.host?c.textContent=`Inserted as a standalone block (${o.label} cannot be injected into [${t.host.name}]).`:c.textContent="Inserted as a standalone block.",r.appendChild(c),e.appendChild(r),t.scope="standalone";return}const d=document.createElement("div");d.style.cssText="display:flex;gap:.3rem;";function i(c,a){const m=document.createElement("button");return m.type="button",m.style.cssText="flex:1;padding:.35rem;border:1px solid var(--dm-border,#333);border-radius:3px;font-size:.75rem;font-weight:600;cursor:pointer;",t.scope===c?(m.style.background="var(--dm-primary,#4338ca)",m.style.color="var(--dm-primary-text,#fff)",m.style.borderColor="var(--dm-primary,#4338ca)"):(m.style.background="transparent",m.style.color="var(--dm-text-muted,#bbb)"),m.textContent=a,m.addEventListener("click",()=>{t.scope=c,n()}),m}d.appendChild(i("standalone","Standalone block")),d.appendChild(i("inject",`Inject into [${t.host.name}]`)),r.appendChild(d),e.appendChild(r)}let y=0;function A(e){return e.replace(/-([a-z])/g,(t,n)=>n.toUpperCase())}function V(e,t){e.replaceChildren();const n=u(t.activeEffect),o=document.createElement("div");o.style.cssText="display:flex;justify-content:space-between;align-items:center;margin-bottom:.25rem;";const l=document.createElement("div");if(l.style.cssText="color:var(--dm-text-muted,#888);text-transform:uppercase;font-size:.65rem;letter-spacing:.05em;",l.textContent="Live preview",o.appendChild(l),!n.previewable){const i=document.createElement("div");i.style.cssText="background:var(--dm-background-alt,#15152a);border:1px solid var(--dm-border,#2a2a40);border-radius:4px;padding:.6rem;color:var(--dm-text-muted,#888);font-size:.8rem;font-style:italic;text-align:center;",i.textContent="Runs full-page on the published site - no inline preview.",e.appendChild(i);return}const r=document.createElement("button");r.type="button",r.style.cssText="background:transparent;border:1px solid var(--dm-border,#333);color:var(--dm-text-muted,#888);font-size:.65rem;padding:.15rem .4rem;border-radius:2px;cursor:pointer;",q(r,"refresh-cw","Replay",12),o.appendChild(r),e.appendChild(o);const s=document.createElement("div");s.style.cssText="background:var(--dm-background-alt,#1a1a2e);border:1px solid var(--dm-border,#2a2a40);border-radius:4px;padding:1rem;text-align:center;min-height:80px;position:relative;overflow:hidden;",e.appendChild(s);function d(i=!1){x?.destroy(),x=null,y++;const c=y;s.replaceChildren();const a=document.createElement("div");a.style.cssText="background:linear-gradient(135deg,#6366f1,#a855f7);color:#fff;padding:.6rem;border-radius:4px;font-size:.8rem;font-weight:600;",a.textContent="Sample content",s.appendChild(a);const m=window.Domma&&window.Domma.effects;if(!m)return;const f={};for(const p of g(n,t.fieldValues)){const b=t.fieldValues[p.name];b===void 0||b===""||b===null||(f[A(p.name)]=b)}n.name==="scribe"&&(f.loop=O(f.loop??!1),f.actions=[{render:a.textContent,effect:f.effect||"none"}],a.textContent="");try{const p=m[A(n.name)];if(typeof p=="function"){if(c!==y)return;x=p(a,f),i&&x?.resume()}}catch(p){console.warn("Effects preview failed:",p)}}r.addEventListener("click",()=>d(!0)),d()}function W(e,t,n){const o=u(t.activeEffect);e.replaceChildren();const l=document.createElement("h3");l.style.cssText="margin:0;font-size:1rem;color:var(--dm-text,#eee);",l.textContent=o.label,e.appendChild(l);const r=document.createElement("p");r.style.cssText="margin:0;color:var(--dm-text-muted,#999);font-size:.8rem;line-height:1.4;",r.textContent=o.description,e.appendChild(r);const s=document.createElement("div");e.appendChild(s);const d=document.createElement("div");e.appendChild(d);const i=document.createElement("div");e.appendChild(i);const c=document.createElement("div");e.appendChild(c);function a(){U(s,t,a),v(d,t,()=>{z(i,t),V(c,t)}),z(i,t),V(c,t)}a();const m=document.createElement("div");m.style.cssText="display:flex;gap:.5rem;margin-top:auto;padding-top:.75rem;border-top:1px solid var(--dm-border,#2a2a40);";const f=document.createElement("button");f.type="button",f.className="btn btn-ghost",f.textContent="Cancel",f.addEventListener("click",()=>n.close()),m.appendChild(f);const p=document.createElement("button");p.type="button",p.className="btn btn-primary",p.style.flex="2",p.textContent=t.editing?"Update":"Insert effect",p.addEventListener("click",()=>X(t,n)),m.appendChild(p),e.appendChild(m)}function X(e,t){const n=e.textarea,o=_(e);if(e.editing){const l=u(e.editing.name),r=n.value,s=`[/${l.name}]`.length,d=e.editing.openTagEnd,i=e.editing.blockEnd-s,c=r.substring(d,i),a=w(e,l),m=a?" ":"",f=l.selfClosing?`[${l.name}${m}${a} /]`:`[${l.name}${m}${a}]${c}[/${l.name}]`;C(n,e.editing.blockStart,e.editing.blockEnd,f);const p=l.selfClosing?e.editing.blockStart+f.length:e.editing.blockStart+f.indexOf("]")+1;n.setSelectionRange(p,p),t.close();return}if(e.scope==="inject"&&e.host){const l=u(e.activeEffect),r=e.host.attrs,s=l.name,d=[];for(const c of Object.keys(r)){if(c===s||c.startsWith(s+"-"))continue;const a=r[c];d.push(a===""?c:`${c}="${String(a).replace(/"/g,""")}"`)}d.push(s);for(const c of g(l,e.fieldValues)){const a=e.fieldValues[c.name];if(a===void 0||a===""||a===null||a===c.default)continue;const m=c.type==="checkbox"?a?"true":"false":String(a).replace(/"/g,""");d.push(`${s}-${c.name}="${m}"`)}const i=`[${e.host.name} ${d.join(" ")}]`;C(n,e.host.openTagStart,e.host.openTagEnd,i),t.close();return}N(n,o),t.close()}
|
|
@@ -89,7 +89,7 @@ In active development.
|
|
|
89
89
|
[/table]`,"The inner content must be a valid GFM Markdown table. The shortcode adds Domma CSS classes and wraps in a responsive scroll container.")]}),t("Slideover",{intro:"A trigger button that opens a slide-in panel with Markdown content. No plugin required.",rows:[['title="..."',"Panel header text"],['trigger="..."','Button label (default: "Open")'],['size="sm|md|lg"',"Panel width (default: md)"],['position="right|left"',"Slide direction (default: right)"]],examples:[e("Example",`[slideover title="More Info" trigger="Read more" size="md"]
|
|
90
90
|
## Details
|
|
91
91
|
Markdown content here.
|
|
92
|
-
[/slideover]`,"Nested [card] and [grid] shortcodes work inside the slideover body.")]})],b=[t("Embedding a Form",{rows:[['name="..."',"Form slug (required). Also accepted as slug=."],['class="..."',"Extra CSS classes on the wrapper div"],['id="..."',"id attribute on the wrapper div"]],examples:[e("Basic",'[form name="contact" /]',"Forms are managed under Forms in the sidebar."),e("With wrapper styling",'[form name="newsletter" class="mt-4" id="newsletter-form" /]')]}),t("Displaying a Collection",{block:'[collection slug="enquiries" display="table" /]',rows:[["slug","Required. The collection slug."],["display","table (default), cards, or list."],["fields","Comma-separated field keys to show. Defaults to all."],["limit","Maximum number of entries to display."],["sort","Field key to sort by."],["order","asc or desc (default asc)."],["title-field","Field used as the card/list title (cards + list)."],["columns","Grid columns for cards display (2-4, default 3)."],["search","true/false - enable search in table mode (default true)."],["sortable","true/false - enable column sorting in table mode (default true)."],["exportable","true/false - show CSV export button in table mode (default false)."],["page-size","Rows per page in table mode (default 25)."],["empty","Text shown when there are no entries."],["cta","Action slug: enables per-entry CTA buttons."],["cta-label",'CTA button label (default: "Run").'],["cta-icon","CTA button icon name."],["cta-style","CTA button variant (default: primary)."],["cta-confirm","CTA confirmation prompt text."],["class","Extra CSS classes on the wrapper div."],["id","id attribute on the wrapper div."]],outro:"Table display uses Domma Table - search, sort, pagination, column selector, and CSV export are all built in. Cards and lists are static."}),t("View - Pro",{intro:"Renders a Collection with full filtering, pagination, and display options. Requires a Pro MongoDB collection.",rows:[["slug","Required. The collection slug."],["display","table (default), cards, or list."],["limit","Maximum number of entries to display."],["fields","Comma-separated field keys to show."],["title-field","Field used as the card/list title."],["columns","Grid columns for cards display (2-4, default 3)."],["empty","Text shown when there are no entries."],["class","Extra CSS classes on the wrapper div."],["id","id attribute on the wrapper div."]],examples:[e("Table display",'[view slug="products" display="table" limit="50" /]'),e("Cards display",'[view slug="team" display="cards" columns="3" title-field="name" /]')]}),t("CTA - Pro",{intro:"Renders an action button that triggers a Pro Action against an entry. Requires the Pro Actions feature.",rows:[["action","Required. The action slug."],["entry","Required. The entry id to act on."],["style","Button variant (default: primary)."],["icon","Domma icon name for the button."],["size","Button size (sm, lg)."],["confirm","Confirmation prompt text before running."],["label","Self-closing only: button label text."]],examples:[e("Wrapping form",'[cta action="approve" entry="abc123" style="success" confirm="Approve this entry?"]Approve[/cta]'),e("Self-closing",'[cta action="archive" entry="abc123" icon="archive" label="Archive" /]')]})],f=[t("Effects",{intro:"Shortcodes for scroll-triggered animations, counters, typewriter text, and more. Requires the Domma Effects plugin.",rows:[['[reveal animation="fade"]...[/reveal]',"Fade/slide/zoom on scroll"],["[breathe]...[/breathe]","Continuous gentle scale loop"],["[pulse]...[/pulse]","Repeating scale pulse"],["[shake]...[/shake]","One-shot shake"],['[scribe speed="
|
|
92
|
+
[/slideover]`,"Nested [card] and [grid] shortcodes work inside the slideover body.")]})],b=[t("Embedding a Form",{rows:[['name="..."',"Form slug (required). Also accepted as slug=."],['class="..."',"Extra CSS classes on the wrapper div"],['id="..."',"id attribute on the wrapper div"]],examples:[e("Basic",'[form name="contact" /]',"Forms are managed under Forms in the sidebar."),e("With wrapper styling",'[form name="newsletter" class="mt-4" id="newsletter-form" /]')]}),t("Displaying a Collection",{block:'[collection slug="enquiries" display="table" /]',rows:[["slug","Required. The collection slug."],["display","table (default), cards, or list."],["fields","Comma-separated field keys to show. Defaults to all."],["limit","Maximum number of entries to display."],["sort","Field key to sort by."],["order","asc or desc (default asc)."],["title-field","Field used as the card/list title (cards + list)."],["columns","Grid columns for cards display (2-4, default 3)."],["search","true/false - enable search in table mode (default true)."],["sortable","true/false - enable column sorting in table mode (default true)."],["exportable","true/false - show CSV export button in table mode (default false)."],["page-size","Rows per page in table mode (default 25)."],["empty","Text shown when there are no entries."],["cta","Action slug: enables per-entry CTA buttons."],["cta-label",'CTA button label (default: "Run").'],["cta-icon","CTA button icon name."],["cta-style","CTA button variant (default: primary)."],["cta-confirm","CTA confirmation prompt text."],["class","Extra CSS classes on the wrapper div."],["id","id attribute on the wrapper div."]],outro:"Table display uses Domma Table - search, sort, pagination, column selector, and CSV export are all built in. Cards and lists are static."}),t("View - Pro",{intro:"Renders a Collection with full filtering, pagination, and display options. Requires a Pro MongoDB collection.",rows:[["slug","Required. The collection slug."],["display","table (default), cards, or list."],["limit","Maximum number of entries to display."],["fields","Comma-separated field keys to show."],["title-field","Field used as the card/list title."],["columns","Grid columns for cards display (2-4, default 3)."],["empty","Text shown when there are no entries."],["class","Extra CSS classes on the wrapper div."],["id","id attribute on the wrapper div."]],examples:[e("Table display",'[view slug="products" display="table" limit="50" /]'),e("Cards display",'[view slug="team" display="cards" columns="3" title-field="name" /]')]}),t("CTA - Pro",{intro:"Renders an action button that triggers a Pro Action against an entry. Requires the Pro Actions feature.",rows:[["action","Required. The action slug."],["entry","Required. The entry id to act on."],["style","Button variant (default: primary)."],["icon","Domma icon name for the button."],["size","Button size (sm, lg)."],["confirm","Confirmation prompt text before running."],["label","Self-closing only: button label text."]],examples:[e("Wrapping form",'[cta action="approve" entry="abc123" style="success" confirm="Approve this entry?"]Approve[/cta]'),e("Self-closing",'[cta action="archive" entry="abc123" icon="archive" label="Archive" /]')]})],f=[t("Effects",{intro:"Shortcodes for scroll-triggered animations, counters, typewriter text, and more. Requires the Domma Effects plugin.",rows:[['[reveal animation="fade"]...[/reveal]',"Fade/slide/zoom on scroll"],["[breathe]...[/breathe]","Continuous gentle scale loop"],["[pulse]...[/pulse]","Repeating scale pulse"],["[shake]...[/shake]","One-shot shake"],['[scribe mode="word" effect="bounce" speed="140" loop="3" cursor-blink="false" controls="true"]...[/scribe]',"Scribe - characters, words, or sentences; effects, counted loops, cursor and playback settings"],['[scribe loop="true"][render]Text[/render][wait]1500[/wait][undo /][/scribe]',"Typewriter - script mode (sequenced render/wait/undo actions)"],["[scramble]...[/scramble]","Character-scramble reveal"],['[counter to="100" /]',"Animated number counter (self-closing)"],["[ripple]...[/ripple]","Click-triggered ripple"],['[twinkle count="50"]...[/twinkle]',"Particle/star overlay"],['[animate type="fade-in-up"]...[/animate]',"CSS-only animation (no plugin needed)"],['[ambient type="aurora"]...[/ambient]',"CSS-only animated background"],['[firework type="burst" colour="rainbow" /]',"CSS firework (self-closing)"],["[fireworks]...[/fireworks]","Fireworks display container"],['[celebrate theme="auto" /]',"Seasonal canvas celebration (auto-detects date)"],["[christmas /]","Christmas - snowflakes, trees, snowmen, sleigh"],["[halloween /]","Halloween - pumpkins, ghosts, bats, spiders"],["[st-patricks /]","St Patrick's Day - shamrocks, coins, rainbows, leprechaun"],["[valentines /]","Valentine's Day - hearts, roses"],["[guy-fawkes /]","Guy Fawkes - fireworks, sparkles"],["[st-andrews /]","St Andrew's Day - heather, thistles"],["[st-davids /]","St David's Day - daffodils, dragons"],["[st-georges /]","St George's Day - roses, flags"]],examples:[e("Scribe script - looping multi-phrase typewriter",`[scribe loop="true" loop-delay="2000" delete-speed="20"]
|
|
93
93
|
[render]We build things that matter.[/render]
|
|
94
94
|
[wait]1200[/wait]
|
|
95
95
|
[undo all="true" /]
|
|
@@ -98,7 +98,7 @@ Markdown content here.
|
|
|
98
98
|
[undo all="true" /]
|
|
99
99
|
[/scribe]`,'Use [render]...[/render] to type text, [wait]Ms[/wait] to pause, and [undo /] to delete. loop="true" replays the sequence. Only [render], [wait], and [undo] shortcodes are parsed - plain text between actions is ignored.'),e("Christmas",'[christmas intensity="medium" snowmen="off" trees="off" wreaths="off" northStars="off" sleigh="off" train="off" elf="off" robin="off" firework="off" /]',"intensity: light | medium | heavy. Count-based (off disables entirely): snowmen, trees, wreaths, northStars. Probability-based specials (off prevents spawning): sleigh, train, elf, robin, firework. Snowflakes always fall."),e("Halloween",'[halloween intensity="medium" gravestones="off" jackOLanterns="off" spiders="off" scarecrows="off" twinklingStars="off" /]',"intensity: light | medium | heavy. Decoration toggles (off disables): gravestones, jackOLanterns, spiders, scarecrows, twinklingStars. Particles: bats, ghosts, pumpkins (always on). Fixed decorations: haunted-house, cauldron (always present)."),e("St Patrick's Day",'[st-patricks intensity="medium" pots="off" twinklingStars="off" /]',"intensity: light | medium | heavy. Decoration toggles (off disables): pots (pots of gold), twinklingStars. Particles: shamrocks, clover petals, gold coins, sparkles (always on). Fixed decorations: rainbow, harp, moon. Leprechaun appears randomly - more likely at higher intensity."),e("Valentine's Day",'[valentines intensity="medium" garlands="off" butterflies="off" /]',"intensity: light | medium | heavy. Decoration toggles (off disables): garlands (heart garlands), butterflies. Particles: hearts, rose petals, sparkles, lips (always on). Fixed decorations: envelopes (always present). Cupid appears randomly - more likely at higher intensity."),e("Guy Fawkes Night",'[guy-fawkes intensity="medium" bonfires="off" /]',"intensity: light | medium | heavy. Decoration toggles (off disables): bonfires. Particles: embers, fireworks, sparks, rockets, bursts, trails (always on). Fixed decorations: guy-effigy, catherine-wheel, roman-candle, sparkler-bundle, moon. Starts at 25% particle density and builds up gradually."),e("St Andrew's Day",'[st-andrews intensity="medium" thistles="off" twinklingStars="off" /]',"intensity: light | medium | heavy. Decoration toggles (off disables): thistles, twinklingStars. Particles: heather petals, saltire sparkles (always on). Fixed decorations: bagpiper, saltire-flag, tartan-pattern, highland-scene (always present). Bagpiper probability increases with intensity."),e("St David's Day",'[st-davids intensity="medium" daffodilFields="off" twinklingStars="off" /]',"intensity: light | medium | heavy. Decoration toggles (off disables): daffodilFields, twinklingStars. Particles: daffodil petals, spring sparkles (always on). Fixed decorations: welsh-dragon, harp, leek-bundle, flag (always present). Flying dragon appears randomly - more likely at higher intensity."),e("St George's Day",'[st-georges intensity="medium" roses="off" twinklingStars="off" /]',"intensity: light | medium | heavy. Decoration toggles (off disables): roses (English roses), twinklingStars. Particles: rose petals, Tudor roses, oak leaves, sparkles (always on). Fixed decorations: st-georges-cross, dragon, shield, castle (always present). Knight appears randomly - more likely at higher intensity.")],outro:"Enable the Domma Effects plugin to activate these shortcodes on your site."}),t("DConfig - Declarative Behaviour",{intro:"Define click handlers and class toggles without writing JavaScript. Use the DConfig section above or embed inline with [dconfig]...[/dconfig] in the content body. Inline shortcodes win on selector conflict.",examples:[e("Toggle a class on click",'{ "#my-btn": { "events": { "click": { "target": "#panel", "toggleClass": "hidden" } } } }','Selector keys use standard CSS selectors. "target" is optional - defaults to the element itself.'),e("Inline shortcode syntax",`[dconfig]
|
|
100
100
|
{ "#my-btn": { "events": { "click": { "target": "#panel", "toggleClass": "hidden" } } } }
|
|
101
|
-
[/dconfig]`)]}),t("CSS Editor",{intro:"The toolbar's </> button (left of the Split View icon) swaps the left pane between Markdown and Custom CSS. Edits are saved together with the page - one Save, one toast.",rows:[["</> button","Toggle between Markdown editor and Custom CSS editor"],["Split / Write / Preview","Standard view mode buttons to the right of </>"],["Save","Saves both page content and CSS in a single operation"]]}),t("Colour Picker",{intro:"Insert \u2192 Colour Picker opens a centred colour picker. Pick a colour, then use Copy to copy the hex code to the clipboard or Insert to drop it at the cursor. Click outside the panel to dismiss."})];export const REFERENCE=[{id:"basics",label:"Basics",sections:m},{id:"layout",label:"Layout",sections:h},{id:"components",label:"Components",sections:g},{id:"data",label:"Data",sections:b},{id:"advanced",label:"Advanced",sections:f}];const
|
|
101
|
+
[/dconfig]`)]}),t("CSS Editor",{intro:"The toolbar's </> button (left of the Split View icon) swaps the left pane between Markdown and Custom CSS. Edits are saved together with the page - one Save, one toast.",rows:[["</> button","Toggle between Markdown editor and Custom CSS editor"],["Split / Write / Preview","Standard view mode buttons to the right of </>"],["Save","Saves both page content and CSS in a single operation"]]}),t("Colour Picker",{intro:"Insert \u2192 Colour Picker opens a centred colour picker. Pick a colour, then use Copy to copy the hex code to the clipboard or Insert to drop it at the cursor. Click outside the panel to dismiss."})];export const REFERENCE=[{id:"basics",label:"Basics",sections:m},{id:"layout",label:"Layout",sections:h},{id:"components",label:"Components",sections:g},{id:"data",label:"Data",sections:b},{id:"advanced",label:"Advanced",sections:f}];const w=`
|
|
102
102
|
<div class="per">
|
|
103
103
|
<div class="per-tabs" role="tablist" data-each="tabs key=id">
|
|
104
104
|
<button type="button" class="per-tab" role="tab" data-on-click="$root.show(id)"
|
|
@@ -164,4 +164,4 @@ pre.per-block { padding-right: .75rem; margin-bottom: .5rem; }
|
|
|
164
164
|
.per-copy { position: absolute; top: .3rem; right: .3rem; background: none; border: none; cursor: pointer; opacity: .45; padding: .15rem;
|
|
165
165
|
line-height: 1; color: inherit; }
|
|
166
166
|
.per-copy:hover, .per-copy:focus-visible { opacity: 1; }
|
|
167
|
-
</style>`;async function
|
|
167
|
+
</style>`;async function y(o){try{return await navigator.clipboard.writeText(o),!0}catch{const a=document.createElement("textarea");a.value=o,a.style.cssText="position:fixed;opacity:0;",document.body.appendChild(a),a.select();let n=!1;try{n=document.execCommand("copy")}catch{}return a.remove(),n}}export function openEditorReference(){const o=E.slideover({title:"Editor Reference",size:"md",position:"right"}),a=document.createElement("div");a.innerHTML=w;const n=M.observable("basics"),s=M.applyBindings({tabs:REFERENCE,tab:n,show:r=>{n.value=r},copy:async r=>{const i=await y(r);E.toast(i?"Copied!":"Could not copy - select the code and copy it.",{type:i?"success":"warning",duration:1200})}},a);o.element.appendChild(a);const l=M.effect(()=>{n.value,requestAnimationFrame(()=>I.scan(a))});p(o,()=>{try{l()}catch{}try{s.dispose()}catch{}}),o.open()}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{insertAtCursor as re}from"./markdown-toolbar.js";import{SCRIBE_FIELDS as ae,scribeDefaults as se,scribeLoop as ce,stateToScribeActions as ie,buildScribeShortcode as le}from"./scribe-model.js";const de=20,Q={render:{label:"Render",icon:"edit-3",color:"var(--dm-info,#3b82f6)"},wait:{label:"Wait",icon:"clock",color:"var(--dm-warning,#f59e0b)"},undo:{label:"Undo",icon:"corner-up-left",color:"var(--dm-secondary,#a855f7)"},redraw:{label:"Redraw",icon:"refresh-cw",color:"var(--dm-success,#22c55e)"}},L="padding:.4rem .6rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text,#eee);font-size:.9em;box-sizing:border-box;width:100%;",pe="display:block;font-size:.7rem;font-weight:600;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;margin-bottom:.25rem;",ue="display:flex;align-items:center;gap:.5rem;cursor:pointer;font-size:.85em;";export function openScribeComposer(s){const r=me(),n=[];let t=null,p=null;function c(){clearTimeout(t),p?.destroy(),p=null}const h=E.slideover({title:"Scribe Composer",size:"lg",position:"right",onClose:c});Ce();const b=document.createElement("div");b.className="scribe-composer",b.style.cssText="display:flex;flex-direction:column;height:100%;";const y=document.createElement("div");y.style.cssText="padding:1rem 1.25rem;border-bottom:1px solid var(--dm-border,#333);background:var(--dm-background-alt,#0f0f17);";const k=document.createElement("div");k.style.cssText="min-height:3.5rem;padding:.85rem 1rem;background:var(--dm-surface,#1a1a1a);border:1px dashed var(--dm-border,#333);border-radius:6px;font-size:1.25rem;line-height:1.5;overflow-wrap:anywhere;",y.appendChild(k);const N=document.createElement("div");N.style.cssText="display:flex;gap:.5rem;margin-top:.75rem;align-items:center;";const Y=V("rotate-cw","Replay"),q=V("code","Show code"),B=document.createElement("span");B.style.cssText="font-size:.8em;color:var(--dm-text-muted,#aaa);flex:1;text-align:right;margin-right:.5rem;",N.appendChild(Y),N.appendChild(B),N.appendChild(q),y.appendChild(N);const M=document.createElement("pre");M.style.cssText="display:none;margin:.75rem 0 0;padding:.6rem .75rem;background:var(--dm-surface,#0a0a0a);border:1px solid var(--dm-border,#333);border-radius:4px;font-family:monospace;font-size:.78em;white-space:pre-wrap;word-break:break-all;color:var(--dm-text-muted,#bbb);max-height:200px;overflow:auto;",y.appendChild(M),q.addEventListener("click",()=>{const e=M.style.display!=="none";M.style.display=e?"none":"block"}),Y.addEventListener("click",()=>{J(),p?.resume()}),b.appendChild(y);const R=document.createElement("div");R.style.cssText="display:flex;flex:1;min-height:0;overflow:hidden;";const F=fe(r,()=>{v(),x()});R.appendChild(F.el);const z=document.createElement("main");z.style.cssText="flex:1;overflow-y:auto;padding:1rem 1.25rem;display:flex;flex-direction:column;";const P=document.createElement("h4");P.textContent="Actions",P.style.cssText="margin:0 0 .75rem;font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--dm-text-muted,#aaa);",z.appendChild(P);const A=document.createElement("div");A.style.cssText="display:flex;flex-direction:column;gap:.6rem;",z.appendChild(A);const U=document.createElement("div");U.style.cssText="display:flex;gap:.4rem;margin-top:.9rem;flex-wrap:wrap;",Object.entries(Q).forEach(([e,a])=>{const i=document.createElement("button");i.type="button",i.style.cssText=`padding:.4rem .8rem;background:transparent;border:1px dashed color-mix(in srgb, ${a.color} 40%, transparent);border-radius:4px;color:${a.color};cursor:pointer;font-size:.85em;display:inline-flex;align-items:center;gap:.35rem;`;const l=document.createElement("span");l.setAttribute("data-icon",a.icon),i.appendChild(l),i.appendChild(document.createTextNode(` + ${a.label}`)),i.addEventListener("click",()=>{v(),r.actions.push(he(e)),$(),x()}),U.appendChild(i)}),z.appendChild(U),R.appendChild(z),b.appendChild(R);const T=document.createElement("div");T.style.cssText="display:flex;padding:.75rem 1rem;border-top:1px solid var(--dm-border,#333);background:var(--dm-background-alt,#0f0f17);gap:.5rem;align-items:center;";const S=document.createElement("button");S.type="button",S.className="btn btn-ghost btn-sm",S.textContent="Undo (Ctrl+Z)",S.addEventListener("click",()=>H()),T.appendChild(S);const D=document.createElement("span");D.style.cssText="font-size:.75em;color:var(--dm-text-muted,#aaa);",T.appendChild(D);const G=document.createElement("div");G.style.flex="1",T.appendChild(G);const W=document.createElement("button");W.type="button",W.className="btn btn-ghost",W.textContent="Cancel",W.addEventListener("click",()=>h.close()),T.appendChild(W);const j=document.createElement("button");j.type="button",j.className="btn btn-primary",j.textContent="Insert Scribe",j.addEventListener("click",()=>{re(s,Z()),h.close()}),T.appendChild(j),b.appendChild(T),h.setContent(b),b.addEventListener("keydown",e=>{const a=(e.key||"").toLowerCase();(e.ctrlKey||e.metaKey)&&a==="z"&&!e.shiftKey&&n.length>0&&(e.preventDefault(),e.stopPropagation(),H())}),$(),x(),O(),requestAnimationFrame(()=>{Domma.icons.scan()}),h.open();function v(){n.push(JSON.stringify(r)),n.length>de&&n.shift(),O()}function H(){if(n.length===0){E.toast("Nothing to undo",{type:"info",duration:700});return}const e=JSON.parse(n.pop());Object.assign(r.globals,e.globals),r.actions.length=0,e.actions.forEach(a=>r.actions.push(a)),F.sync(),$(),x(),O(),E.toast("Undone",{type:"info",duration:500})}function O(){D.textContent=n.length===0?"":`${n.length} step${n.length===1?"":"s"} stored`,S.disabled=n.length===0,S.style.opacity=n.length===0?".4":"1"}function x(e=150){clearTimeout(t),t=setTimeout(J,e)}function J(){c(),ee(k),k.style.color="",k.style.fontStyle="",M.textContent=Z();const e=r.actions.filter(o=>o.type==="render"||o.type==="redraw"?(o.text||"").length>0:!0);if(e.length===0){k.textContent="(add an action to preview)",k.style.color="var(--dm-text-muted,#666)",k.style.fontStyle="italic",B.textContent="";return}const a=document.createElement("span");a.className="dm-fx-scribe",k.appendChild(a);const i=r.globals,{effect:l,controls:g,...w}=i;w.actions=ie(e,l);try{p=E.scribe(a,w),B.textContent=i.autoStart?`${e.length} action${e.length===1?"":"s"}`:"Press Replay to start"}catch{B.textContent="Preview error"}}function $(){if(ee(A),r.actions.length===0){const e=document.createElement("p");e.textContent="No actions yet - add one from the buttons below.",e.style.cssText="font-size:.85em;color:var(--dm-text-muted,#888);font-style:italic;margin:.5rem 0;",A.appendChild(e);return}r.actions.forEach((e,a)=>{A.appendChild(ne(e,a))}),requestAnimationFrame(()=>Domma.icons.scan())}function ne(e,a){const i=Q[e.type],l=document.createElement("div");l.style.cssText=`border:1px solid var(--dm-border,#333);border-left:3px solid ${i.color};border-radius:4px;padding:.6rem .75rem;background:var(--dm-surface,#15151a);`;const g=document.createElement("div");g.style.cssText="display:flex;align-items:center;gap:.5rem;margin-bottom:.5rem;";const w=document.createElement("span");w.style.cssText=`display:inline-flex;align-items:center;gap:.3rem;font-size:.72rem;font-weight:700;color:${i.color};text-transform:uppercase;letter-spacing:.06em;`;const o=document.createElement("span");o.setAttribute("data-icon",i.icon),w.appendChild(o),w.appendChild(document.createTextNode(i.label)),g.appendChild(w);const m=document.createElement("span");m.textContent=`#${a+1}`,m.style.cssText="font-size:.7rem;color:var(--dm-text-muted,#888);",g.appendChild(m);const u=document.createElement("div");u.style.flex="1",g.appendChild(u);const d=K("chevron-up","Move up");a===0&&(d.disabled=!0,d.style.opacity=".3"),d.addEventListener("click",()=>X(a,-1)),g.appendChild(d);const f=K("chevron-down","Move down");a===r.actions.length-1&&(f.disabled=!0,f.style.opacity=".3"),f.addEventListener("click",()=>X(a,1)),g.appendChild(f);const C=K("x","Remove");return C.addEventListener("click",()=>{v(),r.actions.splice(a,1),$(),x()}),g.appendChild(C),l.appendChild(g),l.appendChild(oe(e)),l}function X(e,a){const i=e+a;if(i<0||i>=r.actions.length)return;v();const[l]=r.actions.splice(e,1);r.actions.splice(i,0,l),$(),x()}function oe(e){const a=document.createElement("div");if(a.style.cssText="display:flex;flex-direction:column;gap:.5rem;",e.type==="render"||e.type==="redraw"){const o=document.createElement("textarea");o.value=e.text||"",o.placeholder=e.type==="redraw"?"New text - clears everything first, then types this":"Text to type out",o.rows=2,o.style.cssText=L+"resize:vertical;font-family:inherit;min-height:2.2rem;";let m=o.value;o.addEventListener("input",()=>{e.text=o.value,x()}),o.addEventListener("blur",()=>{o.value!==m&&(v(),m=o.value)}),a.appendChild(o);const u=document.createElement("div");u.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.8em;";const d=document.createElement("label");d.textContent="Effect:",d.style.color="var(--dm-text-muted,#aaa)";const f=document.createElement("select");return f.style.cssText=L+"width:auto;padding:.25rem .4rem;",["inherit","none","fade","bounce","glow"].forEach(C=>{const _=document.createElement("option");_.value=C,_.textContent=C.charAt(0).toUpperCase()+C.slice(1),f.appendChild(_)}),f.value=e.effect||"none",f.addEventListener("change",()=>{v(),e.effect=f.value,x()}),u.appendChild(d),u.appendChild(f),a.appendChild(u),a}if(e.type==="wait"){const o=document.createElement("div");o.style.cssText="display:flex;gap:.4rem;align-items:center;";const m=document.createElement("input");m.type="number",m.min="0",m.value=String(e.duration??1e3),m.style.cssText=L+"flex:1;",m.addEventListener("input",()=>{const d=parseInt(m.value,10);!Number.isNaN(d)&&d>=0&&(e.duration=d,x())}),m.addEventListener("blur",()=>v()),o.appendChild(m);const u=document.createElement("select");return u.style.cssText=L+"width:auto;",[["ms","ms"],["s","seconds"]].forEach(([d,f])=>{const C=document.createElement("option");C.value=d,C.textContent=f,u.appendChild(C)}),u.value=e.unit||"ms",u.addEventListener("change",()=>{v(),e.unit=u.value,x()}),o.appendChild(u),a.appendChild(o),a}const i=document.createElement("div");i.style.cssText="display:flex;gap:.75rem;align-items:center;flex-wrap:wrap;font-size:.85em;";const l=document.createElement("input");l.type="number",l.min="1",l.value=String(e.count||5),l.style.cssText=L+"width:5rem;",l.addEventListener("input",()=>{const o=parseInt(l.value,10);!Number.isNaN(o)&&o>0&&(e.count=o,x())}),l.addEventListener("blur",()=>v());const g=`undo-mode-${Math.random().toString(36).slice(2)}`;return[["last","Last render"],["all","All text"],["count","Exactly N units"]].forEach(([o,m])=>{const u=document.createElement("label");u.style.cssText="display:inline-flex;align-items:center;gap:.3rem;cursor:pointer;";const d=document.createElement("input");d.type="radio",d.name=g,d.value=o,d.checked=(e.mode||"last")===o,d.addEventListener("change",()=>{d.checked&&(v(),e.mode=o,l.style.display=o==="count"?"":"none",x())}),u.appendChild(d),u.appendChild(document.createTextNode(m)),i.appendChild(u),o==="count"&&(i.appendChild(l),l.style.display=(e.mode||"last")==="count"?"":"none")}),a.appendChild(i),a}function Z(){return le(r.globals,r.actions)}}function me(){return{globals:se(),actions:[{type:"render",text:"We build things that matter.",effect:"inherit"},{type:"wait",duration:1500,unit:"ms"},{type:"redraw",text:"We create solutions that last.",effect:"inherit"},{type:"wait",duration:1500,unit:"ms"}]}}function he(s){switch(s){case"render":return{type:"render",text:"",effect:"inherit"};case"wait":return{type:"wait",duration:1e3,unit:"ms"};case"undo":return{type:"undo",mode:"last",count:5};case"redraw":return{type:"redraw",text:"",effect:"inherit"}}return{type:"render",text:"",effect:"inherit"}}function fe(s,r){const n=document.createElement("aside");n.style.cssText="width:240px;flex-shrink:0;padding:1rem 1.25rem;border-right:1px solid var(--dm-border,#333);overflow-y:auto;display:flex;flex-direction:column;gap:.75rem;background:var(--dm-background-alt,#0c0c12);";const t=document.createElement("h4");t.textContent="Global settings",t.style.cssText="margin:0 0 .25rem;font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--dm-text-muted,#aaa);",n.appendChild(t);const p=ae.map(c=>{const h=y=>{s.globals[c.key]=c.key==="loop"?ce(y):y,r()};let b;if(c.type==="checkbox"){const y=ve(s.globals[c.key],h,c.label);n.appendChild(y.wrap),b=y.input}else b=c.type==="select"?ge(c.options,s.globals[c.key],h):c.type==="number"?xe(s.globals[c.key],h,c.min):ye(s.globals[c.key],"",h),n.appendChild(be(c.label,b));return{field:c,input:b}});return{el:n,sync(){p.forEach(({field:c,input:h})=>{c.type==="checkbox"?h.checked=s.globals[c.key]:h.value=String(s.globals[c.key])})}}}function be(s,r){const n=document.createElement("div"),t=document.createElement("label");return t.style.cssText=pe,t.textContent=s,n.appendChild(t),n.appendChild(r),n}function xe(s,r,n=1){const t=document.createElement("input");return t.type="number",t.min=String(n),t.value=String(s),t.style.cssText=L,t.addEventListener("input",()=>{const p=Number(t.value);!Number.isNaN(p)&&p>=n&&r(p)}),t}function ye(s,r,n){const t=document.createElement("input");return t.type="text",t.value=s,t.placeholder=r,t.style.cssText=L,t.addEventListener("input",()=>n(t.value)),t}function ge(s,r,n){const t=document.createElement("select");return t.style.cssText=L,s.forEach(([p,c])=>{const h=document.createElement("option");h.value=p,h.textContent=c,t.appendChild(h)}),t.value=r,t.addEventListener("change",()=>n(t.value)),t}function ve(s,r,n){const t=document.createElement("label");t.style.cssText=ue;const p=document.createElement("input");return p.type="checkbox",p.checked=s,p.addEventListener("change",()=>r(p.checked)),t.appendChild(p),t.appendChild(document.createTextNode(n)),{wrap:t,input:p}}function V(s,r){const n=document.createElement("button");n.type="button",n.className="btn btn-ghost btn-sm",n.style.cssText="display:inline-flex;align-items:center;gap:.35rem;";const t=document.createElement("span");return t.setAttribute("data-icon",s),n.appendChild(t),n.appendChild(document.createTextNode(r)),n}function K(s,r){const n=document.createElement("button");n.type="button",n.title=r,n.style.cssText="padding:.25rem .4rem;background:transparent;border:1px solid var(--dm-border,#333);border-radius:3px;color:var(--dm-text-muted,#aaa);cursor:pointer;display:inline-flex;align-items:center;";const t=document.createElement("span");return t.setAttribute("data-icon",s),n.appendChild(t),n}function ee(s){for(;s.firstChild;)s.removeChild(s.firstChild)}function we(s){return String(s).replace(/&/g,"&").replace(/"/g,""")}let te=!1;function Ce(){te||(te=!0,I.register("edit-3",{viewBox:"0 0 24 24",paths:["M12 20h9","M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4 12.5-12.5z"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("clock",{viewBox:"0 0 24 24",paths:["M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10z","M12 6v6l4 2"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("corner-up-left",{viewBox:"0 0 24 24",paths:["M9 14 4 9l5-5","M20 20v-7a4 4 0 0 0-4-4H4"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("refresh-cw",{viewBox:"0 0 24 24",paths:["M23 4v6h-6","M1 20v-6h6","M3.51 9a9 9 0 0 1 14.85-3.36L23 10","M20.49 15a9 9 0 0 1-14.85 3.36L1 14"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("rotate-cw",{viewBox:"0 0 24 24",paths:["M23 4v6h-6","M20.49 15a9 9 0 1 1-2.12-9.36L23 10"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("code",{viewBox:"0 0 24 24",paths:["M16 18l6-6-6-6","M8 6l-6 6 6 6"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("chevron-up",{viewBox:"0 0 24 24",path:"M18 15l-6-6-6 6",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("chevron-down",{viewBox:"0 0 24 24",path:"M6 9l6 6 6-6",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("x",{viewBox:"0 0 24 24",paths:["M18 6L6 18","M6 6l12 12"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}))}
|
|
1
|
+
import{insertAtCursor as re}from"./markdown-toolbar.js";import{SCRIBE_FIELDS as ae,scribeDefaults as se,scribeLoop as ce,stateToScribeActions as ie,buildScribeShortcode as le}from"./scribe-model.js";const de=20,Q={render:{label:"Render",icon:"edit-3",color:"var(--dm-info,#3b82f6)"},wait:{label:"Wait",icon:"clock",color:"var(--dm-warning,#f59e0b)"},undo:{label:"Undo",icon:"corner-up-left",color:"var(--dm-secondary,#a855f7)"},redraw:{label:"Redraw",icon:"refresh-cw",color:"var(--dm-success,#22c55e)"}},L="padding:.4rem .6rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text,#eee);font-size:.9em;box-sizing:border-box;width:100%;",pe="display:block;font-size:.7rem;font-weight:600;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;margin-bottom:.25rem;",ue="display:flex;align-items:center;gap:.5rem;cursor:pointer;font-size:.85em;";export function openScribeComposer(s){const r=me(),n=[];let t=null,p=null;function c(){clearTimeout(t),p?.destroy(),p=null}const h=E.slideover({title:"Scribe Composer",size:"lg",position:"right",onClose:c});Ce();const b=document.createElement("div");b.className="scribe-composer",b.style.cssText="display:flex;flex-direction:column;height:100%;";const y=document.createElement("div");y.style.cssText="padding:1rem 1.25rem;border-bottom:1px solid var(--dm-border,#333);background:var(--dm-background-alt,#0f0f17);";const k=document.createElement("div");k.style.cssText="min-height:3.5rem;padding:.85rem 1rem;background:var(--dm-surface,#1a1a1a);border:1px dashed var(--dm-border,#333);border-radius:6px;font-size:1.25rem;line-height:1.5;overflow-wrap:anywhere;",y.appendChild(k);const B=document.createElement("div");B.style.cssText="display:flex;gap:.5rem;margin-top:.75rem;align-items:center;";const Y=V("rotate-cw","Replay"),q=V("code","Show code"),N=document.createElement("span");N.style.cssText="font-size:.8em;color:var(--dm-text-muted,#aaa);flex:1;text-align:right;margin-right:.5rem;",B.appendChild(Y),B.appendChild(N),B.appendChild(q),y.appendChild(B);const M=document.createElement("pre");M.style.cssText="display:none;margin:.75rem 0 0;padding:.6rem .75rem;background:var(--dm-surface,#0a0a0a);border:1px solid var(--dm-border,#333);border-radius:4px;font-family:monospace;font-size:.78em;white-space:pre-wrap;word-break:break-all;color:var(--dm-text-muted,#bbb);max-height:200px;overflow:auto;",y.appendChild(M),q.addEventListener("click",()=>{const e=M.style.display!=="none";M.style.display=e?"none":"block"}),Y.addEventListener("click",()=>{J(),p?.resume(),p&&(N.textContent="Playing preview")}),b.appendChild(y);const R=document.createElement("div");R.style.cssText="display:flex;flex:1;min-height:0;overflow:hidden;";const F=fe(r,()=>{C(),x()});R.appendChild(F.el);const z=document.createElement("main");z.style.cssText="flex:1;overflow-y:auto;padding:1rem 1.25rem;display:flex;flex-direction:column;";const D=document.createElement("h4");D.textContent="Actions",D.style.cssText="margin:0 0 .75rem;font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--dm-text-muted,#aaa);",z.appendChild(D);const A=document.createElement("div");A.style.cssText="display:flex;flex-direction:column;gap:.6rem;",z.appendChild(A);const P=document.createElement("div");P.style.cssText="display:flex;gap:.4rem;margin-top:.9rem;flex-wrap:wrap;",Object.entries(Q).forEach(([e,a])=>{const i=document.createElement("button");i.type="button",i.style.cssText=`padding:.4rem .8rem;background:transparent;border:1px dashed color-mix(in srgb, ${a.color} 40%, transparent);border-radius:4px;color:${a.color};cursor:pointer;font-size:.85em;display:inline-flex;align-items:center;gap:.35rem;`;const l=document.createElement("span");l.setAttribute("data-icon",a.icon),i.appendChild(l),i.appendChild(document.createTextNode(` + ${a.label}`)),i.addEventListener("click",()=>{C(),r.actions.push(he(e)),$(),x()}),P.appendChild(i)}),z.appendChild(P),R.appendChild(z),b.appendChild(R);const T=document.createElement("div");T.style.cssText="display:flex;padding:.75rem 1rem;border-top:1px solid var(--dm-border,#333);background:var(--dm-background-alt,#0f0f17);gap:.5rem;align-items:center;";const S=document.createElement("button");S.type="button",S.className="btn btn-ghost btn-sm",S.textContent="Undo (Ctrl+Z)",S.addEventListener("click",()=>H()),T.appendChild(S);const U=document.createElement("span");U.style.cssText="font-size:.75em;color:var(--dm-text-muted,#aaa);",T.appendChild(U);const G=document.createElement("div");G.style.flex="1",T.appendChild(G);const W=document.createElement("button");W.type="button",W.className="btn btn-ghost",W.textContent="Cancel",W.addEventListener("click",()=>h.close()),T.appendChild(W);const j=document.createElement("button");j.type="button",j.className="btn btn-primary",j.textContent="Insert Scribe",j.addEventListener("click",()=>{re(s,Z()),h.close()}),T.appendChild(j),b.appendChild(T),h.setContent(b),b.addEventListener("keydown",e=>{const a=(e.key||"").toLowerCase();(e.ctrlKey||e.metaKey)&&a==="z"&&!e.shiftKey&&n.length>0&&(e.preventDefault(),e.stopPropagation(),H())}),$(),x(),O(),requestAnimationFrame(()=>{Domma.icons.scan()}),h.open();function C(){n.push(JSON.stringify(r)),n.length>de&&n.shift(),O()}function H(){if(n.length===0){E.toast("Nothing to undo",{type:"info",duration:700});return}const e=JSON.parse(n.pop());Object.assign(r.globals,e.globals),r.actions.length=0,e.actions.forEach(a=>r.actions.push(a)),F.sync(),$(),x(),O(),E.toast("Undone",{type:"info",duration:500})}function O(){U.textContent=n.length===0?"":`${n.length} step${n.length===1?"":"s"} stored`,S.disabled=n.length===0,S.style.opacity=n.length===0?".4":"1"}function x(e=150){clearTimeout(t),t=setTimeout(J,e)}function J(){c(),ee(k),k.style.color="",k.style.fontStyle="",M.textContent=Z();const e=r.actions.filter(o=>o.type==="render"||o.type==="redraw"?(o.text||"").length>0:!0);if(e.length===0){k.textContent="(add an action to preview)",k.style.color="var(--dm-text-muted,#666)",k.style.fontStyle="italic",N.textContent="";return}const a=document.createElement("span");a.className="dm-fx-scribe",k.appendChild(a);const i=r.globals,{effect:l,controls:g,...w}=i;w.actions=ie(e,l);try{p=Domma.effects.scribe(a,w),N.textContent=i.autoStart?`${e.length} action${e.length===1?"":"s"}`:"Press Replay to start"}catch{N.textContent="Preview error"}}function $(){if(ee(A),r.actions.length===0){const e=document.createElement("p");e.textContent="No actions yet - add one from the buttons below.",e.style.cssText="font-size:.85em;color:var(--dm-text-muted,#888);font-style:italic;margin:.5rem 0;",A.appendChild(e);return}r.actions.forEach((e,a)=>{A.appendChild(ne(e,a))}),requestAnimationFrame(()=>Domma.icons.scan())}function ne(e,a){const i=Q[e.type],l=document.createElement("div");l.style.cssText=`border:1px solid var(--dm-border,#333);border-left:3px solid ${i.color};border-radius:4px;padding:.6rem .75rem;background:var(--dm-surface,#15151a);`;const g=document.createElement("div");g.style.cssText="display:flex;align-items:center;gap:.5rem;margin-bottom:.5rem;";const w=document.createElement("span");w.style.cssText=`display:inline-flex;align-items:center;gap:.3rem;font-size:.72rem;font-weight:700;color:${i.color};text-transform:uppercase;letter-spacing:.06em;`;const o=document.createElement("span");o.setAttribute("data-icon",i.icon),w.appendChild(o),w.appendChild(document.createTextNode(i.label)),g.appendChild(w);const m=document.createElement("span");m.textContent=`#${a+1}`,m.style.cssText="font-size:.7rem;color:var(--dm-text-muted,#888);",g.appendChild(m);const u=document.createElement("div");u.style.flex="1",g.appendChild(u);const d=K("chevron-up","Move up");a===0&&(d.disabled=!0,d.style.opacity=".3"),d.addEventListener("click",()=>X(a,-1)),g.appendChild(d);const f=K("chevron-down","Move down");a===r.actions.length-1&&(f.disabled=!0,f.style.opacity=".3"),f.addEventListener("click",()=>X(a,1)),g.appendChild(f);const v=K("x","Remove");return v.addEventListener("click",()=>{C(),r.actions.splice(a,1),$(),x()}),g.appendChild(v),l.appendChild(g),l.appendChild(oe(e)),l}function X(e,a){const i=e+a;if(i<0||i>=r.actions.length)return;C();const[l]=r.actions.splice(e,1);r.actions.splice(i,0,l),$(),x()}function oe(e){const a=document.createElement("div");if(a.style.cssText="display:flex;flex-direction:column;gap:.5rem;",e.type==="render"||e.type==="redraw"){const o=document.createElement("textarea");o.value=e.text||"",o.placeholder=e.type==="redraw"?"New text - clears everything first, then types this":"Text to type out",o.rows=2,o.style.cssText=L+"resize:vertical;font-family:inherit;min-height:2.2rem;";let m=o.value;o.addEventListener("input",()=>{e.text=o.value,x()}),o.addEventListener("blur",()=>{o.value!==m&&(C(),m=o.value)}),a.appendChild(o);const u=document.createElement("div");u.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.8em;";const d=document.createElement("label");d.textContent="Effect:",d.style.color="var(--dm-text-muted,#aaa)";const f=document.createElement("select");return f.style.cssText=L+"width:auto;padding:.25rem .4rem;",["inherit","none","fade","bounce","glow"].forEach(v=>{const _=document.createElement("option");_.value=v,_.textContent=v==="inherit"?"Default effect":v.charAt(0).toUpperCase()+v.slice(1),f.appendChild(_)}),f.value=e.effect||"none",f.addEventListener("change",()=>{C(),e.effect=f.value,x()}),u.appendChild(d),u.appendChild(f),a.appendChild(u),a}if(e.type==="wait"){const o=document.createElement("div");o.style.cssText="display:flex;gap:.4rem;align-items:center;";const m=document.createElement("input");m.type="number",m.min="0",m.step="any",m.value=String(e.duration??1e3),m.style.cssText=L+"flex:1;",m.addEventListener("input",()=>{const d=Number(m.value);!Number.isNaN(d)&&d>=0&&(e.duration=d,x())}),m.addEventListener("blur",()=>C()),o.appendChild(m);const u=document.createElement("select");return u.style.cssText=L+"width:auto;",[["ms","ms"],["s","seconds"]].forEach(([d,f])=>{const v=document.createElement("option");v.value=d,v.textContent=f,u.appendChild(v)}),u.value=e.unit||"ms",u.addEventListener("change",()=>{C(),e.unit=u.value,x()}),o.appendChild(u),a.appendChild(o),a}const i=document.createElement("div");i.style.cssText="display:flex;gap:.75rem;align-items:center;flex-wrap:wrap;font-size:.85em;";const l=document.createElement("input");l.type="number",l.min="1",l.value=String(e.count||5),l.style.cssText=L+"width:5rem;",l.addEventListener("input",()=>{const o=parseInt(l.value,10);!Number.isNaN(o)&&o>0&&(e.count=o,x())}),l.addEventListener("blur",()=>C());const g=`undo-mode-${Math.random().toString(36).slice(2)}`;return[["last","Last render"],["all","All text"],["count","Exactly N units"]].forEach(([o,m])=>{const u=document.createElement("label");u.style.cssText="display:inline-flex;align-items:center;gap:.3rem;cursor:pointer;";const d=document.createElement("input");d.type="radio",d.name=g,d.value=o,d.checked=(e.mode||"last")===o,d.addEventListener("change",()=>{d.checked&&(C(),e.mode=o,l.style.display=o==="count"?"":"none",x())}),u.appendChild(d),u.appendChild(document.createTextNode(m)),i.appendChild(u),o==="count"&&(i.appendChild(l),l.style.display=(e.mode||"last")==="count"?"":"none")}),a.appendChild(i),a}function Z(){return le(r.globals,r.actions)}}function me(){return{globals:se(),actions:[{type:"render",text:"We build things that matter.",effect:"inherit"},{type:"wait",duration:1500,unit:"ms"},{type:"redraw",text:"We create solutions that last.",effect:"inherit"},{type:"wait",duration:1500,unit:"ms"}]}}function he(s){switch(s){case"render":return{type:"render",text:"",effect:"inherit"};case"wait":return{type:"wait",duration:1e3,unit:"ms"};case"undo":return{type:"undo",mode:"last",count:5};case"redraw":return{type:"redraw",text:"",effect:"inherit"}}return{type:"render",text:"",effect:"inherit"}}function fe(s,r){const n=document.createElement("aside");n.style.cssText="width:240px;flex-shrink:0;padding:1rem 1.25rem;border-right:1px solid var(--dm-border,#333);overflow-y:auto;display:flex;flex-direction:column;gap:.75rem;background:var(--dm-background-alt,#0c0c12);";const t=document.createElement("h4");t.textContent="Global settings",t.style.cssText="margin:0 0 .25rem;font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--dm-text-muted,#aaa);",n.appendChild(t);const p=ae.map(c=>{const h=y=>{r(),s.globals[c.key]=c.key==="loop"?ce(y):y};let b;if(c.type==="checkbox"){const y=ve(s.globals[c.key],h,c.label);n.appendChild(y.wrap),b=y.input}else b=c.type==="select"?ge(c.options,s.globals[c.key],h):c.type==="number"?xe(s.globals[c.key],h,c.min):ye(s.globals[c.key],"",h),n.appendChild(be(c.label,b));return{field:c,input:b}});return{el:n,sync(){p.forEach(({field:c,input:h})=>{c.type==="checkbox"?h.checked=s.globals[c.key]:h.value=String(s.globals[c.key])})}}}function be(s,r){const n=document.createElement("div"),t=document.createElement("label");return t.style.cssText=pe,t.textContent=s,n.appendChild(t),n.appendChild(r),n}function xe(s,r,n=1){const t=document.createElement("input");return t.type="number",t.min=String(n),t.value=String(s),t.style.cssText=L,t.addEventListener("input",()=>{const p=Number(t.value);!Number.isNaN(p)&&p>=n&&r(p)}),t}function ye(s,r,n){const t=document.createElement("input");return t.type="text",t.value=s,t.placeholder=r,t.style.cssText=L,t.addEventListener("input",()=>n(t.value)),t}function ge(s,r,n){const t=document.createElement("select");return t.style.cssText=L,s.forEach(([p,c])=>{const h=document.createElement("option");h.value=p,h.textContent=c,t.appendChild(h)}),t.value=r,t.addEventListener("change",()=>n(t.value)),t}function ve(s,r,n){const t=document.createElement("label");t.style.cssText=ue;const p=document.createElement("input");return p.type="checkbox",p.checked=s,p.addEventListener("change",()=>r(p.checked)),t.appendChild(p),t.appendChild(document.createTextNode(n)),{wrap:t,input:p}}function V(s,r){const n=document.createElement("button");n.type="button",n.className="btn btn-ghost btn-sm",n.style.cssText="display:inline-flex;align-items:center;gap:.35rem;";const t=document.createElement("span");return t.setAttribute("data-icon",s),n.appendChild(t),n.appendChild(document.createTextNode(r)),n}function K(s,r){const n=document.createElement("button");n.type="button",n.title=r,n.style.cssText="padding:.25rem .4rem;background:transparent;border:1px solid var(--dm-border,#333);border-radius:3px;color:var(--dm-text-muted,#aaa);cursor:pointer;display:inline-flex;align-items:center;";const t=document.createElement("span");return t.setAttribute("data-icon",s),n.appendChild(t),n}function ee(s){for(;s.firstChild;)s.removeChild(s.firstChild)}function we(s){return String(s).replace(/&/g,"&").replace(/"/g,""")}let te=!1;function Ce(){te||(te=!0,I.register("edit-3",{viewBox:"0 0 24 24",paths:["M12 20h9","M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4 12.5-12.5z"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("clock",{viewBox:"0 0 24 24",paths:["M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10z","M12 6v6l4 2"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("corner-up-left",{viewBox:"0 0 24 24",paths:["M9 14 4 9l5-5","M20 20v-7a4 4 0 0 0-4-4H4"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("refresh-cw",{viewBox:"0 0 24 24",paths:["M23 4v6h-6","M1 20v-6h6","M3.51 9a9 9 0 0 1 14.85-3.36L23 10","M20.49 15a9 9 0 0 1-14.85 3.36L1 14"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("rotate-cw",{viewBox:"0 0 24 24",paths:["M23 4v6h-6","M20.49 15a9 9 0 1 1-2.12-9.36L23 10"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("code",{viewBox:"0 0 24 24",paths:["M16 18l6-6-6-6","M8 6l-6 6 6 6"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("chevron-up",{viewBox:"0 0 24 24",path:"M18 15l-6-6-6 6",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("chevron-down",{viewBox:"0 0 24 24",path:"M6 9l6 6 6-6",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("x",{viewBox:"0 0 24 24",paths:["M18 6L6 18","M6 6l12 12"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}))}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const SCRIBE_FIELDS=[{name:"mode",key:"mode",label:"Render mode",type:"select",default:"typewriter",options:[["typewriter","Characters"],["word","Words"],["sentence","Sentences"]]},{name:"effect",key:"effect",label:"Default entrance effect",type:"select",default:"none",options:["none","fade","bounce","glow"].map(r=>[r,r])},{name:"speed",key:"speed",label:"Typing speed (ms/unit)",type:"number",default:50,min:0},{name:"delete-speed",key:"deleteSpeed",label:"Delete speed (ms/unit)",type:"number",default:30,min:0},{name:"cursor",key:"cursor",label:"Show cursor",type:"checkbox",default:!0},{name:"cursor-char",key:"cursorChar",label:"Cursor character",type:"text",default:"|"},{name:"cursor-type",key:"cursorType",label:"Cursor style",type:"select",default:"caret",options:[["caret","Caret"],["block","Block"],["underline","Underline"]]},{name:"cursor-blink",key:"cursorBlink",label:"Blink cursor while idle",type:"checkbox",default:!0},{name:"loop",key:"loop",label:"Loop (false, true, or total plays)",type:"text",default:!1},{name:"loop-delay",key:"loopDelay",label:"Loop delay (ms)",type:"number",default:1e3,min:0},{name:"pause-on-hover",key:"pauseOnHover",label:"Pause on hover",type:"checkbox",default:!1},{name:"auto-start",key:"autoStart",label:"Start automatically",type:"checkbox",default:!0},{name:"respect-motion-preference",key:"respectMotionPreference",label:"Respect reduced motion",type:"checkbox",default:!0},{name:"controls",key:"controls",label:"Show playback controls",type:"checkbox",default:!1}];export function scribeDefaults(){return Object.fromEntries(SCRIBE_FIELDS.map(r=>[r.key,r.default]))}export function scribeLoop(r){if(r===!0||r==="true")return!0;if(r===!1||r==="false"||r==="")return!1;const o=Number(r);return Number.isInteger(o)&&o>=1?o:!1}export function stateToScribeActions(r,o="none"){const n=[];return r.forEach(t=>{t.type==="render"||t.type==="redraw"?(t.type==="redraw"&&n.push({undoRender:"all"}),n.push({render:t.text||"",effect:!t.effect||t.effect==="inherit"?o:t.effect})):t.type==="wait"?n.push({wait:t.unit==="s"?(t.duration||0)*1e3:t.duration||0}):t.type==="undo"&&n.push({undoRender:t.mode==="all"?"all":t.mode==="count"?t.count:!0})}),n}export function buildScribeShortcode(r,o){const n=e=>String(e).replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">"),t=SCRIBE_FIELDS.filter(e=>r[e.key]!==e.default).map(e=>`${e.name}="${n(r[e.key])}"`),l=o.map(e=>{if(e.type==="render"||e.type==="redraw"){const c=e.effect&&e.effect!=="inherit"?` effect="${n(e.effect)}"`:"";return`[${e.type}${c}]${e.text||""}[/${e.type}]`}return e.type==="wait"?`[wait]${e.duration}${e.unit==="s"?"s":""}[/wait]`:e.mode==="all"?'[undo all="true" /]':e.mode==="count"?`[undo count="${e.count}" /]`:"[undo /]"});return`[scribe${t.length?" "+t.join(" "):""}]
|
|
1
|
+
export const SCRIBE_FIELDS=[{name:"mode",key:"mode",label:"Render mode",type:"select",default:"typewriter",options:[["typewriter","Characters"],["word","Words"],["sentence","Sentences"]]},{name:"effect",key:"effect",label:"Default entrance effect",type:"select",default:"none",options:["none","fade","bounce","glow"].map(r=>[r,r])},{name:"speed",key:"speed",label:"Typing speed (ms/unit)",type:"number",default:50,min:0},{name:"delete-speed",key:"deleteSpeed",label:"Delete speed (ms/unit)",type:"number",default:30,min:0},{name:"cursor",key:"cursor",label:"Show cursor",type:"checkbox",default:!0},{name:"cursor-char",key:"cursorChar",label:"Cursor character",type:"text",default:"|"},{name:"cursor-type",key:"cursorType",label:"Cursor style",type:"select",default:"caret",options:[["caret","Caret"],["block","Block"],["underline","Underline"]]},{name:"cursor-blink",key:"cursorBlink",label:"Blink cursor while idle",type:"checkbox",default:!0},{name:"loop",key:"loop",label:"Loop (false, true, or total plays)",type:"text",default:!1},{name:"loop-delay",key:"loopDelay",label:"Loop delay (ms)",type:"number",default:1e3,min:0},{name:"pause-on-hover",key:"pauseOnHover",label:"Pause on hover",type:"checkbox",default:!1},{name:"auto-start",key:"autoStart",label:"Start automatically",type:"checkbox",default:!0},{name:"respect-motion-preference",key:"respectMotionPreference",label:"Respect reduced motion",type:"checkbox",default:!0,always:!0},{name:"controls",key:"controls",label:"Show playback controls",type:"checkbox",default:!1}];export function scribeDefaults(){return Object.fromEntries(SCRIBE_FIELDS.map(r=>[r.key,r.default]))}export function scribeLoop(r){if(r===!0||r==="true")return!0;if(r===!1||r==="false"||r==="")return!1;const o=Number(r);return Number.isInteger(o)&&o>=1?o:!1}export function stateToScribeActions(r,o="none"){const n=[];return r.forEach(t=>{t.type==="render"||t.type==="redraw"?(t.type==="redraw"&&n.push({undoRender:"all"}),n.push({render:t.text||"",effect:!t.effect||t.effect==="inherit"?o:t.effect})):t.type==="wait"?n.push({wait:t.unit==="s"?(t.duration||0)*1e3:t.duration||0}):t.type==="undo"&&n.push({undoRender:t.mode==="all"?"all":t.mode==="count"?t.count:!0})}),n}export function buildScribeShortcode(r,o){const n=e=>String(e).replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">"),t=SCRIBE_FIELDS.filter(e=>e.always||r[e.key]!==e.default).map(e=>`${e.name}="${n(r[e.key])}"`),l=o.map(e=>{if(e.type==="render"||e.type==="redraw"){const c=e.effect&&e.effect!=="inherit"?` effect="${n(e.effect)}"`:"";return`[${e.type}${c}]${e.text||""}[/${e.type}]`}return e.type==="wait"?`[wait]${e.duration}${e.unit==="s"?"s":""}[/wait]`:e.mode==="all"?'[undo all="true" /]':e.mode==="count"?`[undo count="${e.count}" /]`:"[undo /]"});return`[scribe${t.length?" "+t.join(" "):""}]
|
|
2
2
|
${l.join(`
|
|
3
3
|
`)}
|
|
4
4
|
[/scribe]`}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const TAB_FIELDS={general:["title","tagline","siteUrl","adminHome","spacerSize","bodyClass"],seo:["seoTitle","seoSeparator","seoDescription"],footer:["footerCopyright","footerMotionToggle","footerMotionDefault","footerMotionControl","footerClass","footerSocialClass","socialTwitter","socialFacebook","socialInstagram","socialLinkedin","socialGithub","socialYoutube"],email:["smtpHost","smtpPort","smtpUser","smtpPass","smtpSecure","smtpFromAddress","smtpFromName"],backToTop:["bttEnabled","bttSmooth","bttLabel","bttThreshold","bttPosition","bttOffset","bttBottomOffset"],cookies:["ccEnabled","ccMessage","ccAcceptAll","ccRejectAll","ccCustomize","ccSavePrefs","ccPrivacyText","ccPrivacyUrl","ccCookieText","ccCookieUrl","ccPosition","ccLayout","ccTheme","ccShowFunctional","ccShowAnalytics","ccShowMarketing","ccVersion"],breadcrumbs:["bcEnabled","bcHomeLabel","bcPosition","bcOffsetX","bcOffsetY"],css:["css"]},SECRET_FIELDS=["smtpPass"],BREADCRUMB_POSITIONS=["TL","TR","BL","BR"];const o=(t,s="")=>t==null?s:String(t),i=(t,s)=>{const c=Number.parseInt(t,10);return Number.isFinite(c)?c:s};export function homeValue(t){return/^\/[A-Za-z0-9\-_/]*$/.test(t||"")&&String(t).replace(/\/+$/,"")||"/"}export function formFromSettings(t={},s=""){const c=t.backToTop||{},e=t.cookieConsent||{},r=t.breadcrumbs||{};return{title:o(t.title),tagline:o(t.tagline),siteUrl:o(t.baseUrl),adminHome:homeValue(t.adminHome),spacerSize:o(t.layoutOptions?.spacerSize??40),bodyClass:o(t.bodyClass),seoTitle:o(t.seo?.defaultTitle),seoSeparator:o(t.seo?.titleSeparator," | "),seoDescription:o(t.seo?.defaultDescription),footerCopyright:o(t.footer?.copyright),footerMotionToggle:t.footer?.showMotionToggle!==!1,footerMotionDefault:["off","on"].includes(t.footer?.motionDefault)?t.footer.motionDefault:"system",footerMotionControl:t.footer?.motionControl==="checkbox"?"checkbox":"switch",footerClass:o(t.footer?.class),footerSocialClass:o(t.footer?.socialClass),socialTwitter:o(t.social?.twitter),socialFacebook:o(t.social?.facebook),socialInstagram:o(t.social?.instagram),socialLinkedin:o(t.social?.linkedin),socialGithub:o(t.social?.github),socialYoutube:o(t.social?.youtube),smtpHost:o(t.smtp?.host),smtpPort:o(t.smtp?.port||587),smtpUser:o(t.smtp?.user),smtpPass:"",smtpSecure:t.smtp?.secure===!0,smtpFromAddress:o(t.smtp?.fromAddress),smtpFromName:o(t.smtp?.fromName),bttEnabled:c.enabled!==!1,bttSmooth:c.smooth!==!1,bttLabel:o(c.label),bttThreshold:o(c.scrollThreshold??300),bttPosition:o(c.position,"bottom-right"),bttOffset:o(c.offset??32),bttBottomOffset:o(c.bottomOffset??c.offset??32),ccEnabled:e.enabled!==!1,ccMessage:o(e.message),ccAcceptAll:o(e.acceptAllText,"Accept All"),ccRejectAll:o(e.rejectAllText,"Reject All"),ccCustomize:o(e.customizeText,"Customize"),ccSavePrefs:o(e.savePreferencesText,"Save Preferences"),ccPrivacyText:o(e.privacyPolicyText,"Privacy Policy"),ccPrivacyUrl:o(e.privacyPolicyUrl),ccCookieText:o(e.cookiePolicyText,"Cookie Policy"),ccCookieUrl:o(e.cookiePolicyUrl),ccPosition:o(e.position,"bottom"),ccLayout:o(e.layout,"bar"),ccTheme:o(e.theme,"dark"),ccShowFunctional:e.showFunctional!==!1,ccShowAnalytics:e.showAnalytics!==!1,ccShowMarketing:e.showMarketing!==!1,ccVersion:o(e.consentVersion,"1.0"),bcEnabled:r.enabled===!0,bcHomeLabel:o(r.homeLabel,"Home"),bcPosition:BREADCRUMB_POSITIONS.includes(r.position)?r.position:"TL",bcOffsetX:o(r.offsetX??8),bcOffsetY:o(r.offsetY??8),css:o(s)}}export function payloadFromForm(t,s={},{adminHomeReady:c=!0}={}){const e=r=>o(r).trim();return{title:e(t.title),tagline:e(t.tagline),baseUrl:e(t.siteUrl).replace(/\/+$/,""),...c&&{adminHome:e(t.adminHome)||"/"},layoutOptions:{spacerSize:i(t.spacerSize,40)||40},bodyClass:e(t.bodyClass),seo:{defaultTitle:e(t.seoTitle),titleSeparator:o(t.seoSeparator)||" | ",defaultDescription:e(t.seoDescription)},footer:{copyright:e(t.footerCopyright),showMotionToggle:t.footerMotionToggle===!0,links:s.footer?.links||[],motionDefault:["off","on"].includes(t.footerMotionDefault)?t.footerMotionDefault:"system",motionControl:t.footerMotionControl==="checkbox"?"checkbox":"switch",class:e(t.footerClass),socialClass:e(t.footerSocialClass)},social:{twitter:e(t.socialTwitter),facebook:e(t.socialFacebook),instagram:e(t.socialInstagram),linkedin:e(t.socialLinkedin),github:e(t.socialGithub),youtube:e(t.socialYoutube)},smtp:{host:e(t.smtpHost),port:i(t.smtpPort,587)||587,user:e(t.smtpUser),pass:o(t.smtpPass),secure:t.smtpSecure===!0,fromAddress:e(t.smtpFromAddress),fromName:e(t.smtpFromName)},backToTop:{enabled:t.bttEnabled===!0,scrollThreshold:i(t.bttThreshold,300),position:o(t.bttPosition)||"bottom-right",offset:i(t.bttOffset,32),bottomOffset:i(t.bttBottomOffset,32),label:e(t.bttLabel),smooth:t.bttSmooth===!0},cookieConsent:{enabled:t.ccEnabled===!0,message:e(t.ccMessage),acceptAllText:e(t.ccAcceptAll),rejectAllText:e(t.ccRejectAll),customizeText:e(t.ccCustomize),savePreferencesText:e(t.ccSavePrefs),privacyPolicyText:e(t.ccPrivacyText),privacyPolicyUrl:e(t.ccPrivacyUrl),cookiePolicyText:e(t.ccCookieText),cookiePolicyUrl:e(t.ccCookieUrl),position:o(t.ccPosition)||"bottom",layout:o(t.ccLayout)||"bar",theme:o(t.ccTheme)||"dark",showFunctional:t.ccShowFunctional===!0,showAnalytics:t.ccShowAnalytics===!0,showMarketing:t.ccShowMarketing===!0,consentVersion:e(t.ccVersion)||"1.0"},breadcrumbs:{enabled:t.bcEnabled===!0,homeLabel:e(t.bcHomeLabel)||"Home",position:BREADCRUMB_POSITIONS.includes(t.bcPosition)?t.bcPosition:"TL",offsetX:i(t.bcOffsetX,8),offsetY:i(t.bcOffsetY,8)}}}export function siteUrlError(t){const s=o(t).trim().replace(/\/+$/,"");return s?/^https?:\/\//i.test(s)?/^https?:\/\/([a-z0-9.\-]+|\[[0-9a-f:.]+\])(:\d{1,5})?$/i.test(s)?"":"Just the address, like https://example.com - no page path after it.":"Start with https:// (or http://).":""}const a=t=>typeof t=="boolean"?t:o(t);export function snapshot(t){return JSON.stringify(Object.keys(t).sort().map(s=>[s,a(t[s])]))}export function changedTabs(t,s){const c=[];for(const[e,r]of Object.entries(TAB_FIELDS))r.some(n=>a(t[n])!==a(s[n]))&&c.push(e);return c}export function draftOf(t){return Object.fromEntries(Object.entries(t).filter(([s])=>!SECRET_FIELDS.includes(s)))}export function settingsProblems(t){const s=[];return o(t.smtpHost).trim()?o(t.smtpFromAddress).trim()||s.push({tone:"warn",tab:"email",text:"No From address - mail has no sender and many servers refuse it."}):s.push({tone:"danger",tab:"email",text:"No SMTP host - mail goes to a throwaway test inbox and reaches no one (password resets, form notifications)."}),t.ccEnabled===!0&&!o(t.ccPrivacyUrl).trim()&&s.push({tone:"warn",tab:"cookies",text:"The cookie banner is on but links to no privacy policy."}),s}export function describeCacheKey(t){const s=/^page:(.*?):m\d+:role([^:]*):/.exec(String(t||""));return s?{path:s[1]||"/",role:s[2]||"anon",page:!0}:{path:String(t||""),role:"",page:!1}}export function expiresIn(t,s=Date.now()){if(t==null)return"no expiry";const c=t-s;return c<=0?"expired":c<6e4?`${Math.round(c/1e3)}s`:c<36e5?`${Math.round(c/6e4)}m`:`${Math.round(c/36e5)}h`}
|
|
1
|
+
export const TAB_FIELDS={general:["title","tagline","siteUrl","adminHome","spacerSize","bodyClass"],seo:["seoTitle","seoSeparator","seoDescription"],footer:["footerCopyright","footerLayout","footerBlurb","footerMotionToggle","footerMotionDefault","footerMotionControl","footerClass","footerSocialClass","socialTwitter","socialFacebook","socialInstagram","socialLinkedin","socialGithub","socialYoutube"],email:["smtpHost","smtpPort","smtpUser","smtpPass","smtpSecure","smtpFromAddress","smtpFromName"],backToTop:["bttEnabled","bttSmooth","bttLabel","bttThreshold","bttPosition","bttOffset","bttBottomOffset"],cookies:["ccEnabled","ccMessage","ccAcceptAll","ccRejectAll","ccCustomize","ccSavePrefs","ccPrivacyText","ccPrivacyUrl","ccCookieText","ccCookieUrl","ccPosition","ccLayout","ccTheme","ccShowFunctional","ccShowAnalytics","ccShowMarketing","ccVersion"],breadcrumbs:["bcEnabled","bcHomeLabel","bcPosition","bcOffsetX","bcOffsetY"],css:["css"]},SECRET_FIELDS=["smtpPass"],BREADCRUMB_POSITIONS=["TL","TR","BL","BR"],FOOTER_LAYOUTS=["auto","columns","row"];const o=(t,s="")=>t==null?s:String(t),i=(t,s)=>{const c=Number.parseInt(t,10);return Number.isFinite(c)?c:s};export function homeValue(t){return/^\/[A-Za-z0-9\-_/]*$/.test(t||"")&&String(t).replace(/\/+$/,"")||"/"}export function formFromSettings(t={},s=""){const c=t.backToTop||{},e=t.cookieConsent||{},r=t.breadcrumbs||{};return{title:o(t.title),tagline:o(t.tagline),siteUrl:o(t.baseUrl),adminHome:homeValue(t.adminHome),spacerSize:o(t.layoutOptions?.spacerSize??40),bodyClass:o(t.bodyClass),seoTitle:o(t.seo?.defaultTitle),seoSeparator:o(t.seo?.titleSeparator," | "),seoDescription:o(t.seo?.defaultDescription),footerCopyright:o(t.footer?.copyright),footerLayout:FOOTER_LAYOUTS.includes(t.footer?.layout)?t.footer.layout:"auto",footerBlurb:o(t.footer?.blurb),footerMotionToggle:t.footer?.showMotionToggle!==!1,footerMotionDefault:["off","on"].includes(t.footer?.motionDefault)?t.footer.motionDefault:"system",footerMotionControl:t.footer?.motionControl==="checkbox"?"checkbox":"switch",footerClass:o(t.footer?.class),footerSocialClass:o(t.footer?.socialClass),socialTwitter:o(t.social?.twitter),socialFacebook:o(t.social?.facebook),socialInstagram:o(t.social?.instagram),socialLinkedin:o(t.social?.linkedin),socialGithub:o(t.social?.github),socialYoutube:o(t.social?.youtube),smtpHost:o(t.smtp?.host),smtpPort:o(t.smtp?.port||587),smtpUser:o(t.smtp?.user),smtpPass:"",smtpSecure:t.smtp?.secure===!0,smtpFromAddress:o(t.smtp?.fromAddress),smtpFromName:o(t.smtp?.fromName),bttEnabled:c.enabled!==!1,bttSmooth:c.smooth!==!1,bttLabel:o(c.label),bttThreshold:o(c.scrollThreshold??300),bttPosition:o(c.position,"bottom-right"),bttOffset:o(c.offset??32),bttBottomOffset:o(c.bottomOffset??c.offset??32),ccEnabled:e.enabled!==!1,ccMessage:o(e.message),ccAcceptAll:o(e.acceptAllText,"Accept All"),ccRejectAll:o(e.rejectAllText,"Reject All"),ccCustomize:o(e.customizeText,"Customize"),ccSavePrefs:o(e.savePreferencesText,"Save Preferences"),ccPrivacyText:o(e.privacyPolicyText,"Privacy Policy"),ccPrivacyUrl:o(e.privacyPolicyUrl),ccCookieText:o(e.cookiePolicyText,"Cookie Policy"),ccCookieUrl:o(e.cookiePolicyUrl),ccPosition:o(e.position,"bottom"),ccLayout:o(e.layout,"bar"),ccTheme:o(e.theme,"dark"),ccShowFunctional:e.showFunctional!==!1,ccShowAnalytics:e.showAnalytics!==!1,ccShowMarketing:e.showMarketing!==!1,ccVersion:o(e.consentVersion,"1.0"),bcEnabled:r.enabled===!0,bcHomeLabel:o(r.homeLabel,"Home"),bcPosition:BREADCRUMB_POSITIONS.includes(r.position)?r.position:"TL",bcOffsetX:o(r.offsetX??8),bcOffsetY:o(r.offsetY??8),css:o(s)}}export function payloadFromForm(t,s={},{adminHomeReady:c=!0}={}){const e=r=>o(r).trim();return{title:e(t.title),tagline:e(t.tagline),baseUrl:e(t.siteUrl).replace(/\/+$/,""),...c&&{adminHome:e(t.adminHome)||"/"},layoutOptions:{spacerSize:i(t.spacerSize,40)||40},bodyClass:e(t.bodyClass),seo:{defaultTitle:e(t.seoTitle),titleSeparator:o(t.seoSeparator)||" | ",defaultDescription:e(t.seoDescription)},footer:{copyright:e(t.footerCopyright),layout:FOOTER_LAYOUTS.includes(t.footerLayout)?t.footerLayout:"auto",blurb:e(t.footerBlurb),showMotionToggle:t.footerMotionToggle===!0,links:s.footer?.links||[],motionDefault:["off","on"].includes(t.footerMotionDefault)?t.footerMotionDefault:"system",motionControl:t.footerMotionControl==="checkbox"?"checkbox":"switch",class:e(t.footerClass),socialClass:e(t.footerSocialClass)},social:{twitter:e(t.socialTwitter),facebook:e(t.socialFacebook),instagram:e(t.socialInstagram),linkedin:e(t.socialLinkedin),github:e(t.socialGithub),youtube:e(t.socialYoutube)},smtp:{host:e(t.smtpHost),port:i(t.smtpPort,587)||587,user:e(t.smtpUser),pass:o(t.smtpPass),secure:t.smtpSecure===!0,fromAddress:e(t.smtpFromAddress),fromName:e(t.smtpFromName)},backToTop:{enabled:t.bttEnabled===!0,scrollThreshold:i(t.bttThreshold,300),position:o(t.bttPosition)||"bottom-right",offset:i(t.bttOffset,32),bottomOffset:i(t.bttBottomOffset,32),label:e(t.bttLabel),smooth:t.bttSmooth===!0},cookieConsent:{enabled:t.ccEnabled===!0,message:e(t.ccMessage),acceptAllText:e(t.ccAcceptAll),rejectAllText:e(t.ccRejectAll),customizeText:e(t.ccCustomize),savePreferencesText:e(t.ccSavePrefs),privacyPolicyText:e(t.ccPrivacyText),privacyPolicyUrl:e(t.ccPrivacyUrl),cookiePolicyText:e(t.ccCookieText),cookiePolicyUrl:e(t.ccCookieUrl),position:o(t.ccPosition)||"bottom",layout:o(t.ccLayout)||"bar",theme:o(t.ccTheme)||"dark",showFunctional:t.ccShowFunctional===!0,showAnalytics:t.ccShowAnalytics===!0,showMarketing:t.ccShowMarketing===!0,consentVersion:e(t.ccVersion)||"1.0"},breadcrumbs:{enabled:t.bcEnabled===!0,homeLabel:e(t.bcHomeLabel)||"Home",position:BREADCRUMB_POSITIONS.includes(t.bcPosition)?t.bcPosition:"TL",offsetX:i(t.bcOffsetX,8),offsetY:i(t.bcOffsetY,8)}}}export function siteUrlError(t){const s=o(t).trim().replace(/\/+$/,"");return s?/^https?:\/\//i.test(s)?/^https?:\/\/([a-z0-9.\-]+|\[[0-9a-f:.]+\])(:\d{1,5})?$/i.test(s)?"":"Just the address, like https://example.com - no page path after it.":"Start with https:// (or http://).":""}const a=t=>typeof t=="boolean"?t:o(t);export function snapshot(t){return JSON.stringify(Object.keys(t).sort().map(s=>[s,a(t[s])]))}export function changedTabs(t,s){const c=[];for(const[e,r]of Object.entries(TAB_FIELDS))r.some(n=>a(t[n])!==a(s[n]))&&c.push(e);return c}export function draftOf(t){return Object.fromEntries(Object.entries(t).filter(([s])=>!SECRET_FIELDS.includes(s)))}export function settingsProblems(t){const s=[];return o(t.smtpHost).trim()?o(t.smtpFromAddress).trim()||s.push({tone:"warn",tab:"email",text:"No From address - mail has no sender and many servers refuse it."}):s.push({tone:"danger",tab:"email",text:"No SMTP host - mail goes to a throwaway test inbox and reaches no one (password resets, form notifications)."}),t.ccEnabled===!0&&!o(t.ccPrivacyUrl).trim()&&s.push({tone:"warn",tab:"cookies",text:"The cookie banner is on but links to no privacy policy."}),s}export function describeCacheKey(t){const s=/^page:(.*?):m\d+:role([^:]*):/.exec(String(t||""));return s?{path:s[1]||"/",role:s[2]||"anon",page:!0}:{path:String(t||""),role:"",page:!1}}export function expiresIn(t,s=Date.now()){if(t==null)return"no expiry";const c=t-s;return c<=0?"expired":c<6e4?`${Math.round(c/1e3)}s`:c<36e5?`${Math.round(c/6e4)}m`:`${Math.round(c/36e5)}h`}
|
|
@@ -310,7 +310,7 @@ Your text appears letter by letter.
|
|
|
310
310
|
<tr>
|
|
311
311
|
<td><code>[render]</code></td>
|
|
312
312
|
<td><code>[render effect="fade"]Text[/render]</code></td>
|
|
313
|
-
<td>Type the text. Optional <code>effect</code>: fade,
|
|
313
|
+
<td>Type the text. Optional <code>effect</code>: none, fade, bounce, glow (inherits the Scribe default)</td>
|
|
314
314
|
</tr>
|
|
315
315
|
<tr>
|
|
316
316
|
<td><code>[wait]</code></td>
|
|
@@ -321,7 +321,7 @@ Your text appears letter by letter.
|
|
|
321
321
|
<td><code>[undo]</code></td>
|
|
322
322
|
<td><code>[undo /]</code> or <code>[undo count="3" /]</code> or <code>[undo all="true" /]</code>
|
|
323
323
|
</td>
|
|
324
|
-
<td>Delete the last render action, N
|
|
324
|
+
<td>Delete the last render action, N units in the chosen mode, or all text</td>
|
|
325
325
|
</tr>
|
|
326
326
|
</tbody>
|
|
327
327
|
</table>
|
|
@@ -357,12 +357,12 @@ Your text appears letter by letter.
|
|
|
357
357
|
<tr>
|
|
358
358
|
<td><code>cursor-type</code></td>
|
|
359
359
|
<td>-</td>
|
|
360
|
-
<td>Cursor style (block, underline
|
|
360
|
+
<td>Cursor style (caret, block, underline)</td>
|
|
361
361
|
</tr>
|
|
362
362
|
<tr>
|
|
363
363
|
<td><code>loop</code></td>
|
|
364
364
|
<td>false</td>
|
|
365
|
-
<td>
|
|
365
|
+
<td>false: once; true: forever; positive integer: total plays</td>
|
|
366
366
|
</tr>
|
|
367
367
|
<tr>
|
|
368
368
|
<td><code>loop-delay</code></td>
|
|
@@ -374,6 +374,12 @@ Your text appears letter by letter.
|
|
|
374
374
|
<td>false</td>
|
|
375
375
|
<td>Pause animation while hovered (true/false)</td>
|
|
376
376
|
</tr>
|
|
377
|
+
<tr><td><code>mode</code></td><td>typewriter</td><td>Characters (typewriter), word, or sentence</td></tr>
|
|
378
|
+
<tr><td><code>effect</code></td><td>none</td><td>Default entrance: none, fade, bounce, glow</td></tr>
|
|
379
|
+
<tr><td><code>cursor-blink</code></td><td>true</td><td>Blink while idle; steady while typing and deleting</td></tr>
|
|
380
|
+
<tr><td><code>auto-start</code></td><td>true</td><td>false waits for Play; playback controls appear automatically</td></tr>
|
|
381
|
+
<tr><td><code>respect-motion-preference</code></td><td>Site setting</td><td>Honor the visitor’s reduced motion preference</td></tr>
|
|
382
|
+
<tr><td><code>controls</code></td><td>false</td><td>Show Play, Pause, and Replay</td></tr>
|
|
377
383
|
</tbody>
|
|
378
384
|
</table>
|
|
379
385
|
|
|
@@ -116,6 +116,20 @@
|
|
|
116
116
|
<label class="form-label" for="stx-footer-copy">Copyright text</label>
|
|
117
117
|
<input id="stx-footer-copy" type="text" class="form-input" placeholder="© 2026 My Site" data-model="footerCopyright.value">
|
|
118
118
|
</div>
|
|
119
|
+
<div class="stx-setting">
|
|
120
|
+
<label class="form-label" for="stx-footer-layout">Layout
|
|
121
|
+
<span data-help-title="Footer layout" data-help="Columns puts your brand, the blurb and the social links beside one column per group of the footer menu, with copyright, legal links and the motion control in a bar beneath. One row puts everything on a single line. Automatic uses columns when the footer menu has groups (made with sub-items in Menus) and one row when it does not."></span></label>
|
|
122
|
+
<select id="stx-footer-layout" class="form-input" data-model="footerLayout.value">
|
|
123
|
+
<option value="auto">Automatic</option>
|
|
124
|
+
<option value="columns">Columns</option>
|
|
125
|
+
<option value="row">One row</option>
|
|
126
|
+
</select>
|
|
127
|
+
</div>
|
|
128
|
+
<div class="stx-wide">
|
|
129
|
+
<label class="form-label" for="stx-footer-blurb">Blurb
|
|
130
|
+
<span data-help="A sentence or two under your brand in the columns layout - what the site is, in plain words. Leave it empty for none."></span></label>
|
|
131
|
+
<textarea id="stx-footer-blurb" class="form-input" rows="2" maxlength="300" placeholder="What your site is about, in a sentence." data-model="footerBlurb.value"></textarea>
|
|
132
|
+
</div>
|
|
119
133
|
<div class="stx-wide stx-setting">
|
|
120
134
|
<label class="form-label" for="stx-motion">Show a “Reduce motion” switch
|
|
121
135
|
<span data-help="An accessibility switch in the footer that lets visitors turn animations off. Turning this off only hides the switch - visitors who already chose it, and anyone whose browser asks for reduced motion, still get a calmer site."></span></label>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "domma-cms",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.18",
|
|
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",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"@fastify/rate-limit": "^10.3.0",
|
|
85
85
|
"@fastify/static": "9.1.1",
|
|
86
86
|
"bcryptjs": "^3.0.3",
|
|
87
|
-
"domma-js": "0.51.
|
|
87
|
+
"domma-js": "0.51.9",
|
|
88
88
|
"dotenv": "^17.2.3",
|
|
89
89
|
"fastify": "5.8.5",
|
|
90
90
|
"gray-matter": "^4.0.3",
|