domma-cms 1.10.25 → 1.10.26
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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.10.26] - 2026-10-26
|
|
4
|
+
|
|
5
|
+
- **Pages with a carousel, tabs, accordion, grid or timeline made in the insert form are cached again.** The form wrote `expire-scope="ip"` on every slide, tab, item, column and event, which marked the page as expiring: it skipped the response cache, set a cookie and wrote the expiry ledger on every view. `expire-scope` and `expiry-id` on their own are no longer an expiry (they only say how a rule counts) and are taken off the tag, so pages already carrying them are fixed without editing.
|
|
6
|
+
- **The insert form's slide, tab and item rows have room again.** The seven expiry fields sat in each row and squeezed the title and content to nothing; they now fold under the row as Expiry, with the proper controls.
|
|
7
|
+
- **The slideover and countdown fields show Domma's description too**, and a slideover can be extra large or full width, or come from the bottom or top.
|
|
8
|
+
|
|
3
9
|
## [1.10.25] - 2026-10-25
|
|
4
10
|
|
|
5
11
|
- **Built against domma-js 0.60.0** - see [its release notes](https://github.com/pinpointzero73/domma/releases/tag/v0.60.0).
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{replaceRange as
|
|
2
|
-
${
|
|
3
|
-
${l}`}export function buildChildrenBody(e,n){return n.map(
|
|
4
|
-
`)}export function emitSnippet(e,n,
|
|
1
|
+
import{replaceRange as ce}from"./markdown-toolbar.js";import{boolState as de,boolValue as pe,parseAttrs as te,serialiseTag as ne,setAttrs as me}from"./shortcode-tags.js";import{SHORTCODES as ue}from"./shortcode-registry.js";import{clearLookupCache as fe,lookupOptions as he}from"./shortcode-lookups.js";import{PREVIEW_RENDERERS as ge}from"./shortcode-preview.js";import{dommaHelp as be,whenCatalogue as xe}from"./domma-catalogue.js";import{SHORTCODE_EXPIRY_FIELDS as ye}from"../../../public/js/shortcode-expiry.mjs";import{makeCheckbox as ve,makeColourInput as Ee,makeField as v,makeIconInput as oe,makeImageInput as le,makeLivePreview as Ce,makeSelect as W,makeTextInput as Y}from"./shortcode-modal.js";const we=new Map(ue.map(e=>[e.name,e])),se=new Set(ye.map(e=>e.name)),re=6;export function templateAttrs(e){const n=String(e.template||"").match(new RegExp(`^\\[${e.name}([\\s\\S]*?)\\s*/?\\]`));return n?te(n[1]):{}}export function templateBody(e){if(e.selfClosing)return"";const n=String(e.template||"").match(new RegExp(`^\\[${e.name}[^\\]]*\\]([\\s\\S]*)\\[/${e.name}\\]$`));return n?n[1].replace(/^\n/,"").replace(/\n$/,""):""}export function templateChildren(e){if(!e.children)return[];const n=e.children.name,a=new RegExp(`\\[${n}([^\\]]*)\\]([\\s\\S]*?)\\[/${n}\\]`,"g"),c=[];for(const l of templateBody(e).matchAll(a))c.push({attrs:te(l[1]),body:l[2].replace(/^\n/,"").replace(/\n$/,"")});return c}const ke=new Set(["lookup","url"]);export function seedAttrs(e,n){const a=new Map((e.attrs||[]).map(l=>[l.name,l.type])),c={};for(const[l,p]of Object.entries(n))ke.has(a.get(l))||(c[l]=p);return c}export function buildSnippet(e,n,a=""){const c=ne(e.name,n,e.selfClosing);if(e.selfClosing)return c;const l=`[/${e.name}]`;return e.inline?`${c}${a}${l}`:`${c}
|
|
2
|
+
${a}
|
|
3
|
+
${l}`}export function buildChildrenBody(e,n){return n.map(a=>buildSnippet(e,a.attrs,a.body)).join(`
|
|
4
|
+
`)}export function emitSnippet(e,n,a,c){const l=(e.formats||[]).find(p=>p.value===c);if(l&&typeof l.emit=="function"){const p=l.emit(n,a);if(p!=null)return p}return buildSnippet(e,n,a)}const Le="display:block;font-size:.7rem;font-weight:600;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;margin-bottom:.25rem;";function ie(e,n,a,c){const l=n===!0||n==null?"":String(n);if(e.type==="checkbox"){const s=ve(e.label),d=s.querySelector("input");return d.checked=de(n,e.default),d.addEventListener("change",a),{el:s,bare:!0,get:()=>pe(e,d.checked)}}if(e.type==="select"){const s=e.options.some(([w])=>w==="")?e.options:[["","- none -"],...e.options],d=W(s);return d.value=l,d.addEventListener("change",a),{el:v(e.label,d),get:()=>d.value||null}}if(e.type==="icon"){const{el:s,input:d}=oe("icon name (optional)",l);return d.addEventListener("input",a),{el:v(e.label,s),get:()=>d.value.trim()||null}}if(e.type==="image"){const{el:s,input:d}=le("/media/photo.jpg",l);return d.addEventListener("input",a),{el:v(e.label,s),get:()=>d.value.trim()||null}}if(e.type==="colour"){const{el:s,input:d}=Ee("#0f172a or a theme colour",l);return d.addEventListener("input",a),{el:v(e.label,s),get:()=>d.value.trim()||null}}if(e.type==="lookup"){const s=W([["","Loading\u2026"]]);s.disabled=!0,s.addEventListener("change",a);let d;const w=()=>{const h=c(),P=e.source==="collection-fields"?String(h.slug??""):e.source;P!==d&&(d=P,s.disabled=!0,he(e.source,h).then(f=>{const y=s.value||l,g=f.some(([T])=>T===y),k=[["","- none -"],...f];y&&!g&&k.push([y,`${y} (missing)`]),s.replaceChildren();for(const[T,b]of k){const $=document.createElement("option");$.value=T,$.textContent=b,s.appendChild($)}s.value=y,s.disabled=!1,a()}))};return w(),{el:v(e.label,s),get:()=>s.value||null,refresh:e.source==="collection-fields"?w:null}}const p=Y(e.placeholder||(e.type==="url"?"/about or https://example.com":""),l);return e.type==="number"&&(p.type="number"),p.addEventListener("input",a),{el:v(e.label,p),get:()=>p.value.trim()||null}}function Se(e,n){xe(a=>{const c=be(a,n);if(!c)return;const l=document.createElement("small");l.className="sc-domma-help",l.style.cssText="display:block;margin-top:.2rem;font-size:.75em;color:var(--dm-text-muted,#999);",l.textContent=c,e.appendChild(l)})}export function openShortcodeForm(e,n,a={}){const{span:c=null,defaults:l=null}=a,p=!!c;fe();const s=e.selectionStart,d=e.selectionEnd,w=e.value.slice(s,d),h=n.children?we.get(n.children.name):null,P={...seedAttrs(n,templateAttrs(n)),...l||{}},f=document.createElement("div");f.style.cssText="padding:.25rem 0 .5rem;display:flex;flex-direction:column;gap:.75rem;";const y=[],g=[];let k=()=>{};const T=()=>{const t={};for(const{attr:o,w:m}of y){const r=m.get();r!=null&&r!==""&&(t[o.name]=r)}return t},b=()=>k(),$=()=>T();let _=null;!p&&n.formats?.length&&(_=W(n.formats.map(t=>[t.value,t.label])),_.addEventListener("change",b),f.appendChild(v("Format",_)));const R=n.attrs||[],D=R.length>re+2?re:R.length,q=(t,o)=>{const m=p?c.attrs[t.name]:P[t.name],r=ie(t,m,b,$);y.push({attr:t,w:r,initial:r.get()});const x=t.domma&&r.bare?document.createElement("div"):r.el;x!==r.el&&x.appendChild(r.el),o.appendChild(x),t.domma&&Se(x,t)};for(const t of R.slice(0,D))q(t,f);if(D<R.length){const t=document.createElement("details");t.style.cssText="border-top:1px solid var(--dm-border,#333);padding-top:.6rem;";const o=document.createElement("summary");o.textContent=`More options (${R.length-D})`,o.style.cssText="cursor:pointer;font-size:.75rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",t.appendChild(o);const m=document.createElement("div");m.style.cssText="display:flex;flex-direction:column;gap:.75rem;padding-top:.75rem;",t.appendChild(m);for(const r of R.slice(D))q(r,m);f.appendChild(t)}let L=null,S=null;const F=document.createElement("div");if(!p&&h){const t=document.createElement("div");t.style.cssText=Le,t.textContent=`${h.label}s`,f.appendChild(t),F.style.cssText="display:flex;flex-direction:column;gap:.4rem;",f.appendChild(F),S=document.createElement("button"),S.type="button",S.textContent=`+ Add ${h.label.toLowerCase()}`,S.style.cssText="padding:.35rem .75rem;background:transparent;border:1px dashed var(--dm-border,#555);border-radius:4px;color:var(--dm-text-muted,#aaa);cursor:pointer;font-size:.85em;align-self:flex-start;",S.addEventListener("click",()=>{V({attrs:{},body:templateBody(h)||"Content"}),k()}),f.appendChild(S);const o=templateChildren(n),m=o.length?o:[{attrs:{},body:"Content"}];for(const r of m)V({attrs:seedAttrs(h,r.attrs),body:r.body});w&&(g[0].bodyInput.value=w)}else!p&&!n.selfClosing&&(L=document.createElement("textarea"),L.rows=n.inline?2:4,L.value=w||templateBody(n),L.style.cssText="width:100%;padding:.4rem .6rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text,#eee);font-size:.9em;font-family:inherit;box-sizing:border-box;resize:vertical;",L.addEventListener("input",b),f.appendChild(v("Content",L)));function V(t){if(g.length>=(n.children.max??20))return;const o=document.createElement("div");o.style.cssText="display:flex;flex-direction:column;gap:.25rem;";const m=document.createElement("div");m.style.cssText="display:flex;gap:.35rem;align-items:center;",o.appendChild(m);const r=[],x=(h.attrs||[]).filter(i=>!se.has(i.name)),H=(h.attrs||[]).filter(i=>se.has(i.name));for(const i of x)if(i.type==="icon"){const{el:u,input:C}=oe(i.label.toLowerCase(),t.attrs[i.name]||"");u.style.flex=".7",C.addEventListener("input",b),r.push({attr:i,get:()=>C.value.trim()||null}),m.appendChild(u)}else if(i.type==="image"){const{el:u,input:C}=le(i.label,t.attrs[i.name]||"");u.style.flex="1",C.addEventListener("input",b),r.push({attr:i,get:()=>C.value.trim()||null}),m.appendChild(u)}else if(i.type==="select"){const u=W(i.options);u.value=t.attrs[i.name]||i.options[0][0],u.style.flex=".7",u.addEventListener("change",b),r.push({attr:i,get:()=>u.value||null}),m.appendChild(u)}else{const u=Y(i.label,t.attrs[i.name]||"");u.style.flex="1",u.addEventListener("input",b),r.push({attr:i,get:()=>u.value.trim()||null}),m.appendChild(u)}const M=Y("Content",t.body||"");M.style.flex="1.2",M.addEventListener("input",b),m.appendChild(M);const A=document.createElement("button");if(A.type="button",A.textContent="\xD7",A.style.cssText="padding:.3rem .5rem;background:transparent;border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text-muted,#aaa);cursor:pointer;font-size:.85em;flex-shrink:0;",H.length){const i=document.createElement("details");i.style.cssText="margin-left:.15rem;";const u=document.createElement("summary");u.textContent="Expiry",u.style.cssText="cursor:pointer;font-size:.7rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;",i.appendChild(u);const C=document.createElement("div");C.style.cssText="display:flex;flex-direction:column;gap:.6rem;padding:.5rem 0 .25rem .75rem;",i.appendChild(C);for(const z of H){const ee=ie(z,t.attrs[z.name],b,$);r.push({attr:z,get:ee.get}),C.appendChild(ee.el)}H.some(z=>t.attrs[z.name]!=null)&&(i.open=!0),o.appendChild(i)}const Z={row:o,fields:r,bodyInput:M,remove:A};A.addEventListener("click",()=>{g.length<=(n.children.min??1)||(g.splice(g.indexOf(Z),1),o.remove(),k())}),m.appendChild(A),g.push(Z),F.appendChild(o),window.I?.scan?.(o)}const X=ge[n.preview];let I=null;if(X){const t=document.createElement("div");t.style.cssText="background:var(--dm-background-alt,#111);border:1px solid var(--dm-border,#333);border-radius:4px;padding:.75rem;min-height:2.5rem;display:flex;align-items:center;overflow-x:auto;",I=document.createElement("span"),t.appendChild(I),f.appendChild(v("Preview",t))}const K=Ce();f.appendChild(v(p?"Tag preview":"Shortcode preview",K.el));const N=document.createElement("div");N.style.cssText="display:flex;justify-content:flex-end;gap:.75rem;padding-top:.75rem;border-top:1px solid var(--dm-border,#333);";const B=document.createElement("button");B.type="button",B.className="btn btn-ghost",B.textContent="Cancel";const O=document.createElement("button");O.type="button",O.className="btn btn-primary",O.textContent=p?"Apply":`Insert ${n.label}`,N.appendChild(B),N.appendChild(O),f.appendChild(N);const G=()=>h&&g.length?buildChildrenBody(h,g.map(t=>({attrs:Object.fromEntries(t.fields.map(o=>[o.attr.name,o.get()]).filter(([,o])=>o!=null)),body:t.bodyInput.value}))):L?L.value:templateBody(n),J=()=>emitSnippet(n,T(),G(),_?.value),ae=t=>{if(n.inline||n.selfClosing||!t.startsWith("["))return t;const o=e.value.slice(0,s),m=e.value.slice(d),r=o===""||o.endsWith(`
|
|
5
5
|
`)?"":`
|
|
6
|
-
`,
|
|
6
|
+
`,x=m===""||m.startsWith(`
|
|
7
7
|
`)?"":`
|
|
8
|
-
`;return`${
|
|
8
|
+
`;return`${r}${t}${x}`};k=()=>{S&&(S.disabled=g.length>=(n.children.max??20));for(const{w:t}of y)t.refresh?.();if(I){const t=X(p?{...c.attrs,...Q()}:T(),p?"":G());I.style.cssText=t.css,I.textContent=t.text}K.update(p?ne(c.name,{...c.attrs,...U()},c.selfClosing,{keepEmpty:!!n.block}):J())};function Q(){const t={};for(const{attr:o,w:m,initial:r}of y){const x=m.get();x!==r&&(t[o.name]=x)}return t}function U(){const t=Q();if(n.block)for(const o of Object.keys(t))t[o]==null&&(t[o]="");return t}const j=E.slideover({title:p?`Edit ${n.label}`:`Insert ${n.label}`,size:h?"lg":"md",position:"right",content:f});return j.open(),window.I?.scan?.(f),k(),B.addEventListener("click",()=>j.close()),O.addEventListener("click",()=>{if(j.close(),p)me(e,c,U(),{keepEmpty:!!n.block});else{const t=ae(J());ce(e,s,d,t),e.setSelectionRange(s+t.length,s+t.length)}e.dispatchEvent(new Event("input",{bubbles:!0})),e.focus()}),requestAnimationFrame(()=>{f.querySelector("input:not([type=checkbox]):not([type=color]), select, textarea")?.focus()}),j}
|
|
@@ -20,7 +20,7 @@ Right
|
|
|
20
20
|
Content
|
|
21
21
|
[/col]`,attrs:[{name:"span",type:"number",label:"Span"},{name:"align",type:"select",label:"Content alignment",options:[["","Inherit"],["left","Left"],["center","Centre"],["centre","Centre (alias)"],["right","Right"]]},{name:"id",type:"text",label:"ID"}]},{name:"slideover",label:"Slideover",icon:"panel-right",category:"Layout",selfClosing:!1,container:!0,wrappable:!0,template:`[slideover title="More information" trigger="Read more"]
|
|
22
22
|
Content
|
|
23
|
-
[/slideover]`,attrs:[{name:"title",type:"text",label:"Title"},{name:"trigger",type:"text",label:"Trigger label"},{name:"size",type:"select",label:"Size",options:[["sm","Small"],["md","Medium"],["lg","Large"]]},{name:"position",type:"select",label:"Position",options:[["right","Right"],["left","Left"]]}]},{name:"center",label:"Centre",icon:"text-center",category:"Layout",selfClosing:!1,container:!0,wrappable:!0,template:`[center]
|
|
23
|
+
[/slideover]`,attrs:[{name:"title",type:"text",label:"Title",domma:"slideover.title"},{name:"trigger",type:"text",label:"Trigger label"},{name:"size",type:"select",label:"Size",options:[["sm","Small"],["md","Medium"],["lg","Large"],["xl","Extra large"],["full","Full width"]],domma:"slideover.size"},{name:"position",type:"select",label:"Position",options:[["right","Right"],["left","Left"],["bottom","Bottom"],["top","Top"]],domma:"slideover.position"}]},{name:"center",label:"Centre",icon:"text-center",category:"Layout",selfClosing:!1,container:!0,wrappable:!0,template:`[center]
|
|
24
24
|
Centred content
|
|
25
25
|
[/center]`,attrs:[{name:"class",type:"text",label:"CSS class"}]},{name:"spacer",label:"Spacer",icon:"spacer-insert",category:"Layout",selfClosing:!0,container:!1,wrappable:!1,template:'[spacer size="24" /]',attrs:[{name:"size",type:"number",label:"Height (px)"},{name:"class",type:"text",label:"CSS class"}]},{name:"banner",label:"Banner",icon:"banner-insert",category:"Layout",selfClosing:!1,container:!0,wrappable:!0,template:`[banner type="info" title="Note"]
|
|
26
26
|
Banner content
|
|
@@ -33,7 +33,7 @@ Banner content
|
|
|
33
33
|
[/accordion]`,children:{name:"item",min:2,max:12},attrs:[{name:"multiple",type:"checkbox",label:"Allow multiple open",domma:"accordion.allowMultiple"},{name:"id",type:"text",label:"ID"}]},{name:"item",label:"Item",icon:"list",category:"Components",child:!0,selfClosing:!1,container:!0,wrappable:!1,template:'[item title="Item title"]Content[/item]',inline:!0,attrs:[{name:"title",type:"text",label:"Title"}]},{name:"carousel",label:"Carousel",icon:"carousel-insert",category:"Components",selfClosing:!1,container:!0,wrappable:!1,template:`[carousel autoplay="true" interval="5000"]
|
|
34
34
|
[slide title="Slide 1" image="/media/photo.jpg"]Caption.[/slide]
|
|
35
35
|
[slide title="Slide 2"]Text-only slide.[/slide]
|
|
36
|
-
[/carousel]`,children:{name:"slide",min:2,max:12},quickAttrs:["height-mode","height","arrow-position","background","arrow-background","arrow-color"],attrs:[{name:"autoplay",type:"checkbox",label:"Autoplay",domma:"carousel.autoplay"},{name:"interval",type:"number",label:"Interval (ms)",domma:"carousel.interval"},{name:"loop",type:"checkbox",label:"Loop",default:!0,domma:"carousel.loop"},{name:"animation",type:"select",label:"Animation",options:[["slide","Slide"],["fade","Fade"],["crossfade","Crossfade"]],domma:"carousel.animation"},{name:"animation-duration",type:"number",label:"Animation duration (ms)",domma:"carousel.animationDuration"},{name:"animation-easing",type:"text",label:"Animation easing",domma:"carousel.animationEasing"},{name:"height-mode",type:"select",label:"Image height",options:[["crop","Top-aligned crop (shortest image)"],["average","Average of shortest and tallest images"]],domma:"carousel.heightMode"},{name:"height",type:"number",label:"Fixed height (px, optional)",domma:"carousel.height"},{name:"mobile-popup",type:"checkbox",label:"Open carousel cards in a popup on mobile"},{name:"arrow-position",type:"select",label:"Arrow position",options:[["middle","Middle"],["top","Top"],["bottom","Bottom"]]},{name:"background",type:"colour",label:"Background colour"},{name:"arrow-background",type:"colour",label:"Arrow background"},{name:"arrow-color",type:"colour",label:"Arrow colour"},{name:"id",type:"text",label:"ID"}]},{name:"slide",label:"Slide",icon:"image",category:"Components",child:!0,selfClosing:!1,container:!0,wrappable:!1,template:'[slide title="Slide title" image="/media/photo.jpg"]Caption[/slide]',inline:!0,attrs:[{name:"title",type:"text",label:"Title"},{name:"image",type:"image",label:"Image"}]},{name:"countdown",label:"Countdown",icon:"stopwatch",category:"Components",selfClosing:!0,container:!1,wrappable:!1,template:'[countdown to="2026-12-31" format="DD:HH:mm:ss" /]',attrs:[{name:"to",type:"text",label:"Target date (ISO)"},{name:"duration",type:"number",label:"Duration (seconds)"},{name:"format",type:"select",label:"Format",options:[["mm:ss","mm:ss"],["HH:mm:ss","HH:mm:ss"],["DD:HH:mm:ss","DD:HH:mm:ss"]]},{name:"id",type:"text",label:"ID"}]},{name:"timeline",label:"Timeline",icon:"activity",category:"Components",selfClosing:!1,container:!0,wrappable:!1,template:`[timeline layout="vertical" theme="modern"]
|
|
36
|
+
[/carousel]`,children:{name:"slide",min:2,max:12},quickAttrs:["height-mode","height","arrow-position","background","arrow-background","arrow-color"],attrs:[{name:"autoplay",type:"checkbox",label:"Autoplay",domma:"carousel.autoplay"},{name:"interval",type:"number",label:"Interval (ms)",domma:"carousel.interval"},{name:"loop",type:"checkbox",label:"Loop",default:!0,domma:"carousel.loop"},{name:"animation",type:"select",label:"Animation",options:[["slide","Slide"],["fade","Fade"],["crossfade","Crossfade"]],domma:"carousel.animation"},{name:"animation-duration",type:"number",label:"Animation duration (ms)",domma:"carousel.animationDuration"},{name:"animation-easing",type:"text",label:"Animation easing",domma:"carousel.animationEasing"},{name:"height-mode",type:"select",label:"Image height",options:[["crop","Top-aligned crop (shortest image)"],["average","Average of shortest and tallest images"]],domma:"carousel.heightMode"},{name:"height",type:"number",label:"Fixed height (px, optional)",domma:"carousel.height"},{name:"mobile-popup",type:"checkbox",label:"Open carousel cards in a popup on mobile"},{name:"arrow-position",type:"select",label:"Arrow position",options:[["middle","Middle"],["top","Top"],["bottom","Bottom"]]},{name:"background",type:"colour",label:"Background colour"},{name:"arrow-background",type:"colour",label:"Arrow background"},{name:"arrow-color",type:"colour",label:"Arrow colour"},{name:"id",type:"text",label:"ID"}]},{name:"slide",label:"Slide",icon:"image",category:"Components",child:!0,selfClosing:!1,container:!0,wrappable:!1,template:'[slide title="Slide title" image="/media/photo.jpg"]Caption[/slide]',inline:!0,attrs:[{name:"title",type:"text",label:"Title"},{name:"image",type:"image",label:"Image"}]},{name:"countdown",label:"Countdown",icon:"stopwatch",category:"Components",selfClosing:!0,container:!1,wrappable:!1,template:'[countdown to="2026-12-31" format="DD:HH:mm:ss" /]',attrs:[{name:"to",type:"text",label:"Target date (ISO)"},{name:"duration",type:"number",label:"Duration (seconds)"},{name:"format",type:"select",label:"Format",options:[["mm:ss","mm:ss"],["HH:mm:ss","HH:mm:ss"],["DD:HH:mm:ss","DD:HH:mm:ss"]],domma:"timer.format"},{name:"id",type:"text",label:"ID"}]},{name:"timeline",label:"Timeline",icon:"activity",category:"Components",selfClosing:!1,container:!0,wrappable:!1,template:`[timeline layout="vertical" theme="modern"]
|
|
37
37
|
[event title="Launch" date="2025-01-15" status="completed"]Launched.[/event]
|
|
38
38
|
[/timeline]`,children:{name:"event",min:1,max:20},custom:"timeline",attrs:[{name:"layout",type:"select",label:"Layout",options:[["vertical","Vertical"],["centred","Centred"],["horizontal","Horizontal"]],domma:"progression.layout",dommaValues:{centred:"centered"}},{name:"theme",type:"select",label:"Theme",options:[["minimal","Minimal"],["corporate","Corporate"],["modern","Modern"]],domma:"progression.theme"},{name:"mode",type:"select",label:"Mode",options:[["timeline","Timeline"],["roadmap","Roadmap"]],domma:"progression.mode"},{name:"class",type:"text",label:"CSS class"},{name:"id",type:"text",label:"ID"}]},{name:"event",label:"Event",icon:"dot",category:"Components",child:!0,selfClosing:!1,container:!0,wrappable:!1,template:'[event title="Milestone" date="2025-01-15" status="completed"]Description[/event]',inline:!0,attrs:[{name:"title",type:"text",label:"Title"},{name:"date",type:"text",label:"Date"},{name:"status",type:"select",label:"Status",options:[["planned","Planned"],["in-progress","In progress"],["completed","Completed"],["blocked","Blocked"]]},{name:"icon",type:"icon",label:"Icon"}]},{name:"hero",label:"Hero",icon:"hero",category:"Content",selfClosing:!1,container:!0,wrappable:!0,template:`[hero title="Welcome" tagline="Build something great" size="lg" variant="gradient-blue"]
|
|
39
39
|
Optional body content.
|
package/package.json
CHANGED
|
@@ -7,12 +7,19 @@ import {SHORTCODE_EXPIRY_FIELDS} from '../../public/js/shortcode-expiry.mjs';
|
|
|
7
7
|
|
|
8
8
|
const STATE_FILE = path.resolve('content/shortcode-expiry.json');
|
|
9
9
|
const EXPIRY_KEYS = new Set(['expires-at', 'expire-after', 'expire-views', 'expire-scope', 'expire-ip', 'expire-session', 'expiry-id']);
|
|
10
|
+
// What can hide a shortcode. expire-scope and expiry-id only say how a rule counts, so a tag carrying
|
|
11
|
+
// just those (the insert forms used to write expire-scope="ip" on every child) is not expiring.
|
|
12
|
+
const RULE_KEYS = new Set(['expires-at', 'expire-after', 'expire-views', 'expire-ip', 'expire-session']);
|
|
10
13
|
let stateQueue = Promise.resolve();
|
|
11
14
|
|
|
12
15
|
export function hasShortcodeExpiry(attrs) {
|
|
13
|
-
return Object.keys(attrs || {}).some(key =>
|
|
16
|
+
return Object.keys(attrs || {}).some(key => RULE_KEYS.has(key));
|
|
14
17
|
}
|
|
15
18
|
|
|
19
|
+
const hasExpiryAttrs = (attrs) => Object.keys(attrs || {}).some(key => EXPIRY_KEYS.has(key));
|
|
20
|
+
// A quoted value is matched whole first, so an expiry name inside one (title="Set expire-scope here") is left alone
|
|
21
|
+
const withoutExpiryAttrs = (raw) => raw.replace(/("[^"]*"|'[^']*')|\s+(?:expires-at|expire-after|expire-views|expire-scope|expire-ip|expire-session|expiry-id)(?![\w-])(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s\]]+))?/gi, (match, quoted) => quoted || '');
|
|
22
|
+
|
|
16
23
|
export function validSessionCookie(value, secret) {
|
|
17
24
|
if (!value || !secret) return '';
|
|
18
25
|
const [id, signature, extra] = String(value).split('.');
|
|
@@ -56,6 +63,8 @@ async function applyShortcodeExpiryUnlocked(markdown, {urlPath = '/', ip = '', s
|
|
|
56
63
|
}));
|
|
57
64
|
const ranges = [];
|
|
58
65
|
const stack = [];
|
|
66
|
+
// Tags with a counting attribute but no rule: shown as they are, the attribute taken off
|
|
67
|
+
const strays = [];
|
|
59
68
|
for (let i = 0; i < tokens.length; i++) {
|
|
60
69
|
const t = tokens[i];
|
|
61
70
|
if (t.close) {
|
|
@@ -68,6 +77,7 @@ async function applyShortcodeExpiryUnlocked(markdown, {urlPath = '/', ip = '', s
|
|
|
68
77
|
}
|
|
69
78
|
} else {
|
|
70
79
|
t.expiring = hasShortcodeExpiry(t.attrs);
|
|
80
|
+
if (!t.expiring && hasExpiryAttrs(t.attrs)) strays.push(t);
|
|
71
81
|
if (t.self || /\/\s*$/.test(t.attrsText)) {
|
|
72
82
|
if (t.expiring) ranges.push({start:t.start, end:t.end, token:t});
|
|
73
83
|
} else stack.push(t);
|
|
@@ -75,7 +85,11 @@ async function applyShortcodeExpiryUnlocked(markdown, {urlPath = '/', ip = '', s
|
|
|
75
85
|
}
|
|
76
86
|
// Treat malformed/unclosed expiry tags as extending to the end of the source.
|
|
77
87
|
for (const open of stack) if (open.expiring) ranges.push({start:open.start, end:markdown.length, token:open});
|
|
78
|
-
if (!ranges.length)
|
|
88
|
+
if (!ranges.length) {
|
|
89
|
+
let output = markdown;
|
|
90
|
+
for (const t of strays.sort((a,b)=>b.start-a.start)) output = output.slice(0,t.start) + withoutExpiryAttrs(t.raw) + output.slice(t.end);
|
|
91
|
+
return {markdown:output, hasExpiry:false};
|
|
92
|
+
}
|
|
79
93
|
|
|
80
94
|
const now = Date.now();
|
|
81
95
|
let state = {};
|
|
@@ -129,9 +143,9 @@ async function applyShortcodeExpiryUnlocked(markdown, {urlPath = '/', ip = '', s
|
|
|
129
143
|
await fs.rename(temp, STATE_FILE);
|
|
130
144
|
}
|
|
131
145
|
const edits = collapsed.map(range => ({start:range.start, end:range.end, value:''}));
|
|
132
|
-
for (const token of cleanOpeners) {
|
|
146
|
+
for (const token of [...cleanOpeners, ...strays]) {
|
|
133
147
|
if (collapsed.some(range => range.start <= token.start && range.end >= token.end)) continue;
|
|
134
|
-
const cleaned = token.raw
|
|
148
|
+
const cleaned = withoutExpiryAttrs(token.raw);
|
|
135
149
|
if (cleaned !== token.raw) edits.push({start:token.start, end:token.end, value:cleaned});
|
|
136
150
|
}
|
|
137
151
|
let output = markdown;
|