@mapled/vanilla 0.2.3 → 0.4.0

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/README.md CHANGED
@@ -13,7 +13,7 @@
13
13
  <html lang="en">
14
14
  <head>
15
15
  <title data-mapled-bind="home.headline">Studio Nord</title>
16
- <script src="https://cdn.jsdelivr.net/npm/@mapled/vanilla@0.2.3/dist/mapled.js" data-mapled-key="mk_live_…" defer></script>
16
+ <script src="https://cdn.jsdelivr.net/npm/@mapled/vanilla@0.4.0/dist/mapled.js" data-mapled-key="mk_live_…" defer></script>
17
17
  </head>
18
18
  <body>
19
19
  <h1 data-mapled-bind="home.headline">Websites, built by hand</h1>
@@ -58,6 +58,35 @@ The key is the project's **delivery key** (Mapled: Integrations → Your site).
58
58
  <li><strong>Designed</strong> by people</li>
59
59
  </ul>
60
60
 
61
+ <!-- a components field: the blocks in their order, each from the template of its type -->
62
+ <main data-mapled-each="home.sections" data-mapled-expand="sections.picks">
63
+ <template data-mapled-type="hero">
64
+ <section class="hero">
65
+ <h2 data-mapled-bind="heading"></h2>
66
+ <a data-mapled-bind="button-label" data-mapled-bind-href="button-link"></a>
67
+ </section>
68
+ </template>
69
+ <template data-mapled-type="text">
70
+ <section data-mapled-bind="body" data-mapled-format="markdown"></section>
71
+ </template>
72
+ <!-- a block's relation: the posts it picks, read along by data-mapled-expand -->
73
+ <template data-mapled-type="featured">
74
+ <section>
75
+ <h2 data-mapled-bind="heading"></h2>
76
+ <ul data-mapled-each="picks">
77
+ <template>
78
+ <li><a data-mapled-link="/post.html?slug={slug}" data-mapled-bind="title"></a></li>
79
+ </template>
80
+ </ul>
81
+ </section>
82
+ </template>
83
+ <!-- every other type of block -->
84
+ <template>
85
+ <section><h2 data-mapled-bind="heading"></h2></section>
86
+ </template>
87
+ <section><h2>Studio Nord</h2></section>
88
+ </main>
89
+
61
90
  <!-- a collection: the template once per record -->
62
91
  <ul data-mapled-list="posts" data-mapled-sort="-date" data-mapled-limit="5" data-mapled-filter="featured=true">
63
92
  <template>
@@ -71,11 +100,12 @@ The key is the project's **delivery key** (Mapled: Integrations → Your site).
71
100
  </ul>
72
101
  ```
73
102
 
74
- - **Paths.** From the document a path starts with a single's key: `home.headline`, `home.seo.title` for a field inside a group. Inside `data-mapled-list`, `data-mapled-each` and `data-mapled-record` it starts at the record: `title`, `author.name` for a linked record — name the relation in `data-mapled-expand="author"` on the list or the record element.
103
+ - **Paths.** From the document a path starts with a single's key: `home.headline`, `home.seo.title` for a field inside a group. Inside `data-mapled-list`, `data-mapled-each` and `data-mapled-record` it starts at the record: `title`, `author.name` for a linked record — name the relation in `data-mapled-expand="author"` on the list or the record element (on the element itself for a single). `data-mapled-each="related"` repeats the records a relation the read expanded links to, the template once per record.
75
104
  - **`data-mapled-bind`** fills the element with text — on an `<img>`, with the picture. `data-mapled-format` says how: `markdown` for a rich text field, `date`, `datetime` and `number` for those, written the way the nearest `lang` attribute says.
76
105
  - **`data-mapled-bind-…`** fills an attribute: `href` (on `a`, `area`), `src` (`img`, `video`, `audio`, `source`), `alt`, `title`, `aria-label`, `placeholder`, `datetime`. Nothing else — no `style`, no `class`, no `on…`.
77
106
  - **`data-mapled-list`** reads a collection: `data-mapled-sort="-date"`, `data-mapled-limit` (1–100), `data-mapled-filter="featured=true; category=news"`. Whatever else sits inside the element is its fallback and leaves when records arrive; an element with `data-mapled-empty` shows when there are none.
78
107
  - **`data-mapled-link`** builds an address from a template. Every `{field}` is percent-encoded before it goes in, so a value fills its place and nothing more.
108
+ - **Blocks.** A components field holds blocks of different types — a hero, a text, a gallery — in the order editors put them, and editors add, remove and reorder them in Mapled. `data-mapled-each` repeats them: each block takes the `<template data-mapled-type="…">` of its type (the type's key, as `MAPLED.md` lists it), or else the `<template>` without a type. A block the page has neither for is left out, and the report says `no-template`. Inside, paths start at the block: `heading`, `button-link`. A block's group — a pricing block's tiers — repeats inside the block's template with a `data-mapled-each` of its own, `data-mapled-each="tiers"`, and its paths start at the item: `name`, `price`. A block's relation — the posts a featured block picks — comes along when the read names the field and the sub-field, `data-mapled-expand="sections.picks"` on the each (on the list or the record element for a collection's records): inside the block's template `data-mapled-each="picks"` repeats the linked records, their paths starting at the record (`title`, `slug`), and `lead.title` reads a relation to one record. A JSON field's objects that carry a `_type` pick a template the same way; a list's records, a group's items and a relation's records have no type and take the `<template>` without one.
79
109
 
80
110
  ### One record per page
81
111
 
@@ -114,10 +144,11 @@ The key is the project's **delivery key** (Mapled: Integrations → Your site).
114
144
  | `empty` | The record is there, a value at this path isn't: an editor left the field empty — or the key is misspelled | Nothing: the text is emptied, a picture is hidden, an attribute is removed (`alt` becomes `""`) |
115
145
  | `failed` | The read didn't come back | The HTML you wrote |
116
146
  | `unsafe-url` | An address that isn't `http:`, `https:` — or `mailto:`, `tel:` in a link — or that carries credentials; a value that can't go into a link template | The HTML you wrote |
117
- | `type` | A value that has no text: a group bound as text, a word where a date goes | The HTML you wrote |
147
+ | `type` | A value that has no text: a group bound as text, a word where a date goes, a relation an each repeats that the read didn't expand | The HTML you wrote |
118
148
  | `refused-element` | `<script>`, `<style>`, `<iframe>`, `<object>`, `<embed>`, `<base>`, `<link>`, `<meta>`, `<template>`, `<noscript>` are never written into | The HTML you wrote |
119
149
  | `unsupported` | An attribute Mapled doesn't read — `data-mapled-bind-style`, a misspelled name — or a list without a `<template>` | The HTML you wrote |
120
150
  | `bad-path` | A path, a key or an option that isn't one | The HTML you wrote |
151
+ | `no-template` | A block of a type the page has no `<template data-mapled-type>` for, and no `<template>` without a type to take it | Nothing for that block; the other blocks show |
121
152
 
122
153
  ```html
123
154
  <!-- debug.html -->
@@ -187,11 +218,12 @@ if (report.state === "fallback") console.info("Showing the page as written.");
187
218
  | `data-mapled-link` | `a`, `area` | an address template with `{field}` places |
188
219
  | `data-mapled-list` | an element with a `<template>` | the collection to repeat the template for |
189
220
  | `data-mapled-sort`, `data-mapled-limit`, `data-mapled-filter` | with `data-mapled-list` | the order, how many, which |
190
- | `data-mapled-each` | an element with a `<template>` | the path of a group to repeat the template for |
221
+ | `data-mapled-each` | an element with a `<template>` | the path of a group, a components field or an expanded relation to repeat the template for |
222
+ | `data-mapled-type` | a `<template>` of an each | the type of block it shows |
191
223
  | `data-mapled-empty` | inside a list or an each | shown when there is nothing to repeat |
192
224
  | `data-mapled-record` | an element | the collection of the one record its content shows |
193
225
  | `data-mapled-slug`, `data-mapled-slug-param` | with `data-mapled-record` | the record's slug; the query parameter that holds it |
194
- | `data-mapled-expand` | a list, a record, a bound element | relation fields to read along |
226
+ | `data-mapled-expand` | a list, a record, a bound element, an each | relation fields to read along — `sections.picks` for a relation inside the blocks of `sections` |
195
227
  | `data-mapled-form` | a `<form>` | the key of the Mapled form it posts to |
196
228
  | `data-mapled-consent`, `data-mapled-form-sent`, `data-mapled-form-failed`, `data-mapled-end-preview` | inside a form; anywhere | the consent checkbox; the two outcomes; a way out of preview |
197
229
  | `data-mapled-state`, `data-mapled-preview`, `data-mapled-form-state` | set by the script | `<html>`: how the fill went, whether drafts are shown; a form: `sending`, `sent`, `failed` |
package/dist/mapled.js CHANGED
@@ -1,18 +1,18 @@
1
- /*! @mapled/vanilla 0.2.3 | MIT | https://mapled.io */
2
- "use strict";(()=>{var $t=Object.defineProperty;var Lt=(e,t,n)=>t in e?$t(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var be=(e,t,n)=>Lt(e,typeof t!="symbol"?t+"":t,n);var we="mapled-preview",ie="mapled:preview",Ut=/^mpv_[A-Za-z0-9]{16,96}$/,Ze=/^mps_[A-Za-z0-9]{16,96}$/,Ve=new WeakMap,Nt=4e3;function ke(){if(typeof window>"u"||typeof document>"u")return null;try{let e=window.sessionStorage,t=Ve.get(window);return t||Ve.set(window,t={memory:null,exchanging:null,epoch:0}),{location:window.location,history:window.history,sessionStorage:e,page:t}}catch{return null}}function It(e){try{let t=e.getItem(ie);if(!t)return null;let n=JSON.parse(t),r=typeof n?.expiresAt=="string"?Date.parse(n.expiresAt):NaN;return typeof n?.draftToken!="string"||!Ze.test(n.draftToken)||!(r>Date.now())?(e.removeItem(ie),null):{draftToken:n.draftToken,expiresAt:n.expiresAt}}catch{return null}}function K(e){let t=It(e.sessionStorage);if(t)return t;let n=e.page.memory;return n&&Date.parse(n.expiresAt)>Date.now()?n:(e.page.memory=null,null)}function B(){let e=ke();return e?K(e):null}function Ye(e){let t;try{t=new URL(e.location.href)}catch{return null}let n=t.searchParams.get(we);if(n===null)return null;t.searchParams.delete(we);try{e.history.replaceState(e.history.state,"",`${t.pathname}${t.search}${t.hash}`)}catch{}return n}function Se(){let e=ke();if(e){e.page.memory=null,e.page.epoch++,e.page.exchanging=null,Ye(e);try{e.sessionStorage.removeItem(ie)}catch{}}}function Je(e={}){let t=ke();if(!t)return Promise.resolve(null);let n=Ye(t);if(n===null)return t.page.exchanging?t.page.exchanging.done:Promise.resolve(K(t));if(!Ut.test(n))return Promise.resolve(K(t));if(t.page.exchanging?.token===n)return t.page.exchanging.done;let r=(e.apiUrl??"https://api.mapled.io").replace(/\/+$/,""),s=(e.appUrl??"https://app.mapled.io").replace(/\/+$/,""),o=e.fetch??fetch,c=++t.page.epoch,a=(async()=>{try{let i=await o(`${r}/v1/delivery/preview/exchange`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({token:n}),cache:"no-store"});if(i.ok){let p=await i.json();if(typeof p.draftToken!="string"||typeof p.expiresAt!="string"||!Ze.test(p.draftToken)||!(Date.parse(p.expiresAt)>Date.now())||t.page.epoch!==c)return K(t);let d={draftToken:p.draftToken,expiresAt:p.expiresAt};t.page.memory=d;try{t.sessionStorage.setItem(ie,JSON.stringify(d))}catch{}return d}if(i.status===401&&t.page.epoch===c){let p=await i.json().catch(()=>null),d=p?.error?.projectId;if(t.page.epoch===c&&p?.error?.code==="PREVIEW_EXPIRED"&&typeof d=="string"&&/^[0-9a-f-]{8,64}$/i.test(d))return t.location.assign(`${s}/preview/expired?project=${encodeURIComponent(d)}`),await new Promise(l=>setTimeout(l,Nt)),K(t)}return K(t)}catch{return K(t)}})(),f={token:n,done:a};return t.page.exchanging=f,a.then(()=>{t.page.exchanging===f&&(t.page.exchanging=null)}),a}async function Qe(e){return(await Je(e))?.draftToken??null}function Ae(e){if(!e||typeof e!="object")return;let{release:t,publishedAt:n}=e;if(t===null)return n===null?null:void 0;if(!(!Number.isInteger(t)||t<1||typeof n!="string"))return{release:t,publishedAt:n}}var Ft=1e4;function Dt(e,t){let n=typeof document>"u"?void 0:globalThis.performance?.timeOrigin;if(n===void 0)return!1;let r=Date.parse(t.get("date")??""),s=Number.isNaN(r)?0:r+(Number(t.get("age"))||0)*1e3-Date.now();return Date.parse(e)>n+s-Ft}function et(e,t){return(n,r)=>{if(e!==void 0)return e;let s=t?.();return s!==void 0?s:Dt(n.publishedAt,r)?null:n.release}}function tt(e,t,n){let r=typeof e.key=="string"&&e.key.length>0;if(!r&&!e.endpoint)throw new Error("Mapled: watchRelease needs an endpoint or a delivery key.");let s=r?`${(e.apiUrl??"https://api.mapled.io").replace(/\/+$/,"")}/v1/delivery/release`:e.endpoint,o=r?{accept:"application/json","x-mapled-key":e.key}:{accept:"application/json"},c=(r?Math.max(15,e.interval??60):Math.max(2,e.interval??10))*1e3,a=e.fetch??fetch,f=typeof document>"u"?null:document,i,p=null,d=0,l=null,g=0,S=!1,E,M=null,b=()=>!f||f.visibilityState!=="hidden",$=()=>{S||!b()||(E=setTimeout(L,Math.min(c*2**g,3e5)))};async function L(){if(S||M)return;let U=new AbortController;M=U;let N=null;try{let X=await a(s,{cache:"no-cache",headers:o,signal:U.signal}),O=X.ok?Ae(await X.json()):void 0;if(S)return;O===void 0?g+=1:(g=0,i===void 0&&(i=O?t(O,X.headers):null),O&&O.release>(p?.release??0)&&(p=O),O&&O.release>(i??0)?(N={next:O,previous:i},i=O.release,d=O.release,l=null):O&&l!==null&&typeof i=="number"&&O.release>=i&&i>d&&(N={next:O,previous:l},d=i,l=null))}catch{if(S)return;g+=1}finally{M===U&&(M=null)}$(),N&&e.onPublish(N.next,N.previous)}let C=()=>{clearTimeout(E),b()&&L()};f?.addEventListener("visibilitychange",C);let z=n?.(U=>{if(S||typeof i!="number"||U>=i||i<=d||(l=l===null?U:Math.min(l,U),p===null||p.release<i))return;d=i;let N=l;l=null,e.onPublish(p,N)});return b()&&L(),()=>{S=!0,clearTimeout(E),M?.abort(),z?.(),f?.removeEventListener("visibilitychange",C)}}function nt(e){let t={};return e.forEach((n,r)=>{typeof n!="string"||r in t||(t[r]=n)}),t}async function Re(e,t,n){if(!n?.key)throw new Error("Mapled: a delivery key is required.");let r=(n.apiUrl??"https://api.mapled.io").replace(/\/+$/,""),s=typeof HTMLFormElement<"u"&&t instanceof HTMLFormElement?nt(new FormData(t)):typeof FormData<"u"&&t instanceof FormData?nt(t):{...t},o=n.page??(typeof window<"u"&&typeof document<"u"?window.location.pathname:void 0),c={...s};n.consent&&(c._consent=n.consent),o&&c._page===void 0&&(c._page=o),n.test&&(c._test=!0);let a=B()?.draftToken,f={"content-type":"application/json","x-mapled-key":n.key};a&&(f["x-mapled-draft"]=a);let i;try{i=await(n.fetch??fetch)(`${r}/v1/delivery/forms/${encodeURIComponent(e)}`,{method:"POST",headers:f,body:JSON.stringify(c)})}catch{return{ok:!1,status:0,code:"NETWORK",message:"Mapled couldn't be reached. Try again in a minute."}}if(i.ok)return{ok:!0};let p=`The submission wasn't accepted (${i.status}).`,d;try{let l=await i.json();l.error?.message&&(p=l.error.message),typeof l.error?.code=="string"&&(d=l.error.code)}catch{}return{ok:!1,status:i.status,code:d,message:p}}var ve=/^[a-z0-9][a-z0-9-]{0,63}$/,rt=new Set;function _t(e){if(typeof process<"u")return;let t=e?.aliases;if(!(!t||typeof t!="object")){for(let[n,r]of Object.entries(t))if(!(!r||typeof r!="object"||!ve.test(n)))for(let[s,o]of Object.entries(r)){if(typeof o!="string"||!ve.test(s)||!ve.test(o))continue;let c=`${n}.${s}`;rt.has(c)||(rt.add(c),console.warn(`[mapled] \u201C${s}\u201D in \u201C${n}\u201D was renamed to \u201C${o}\u201D. The old key keeps working until its alias is removed in Mapled \u2014 use \u201C${o}\u201D instead.`))}}}function it(e,t={}){let n=new URLSearchParams;t.width&&n.set("w",String(t.width)),t.height&&n.set("h",String(t.height)),t.fit&&n.set("fit",t.fit),t.format&&n.set("fmt",t.format),t.quality&&n.set("q",String(t.quality));let r=n.toString(),s=t.files?(t.files[e]??t.files[e.toLowerCase()])?.url:void 0;return typeof s=="string"&&s?r?`${s}${s.includes("?")?"&":"?"}${r}`:s:`${(t.apiUrl??"https://api.mapled.io").replace(/\/+$/,"")}/files/${encodeURIComponent(e)}${r?`?${r}`:""}`}var W=class extends Error{constructor(n,r,s){super(r);be(this,"status");be(this,"code");this.name="MapledError",this.status=n,this.code=s}},st=e=>Number.isInteger(e)&&e>=1,ot=()=>new Error("Mapled: release must be a positive whole number.");function lt(e){let t=(e.apiUrl??"https://api.mapled.io").replace(/\/+$/,"");if(!e.key)throw new Error("Mapled: a delivery key is required.");if(e.release!==void 0&&!st(e.release))throw ot();let n=(d,l)=>(e.fetch??fetch)(d,l),r,s=new Set;async function o(){return e.draft===null?null:typeof e.draft=="string"?e.draft||null:typeof e.draft=="function"?await e.draft()||null:Qe({apiUrl:t,appUrl:e.appUrl,fetch:e.fetch})}async function c(d){let l=`Mapled request failed (${d.status}).`,g;try{let S=await d.json();S.error?.message&&(l=S.error.message),typeof S.error?.code=="string"&&(g=S.error.code)}catch{}return new W(d.status,l,g)}async function a(d,l,g){let S=await o(),E=g.release??e.release;if(E!==void 0&&!st(E))throw ot();E!==void 0&&!S&&l.set("release",String(E));let M=g.locale||e.locale;M&&l.set("locale",M);let b=l.toString(),$=await n(`${t}${d}${b?`?${b}`:""}`,{headers:S?{"x-mapled-key":e.key,"x-mapled-draft":S}:{"x-mapled-key":e.key},...S?{cache:"no-store"}:{},...g.signal?{signal:g.signal}:{}});if(!$.ok)throw await c($);let L=await $.json();if(!S){let C=Number($.headers.get("x-mapled-release"));if(Number.isInteger(C)&&C>=1){r=r===void 0?C:Math.min(r,C);for(let z of s)Promise.resolve().then(()=>z(C))}}return _t(L),L}let f=(d,l)=>(l.expand?.length&&d.set("expand",l.expand.join(",")),l.fields?.length&&d.set("fields",l.fields.join(",")),d),i=async(d,l)=>{try{return(await a(d,f(new URLSearchParams,l),l)).record}catch(g){if(g instanceof W&&g.status===404&&g.code!=="RELEASE_NOT_FOUND")return null;throw g}};return{async getRecords(d,l={}){let g=new URLSearchParams;for(let[S,E]of Object.entries(l.filter??{}))if(E!==null&&typeof E=="object")for(let[M,b]of Object.entries(E))b!==void 0&&g.set(`filter[${S}][${M}]`,Array.isArray(b)?b.join(","):String(b));else g.set(`filter[${S}]`,String(E));return l.sort&&g.set("sort",l.sort),l.limit!==void 0&&g.set("limit",String(l.limit)),l.offset!==void 0&&g.set("offset",String(l.offset)),l.search&&g.set("search",l.search),f(g,l),a(`/v1/delivery/collections/${encodeURIComponent(d)}/records`,g,l)},getRecord(d,l,g={}){return i(`/v1/delivery/collections/${encodeURIComponent(d)}/records/${encodeURIComponent(l)}`,g)},getRecordBySlug(d,l,g={}){return i(`/v1/delivery/collections/${encodeURIComponent(d)}/records/by-slug/${encodeURIComponent(l)}`,g)},getSingle(d,l={}){return i(`/v1/delivery/singles/${encodeURIComponent(d)}`,l)},async isPreview(){return await o()!==null},watch(d,l={}){return tt({key:e.key,apiUrl:t,interval:l.interval,onPublish:d,fetch:e.fetch},et(l.from,()=>r),g=>(s.add(g),()=>{s.delete(g)}))},async getRelease(d={}){let l=await n(`${t}/v1/delivery/release`,{headers:{"x-mapled-key":e.key},cache:"no-cache",...d.signal?{signal:d.signal}:{}});if(!l.ok)throw await c(l);let g=Ae(await l.json());if(g===void 0)throw new Error("Mapled: the release pointer didn't come back as one \u2014 check the API origin.");return g}}}var jt=/^[a-z0-9][a-z0-9_-]{0,63}$/;function Z(e){if(typeof e!="string")return null;let t=e.trim().split(".");if(t.length>8)return null;for(let n of t)if(!jt.test(n))return null;return t}var le=(e,t)=>e!==null&&typeof e=="object"&&!Array.isArray(e)&&Object.prototype.hasOwnProperty.call(e,t)?e[t]:void 0;function Te(e,t){let n=e.data,r=e.expanded;for(let s=0;s<t.length;s++){let o=t[s],c=s<t.length-1?le(r,o):void 0;if(c!==void 0){if(c===null||Array.isArray(c))return;n=le(c,"data"),r=le(c,"expanded");continue}if(n=le(n,o),r=void 0,n===void 0)return}return n}var Y=e=>e==null||e===""||Array.isArray(e)&&e.length===0;function xe(e){return typeof e=="string"?e:typeof e=="number"&&Number.isFinite(e)?String(e):typeof e=="boolean"?e?"true":"false":Array.isArray(e)&&e.every(t=>typeof t=="string"||typeof t=="number")?e.join(", "):null}var Kt=new Set(["http:","https:","mailto:","tel:"]),Bt=new Set(["http:","https:"]),qt=2048;function q(e,t,n){if(typeof e!="string"||e.length>qt)return null;let r;try{r=new URL(e,t)}catch{return null}return!(n==="link"?Kt:Bt).has(r.protocol)||r.username!==""||r.password!==""?null:r.href}var Ht=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,at=e=>typeof e=="string"&&Ht.test(e);function ut(e,t,n){let r=[],s=e.replace(/\{([^{}]*)\}/g,(c,a)=>{let f=Z(a);if(!f)return r.push({ok:!1,reason:"bad-path",path:a.trim().slice(0,80)}),"";let i=n(f);if(typeof i!="string"&&typeof i!="number"||i==="")return r.push({ok:!1,reason:"empty",path:f.join(".")}),"";try{return encodeURIComponent(String(i))}catch{return r.push({ok:!1,reason:"unsafe-url",path:f.join(".")}),""}});if(r[0])return r[0];let o=q(s,t,"link");return o===null?{ok:!1,reason:"unsafe-url",path:e.slice(0,80)}:{ok:!0,url:o}}var zt=1e5,dt=8,ft=2048,Wt="!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",ct={amp:"&",lt:"<",gt:">",quot:'"',apos:"'",nbsp:"\xA0",copy:"\xA9",reg:"\xAE",trade:"\u2122",mdash:"\u2014",ndash:"\u2013",hellip:"\u2026",laquo:"\xAB",raquo:"\xBB"};function pt(e,t,n){let r=t.createDocumentFragment();if(typeof e!="string"||e==="")return r;let s=e.replace(/\r\n?/g,`
3
- `).replace(/\t/g," ").replace(/\u0000/g,"\uFFFD"),o={doc:t,base:n};if(s.length>zt){for(let c of s.split(/\n{2,}/))c.trim()!==""&&(P(o,"p",r).textContent=c.trim());return r}return $e(o,s.split(`
4
- `),r,0),r}function P(e,t,n){let r=e.doc.createElement(t);return n.appendChild(r),r}var Ee=e=>e.trim()==="",Q=e=>e.length-e.trimStart().length;function mt(e){let t=Q(e);if(t>3)return null;let n=0;for(;n<7&&e[t+n]==="#";)n++;if(n===0||n>6)return null;let r=e[t+n];if(r!==void 0&&r!==" ")return null;let s=e.slice(t+n).trim(),o=s.length;for(;o>0&&s[o-1]==="#";)o--;return o<s.length&&(o===0||s[o-1]===" ")&&(s=s.slice(0,o).trim()),{level:n,text:s}}function Ce(e){if(Q(e)>3)return!1;let t=e.replace(/ /g,""),n=t[0];if(t.length<3||n!=="-"&&n!=="*"&&n!=="_")return!1;for(let r of t)if(r!==n)return!1;return!0}function Me(e){let t=/^ {0,3}(`{3,}|~{3,})/.exec(e);if(!t)return null;let n=t[1][0];return n==="`"&&e.slice(t[0].length).includes("`")?null:{mark:n,size:t[1].length}}function J(e){let t=/^( {0,3})([-*+]|\d{1,9}[.)])( +|$)/.exec(e);if(!t)return null;let n=t[2],r=t[3].length,s=n.length>1||/\d/.test(n);return{indent:t[1].length,width:n.length+(r>=1&&r<=4?r:1),ordered:s,start:s?parseInt(n,10):1,rest:e.slice(t[0].length)}}var Pe=e=>/^ {0,3}>/.test(e);function Gt(e){if(mt(e)!==null||Me(e)!==null||Pe(e)||Ce(e))return!0;let t=J(e);return t!==null&&t.rest!==""&&(!t.ordered||t.start===1)}function $e(e,t,n,r){if(r>=dt){let o=t.join(`
5
- `).trim();o!==""&&(P(e,"p",n).textContent=o);return}let s=0;for(;s<t.length;){let o=t[s];if(Ee(o)){s++;continue}let c=Me(o);if(c){let p=[],d=Q(o);for(s++;s<t.length;){let l=t[s],g=Me(l);if(g&&g.mark===c.mark&&g.size>=c.size&&l.trim().length===g.size)break;p.push(l.slice(Math.min(d,Q(l)))),s++}s++,P(e,"code",P(e,"pre",n)).textContent=p.length>0?`${p.join(`
1
+ /*! @mapled/vanilla 0.4.0 | MIT | https://mapled.io */
2
+ "use strict";(()=>{var mn=Object.defineProperty;var gn=(e,t,n)=>t in e?mn(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var We=(e,t,n)=>gn(e,typeof t!="symbol"?t+"":t,n);var qe="mapled-preview",Ne="mapled:preview",hn=/^mpv_[A-Za-z0-9]{16,96}$/,yt=/^mps_[A-Za-z0-9]{16,96}$/,yn=/^(?:https:\/\/[a-z0-9.-]+|http:\/\/(?:localhost|127\.0\.0\.1))(?::[0-9]{1,5})?$/;function kt(e){let t={draftToken:e.draftToken,expiresAt:e.expiresAt};return e.mode==="edit"&&typeof e.appOrigin=="string"&&yn.test(e.appOrigin)&&(t.mode="edit",t.appOrigin=e.appOrigin),t}var ht=new WeakMap,kn=4e3;function Ve(){if(typeof window>"u"||typeof document>"u")return null;try{let e=window.sessionStorage,t=ht.get(window);return t||ht.set(window,t={memory:null,exchanging:null,epoch:0}),{location:window.location,history:window.history,sessionStorage:e,page:t}}catch{return null}}function bn(e){try{let t=e.getItem(Ne);if(!t)return null;let n=JSON.parse(t),r=typeof n?.expiresAt=="string"?Date.parse(n.expiresAt):NaN;return typeof n?.draftToken!="string"||!yt.test(n.draftToken)||!(r>Date.now())?(e.removeItem(Ne),null):kt({...n,draftToken:n.draftToken,expiresAt:n.expiresAt})}catch{return null}}function te(e){let t=bn(e.sessionStorage);if(t)return t;let n=e.page.memory;return n&&Date.parse(n.expiresAt)>Date.now()?n:(e.page.memory=null,null)}function J(){let e=Ve();return e?te(e):null}function bt(e){let t;try{t=new URL(e.location.href)}catch{return null}let n=t.searchParams.get(qe);if(n===null)return null;t.searchParams.delete(qe);try{e.history.replaceState(e.history.state,"",`${t.pathname}${t.search}${t.hash}`)}catch{}return n}function Ge(){let e=Ve();if(e){e.page.memory=null,e.page.epoch++,e.page.exchanging=null,bt(e);try{e.sessionStorage.removeItem(Ne)}catch{}}}function wt(e={}){let t=Ve();if(!t)return Promise.resolve(null);let n=bt(t);if(n===null)return t.page.exchanging?t.page.exchanging.done:Promise.resolve(te(t));if(!hn.test(n))return Promise.resolve(te(t));if(t.page.exchanging?.token===n)return t.page.exchanging.done;let r=(e.apiUrl??"https://api.mapled.io").replace(/\/+$/,""),s=(e.appUrl??"https://app.mapled.io").replace(/\/+$/,""),i=e.fetch??fetch,u=++t.page.epoch,a=(async()=>{try{let l=await i(`${r}/v1/delivery/preview/exchange`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({token:n}),cache:"no-store"});if(l.ok){let g=await l.json();if(typeof g.draftToken!="string"||typeof g.expiresAt!="string"||!yt.test(g.draftToken)||!(Date.parse(g.expiresAt)>Date.now())||t.page.epoch!==u)return te(t);let m=kt({...g,draftToken:g.draftToken,expiresAt:g.expiresAt});t.page.memory=m;try{t.sessionStorage.setItem(Ne,JSON.stringify(m))}catch{}return m}if(l.status===401&&t.page.epoch===u){let g=await l.json().catch(()=>null),m=g?.error?.projectId;if(t.page.epoch===u&&g?.error?.code==="PREVIEW_EXPIRED"&&typeof m=="string"&&/^[0-9a-f-]{8,64}$/i.test(m))return t.location.assign(`${s}/preview/expired?project=${encodeURIComponent(m)}`),await new Promise(c=>setTimeout(c,kn)),te(t)}return te(t)}catch{return te(t)}})(),d={token:n,done:a};return t.page.exchanging=d,a.then(()=>{t.page.exchanging===d&&(t.page.exchanging=null)}),a}async function At(e){return(await wt(e))?.draftToken??null}function Xe(e){if(!e||typeof e!="object")return;let{release:t,publishedAt:n}=e;if(t===null)return n===null?null:void 0;if(!(!Number.isInteger(t)||t<1||typeof n!="string"))return{release:t,publishedAt:n}}var wn=1e4;function An(e,t){let n=typeof document>"u"?void 0:globalThis.performance?.timeOrigin;if(n===void 0)return!1;let r=Date.parse(t.get("date")??""),s=Number.isNaN(r)?0:r+(Number(t.get("age"))||0)*1e3-Date.now();return Date.parse(e)>n+s-wn}function St(e,t){return(n,r)=>{if(e!==void 0)return e;let s=t?.();return s!==void 0?s:An(n.publishedAt,r)?null:n.release}}function Rt(e,t,n){let r=typeof e.key=="string"&&e.key.length>0;if(!r&&!e.endpoint)throw new Error("Mapled: watchRelease needs an endpoint or a delivery key.");let s=r?`${(e.apiUrl??"https://api.mapled.io").replace(/\/+$/,"")}/v1/delivery/release`:e.endpoint,i=r?{accept:"application/json","x-mapled-key":e.key}:{accept:"application/json"},u=(r?Math.max(15,e.interval??60):Math.max(2,e.interval??10))*1e3,a=e.fetch??fetch,d=typeof document>"u"?null:document,l,g=null,m=0,c=null,b=0,x=!1,_,D=null,k=()=>!d||d.visibilityState!=="hidden",N=()=>{x||!k()||(_=setTimeout(q,Math.min(u*2**b,3e5)))};async function q(){if(x||D)return;let H=new AbortController;D=H;let j=null;try{let B=await a(s,{cache:"no-cache",headers:i,signal:H.signal}),I=B.ok?Xe(await B.json()):void 0;if(x)return;I===void 0?b+=1:(b=0,l===void 0&&(l=I?t(I,B.headers):null),I&&I.release>(g?.release??0)&&(g=I),I&&I.release>(l??0)?(j={next:I,previous:l},l=I.release,m=I.release,c=null):I&&c!==null&&typeof l=="number"&&I.release>=l&&l>m&&(j={next:I,previous:c},m=l,c=null))}catch{if(x)return;b+=1}finally{D===H&&(D=null)}N(),j&&e.onPublish(j.next,j.previous)}let K=()=>{clearTimeout(_),k()&&q()};d?.addEventListener("visibilitychange",K);let Z=n?.(H=>{if(x||typeof l!="number"||H>=l||l<=m||(c=c===null?H:Math.min(c,H),g===null||g.release<l))return;m=l;let j=c;c=null,e.onPublish(g,j)});return k()&&q(),()=>{x=!0,clearTimeout(_),D?.abort(),Z?.(),d?.removeEventListener("visibilitychange",K)}}function Et(e){let t={};return e.forEach((n,r)=>{typeof n!="string"||r in t||(t[r]=n)}),t}async function Ze(e,t,n){if(!n?.key)throw new Error("Mapled: a delivery key is required.");let r=(n.apiUrl??"https://api.mapled.io").replace(/\/+$/,""),s=typeof HTMLFormElement<"u"&&t instanceof HTMLFormElement?Et(new FormData(t)):typeof FormData<"u"&&t instanceof FormData?Et(t):{...t},i=n.page??(typeof window<"u"&&typeof document<"u"?window.location.pathname:void 0),u={...s};n.consent&&(u._consent=n.consent),i&&u._page===void 0&&(u._page=i),n.test&&(u._test=!0);let a=J()?.draftToken,d={"content-type":"application/json","x-mapled-key":n.key};a&&(d["x-mapled-draft"]=a);let l;try{l=await(n.fetch??fetch)(`${r}/v1/delivery/forms/${encodeURIComponent(e)}`,{method:"POST",headers:d,body:JSON.stringify(u)})}catch{return{ok:!1,status:0,code:"NETWORK",message:"Mapled couldn't be reached. Try again in a minute."}}if(l.ok)return{ok:!0};let g=`The submission wasn't accepted (${l.status}).`,m;try{let c=await l.json();c.error?.message&&(g=c.error.message),typeof c.error?.code=="string"&&(m=c.error.code)}catch{}return{ok:!1,status:l.status,code:m,message:g}}var vt={"\u200B":0,"\u200C":1,"\u200D":2,"\u2060":3},Sn=1,Rn=1024,Ct=/\u2064[\u200B\u200C\u200D\u2060]*/g;function be(e){return e.indexOf("\u2064")<0?e:e.replace(Ct,"")}function _e(e){if(e.indexOf("\u2064")<0)return[];let t=[];for(let n of e.matchAll(Ct)){let r=En(n[0]);r&&t.push(r)}return t}function En(e){for(let t=e.indexOf("\u2064");t>=0;t=e.indexOf("\u2064",t+1)){let n=vn(e,t);if(n)return n}return null}function vn(e,t){let n=t+1;for(;n<e.length&&vt[e[n]]!==void 0;)if(n+=1,n-t-1>Rn*4)return null;let r=e.slice(t,n),s=r.length-1;if(s===0||s%4!==0)return null;let i=new Uint8Array(s/4);for(let u=0;u<i.length;u+=1){let a=0;for(let d=0;d<4;d+=1)a=a<<2|vt[r[1+u*4+d]];i[u]=a}return Tn(i,r)}function Tn(e,t){if(e.length<19||e[0]!==Sn)return null;let n=Tt(e,1),s=18+e[17];if(s>=e.length)return null;let i="";for(let l=18;l<s;l+=1)i+=String.fromCharCode(e[l]);if(i&&!xn.test(i))return null;let u=e.indexOf(0,s),a=Pt(xt(e.subarray(s,u<0?e.length:u)));if(!a)return null;let d={raw:t,token:Pn(e),record:n,locale:i||null,path:a};if(u>=0){if(s=u+1,e.length<s+17)return null;let l=Pt(xt(e.subarray(s+16)));if(!l)return null;d.via={record:Tt(e,s),path:l}}return d}function Tt(e,t){let n="";for(let r=t;r<t+16;r+=1)n+=e[r].toString(16).padStart(2,"0");return`${n.slice(0,8)}-${n.slice(8,12)}-${n.slice(12,16)}-${n.slice(16,20)}-${n.slice(20)}`}function xt(e){if(e.length===0)return null;try{return new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}).decode(e)}catch{return null}}var xn=/^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{1,8}){0,3}$/,Mt=/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/,Ot=/^(?:0|[1-9][0-9]{0,3})$/,Mn=/^@[A-Za-z0-9_-]{1,40}$/,On=new Set(["__proto__","prototype","constructor"]);function Pt(e){if(!e||e.length>2048)return null;let t=e.split(".");if(!Mt.test(t[0])||Ot.test(t[0]))return null;for(let n of t)if(!(Mt.test(n)||Ot.test(n)||Mn.test(n))||On.has(n))return null;return e}var Ue="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";function Pn(e){let t="";for(let n=0;n<e.length;n+=3){let r=e[n]<<16|(e[n+1]??0)<<8|(e[n+2]??0);t+=Ue[r>>18&63]+Ue[r>>12&63],n+1<e.length&&(t+=Ue[r>>6&63]),n+2<e.length&&(t+=Ue[r&63])}return t}var Je={mapled:"editor",v:1},X={marks:2e3,assets:500,text:1e5,mark:4100,asset:64,path:2048,label:200},Cn=/^\u2064[\u200B\u200C\u200D\u2060]+$/,$n=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function Ln(e){if(!e||typeof e!="object"||Array.isArray(e))return null;let t=e;return t.mapled===Je.mapled&&t.v===Je.v&&typeof t.type=="string"?t:null}var we=(e,t)=>typeof e=="string"&&e.length<=t,ue=e=>we(e,X.mark)&&Cn.test(e),In=e=>typeof e=="string"&&$n.test(e);function $t(e){let t=Ln(e);if(!t)return null;switch(t.type){case"init":{let n=Ye(t.homes,X.marks,ue,i=>i==="page"||i==="cms"||i==="none"),r=Ye(t.assets,X.assets,In,i=>i==="page"||i==="cms"),s=t.labels===void 0?void 0:Ye(t.labels,X.marks,ue,i=>we(i,X.label));return!n||!r||s===null?null:{type:"init",homes:n,assets:r,...s?{labels:s}:{}}}case"edit":return!ue(t.mark)||t.kind!=="inline"&&t.kind!=="panel"||t.text!==void 0&&!we(t.text,X.text)?null:{type:"edit",mark:t.mark,kind:t.kind,...typeof t.text=="string"?{text:t.text}:{}};case"patch":return ue(t.mark)&&we(t.text,X.text)&&we(t.previous,X.text)?{type:"patch",mark:t.mark,text:t.text,previous:t.previous}:null;case"refresh":return{type:"refresh"};case"highlight":return ue(t.mark)?{type:"highlight",mark:t.mark}:null;case"finish":return ue(t.mark)&&typeof t.save=="boolean"?{type:"finish",mark:t.mark,save:t.save}:null;default:return null}}function Ye(e,t,n,r){if(!e||typeof e!="object"||Array.isArray(e))return null;let s=Object.entries(e);if(s.length>t)return null;let i=Object.create(null);for(let[u,a]of s){if(!n(u)||!r(a))return null;i[u]=a}return i}var Dn=/^(?:https:\/\/[a-z0-9.-]+|http:\/\/(?:localhost|127\.0\.0\.1))(?::[0-9]{1,5})?$/;function Lt(e,t,n){return!Dn.test(t)||e.origin!==t?!1:n.parent!==void 0&&n.parent!==null&&n.parent!==n.self&&e.source===n.parent||n.opener!=null&&e.source===n.opener}function It(e){return{...Je,...e}}var Nt="#eb5c1a",Nn="#2d82cc",Un=/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi,Ut=["alt","title","aria-label"],_n="script, style, textarea, noscript, template, iframe, object, select, option",_t="a[href], area[href]";function et(e){let t=e.window??(typeof window>"u"?void 0:window);if(!t)return()=>{};let n=t,r=n.document,i=n.parent&&n.parent!==n.self?n.parent:n.opener;if(!i)return()=>{};let u=e.appOrigin,a=!1,d=new Map,l=new WeakMap,g=new Map,m=new WeakMap,c=Object.create(null),b=Object.create(null),x=Object.create(null),_="",D=null,k=null,N=o=>{try{i.postMessage(It(o),u)}catch{}},q=()=>`${n.location.pathname}${n.location.search}`,K=r.createElement("mapled-editor"),Z=K.attachShadow({mode:"closed"});Ae(K,{position:"fixed",inset:"0",pointerEvents:"none",zIndex:"2147483647"});let H=me(),j=me();j.style.borderStyle="dashed",j.style.borderWidth="1px";let B=me(),I=r.createElement("div");Ae(I,{position:"absolute",display:"none",padding:"3px 8px",borderRadius:"6px",font:"500 12px/16px Inter, system-ui, sans-serif",color:"#ffffff",whiteSpace:"nowrap"}),Z.append(j,H,B,I),r.documentElement.append(K);function me(){let o=r.createElement("div");return Ae(o,{position:"absolute",display:"none",border:`2px solid ${Nt}`,borderRadius:"6px",boxSizing:"border-box"}),o}function z(o,p,S=6){if(!p){o.style.display="none";return}Ae(o,{display:"block",left:`${p.x-S}px`,top:`${p.y-S}px`,width:`${p.width+S*2}px`,height:`${p.height+S*2}px`})}function ae(){if(a||k)return;let o=new Map,p=new WeakMap,S=A=>{if(o.size>=X.marks&&!o.has(A.mark.raw))return;let $=o.get(A.mark.raw)??[];$.push(A),o.set(A.mark.raw,$);let F=p.get(A.el)??[];F.push(A),p.set(A.el,F)},w=r.createTreeWalker(r.body??r.documentElement,n.NodeFilter.SHOW_TEXT,{acceptNode:A=>A.parentElement?.closest(_n)?n.NodeFilter.FILTER_REJECT:n.NodeFilter.FILTER_ACCEPT});for(let A=w.nextNode();A;A=w.nextNode()){let $=A;if(!($.data.indexOf("\u2064")<0||!$.parentElement))for(let F of _e($.data))S({mark:F,el:$.parentElement,node:$})}for(let A of Ut)for(let $ of Array.from(r.querySelectorAll(`[${A}]`))){let F=$.getAttribute(A)??"";if(F.indexOf("\u2064")>=0)for(let ce of _e(F))S({mark:ce,el:$,attr:A})}let P=new Map,U=new WeakMap,G=(A,$)=>{if($)for(let F of $.matchAll(Un)){let ce=F[0].toLowerCase();if(P.size>=X.assets&&!P.has(ce))return;let gt=P.get(ce)??[];gt.push(A),P.set(ce,gt),U.has(A)||U.set(A,ce)}};for(let A of Array.from(r.images)){G(A,A.getAttribute("src")),G(A,A.getAttribute("srcset"));let $=A.parentElement?.tagName==="PICTURE"?A.parentElement:null;if($)for(let F of Array.from($.querySelectorAll("source")))G(A,F.getAttribute("srcset"))}for(let A of Array.from(r.querySelectorAll("[style*='background']")))G(A,A.style.backgroundImage);d=o,l=p,g=P,m=U;let oe={type:"marks",path:q(),marks:[...d.keys()],assets:[...g.keys()]},R=JSON.stringify(oe);R!==_&&(_=R,N(oe)),D&&h()}function le(o){let p=o instanceof n.Element?o:null;for(;p&&p!==r.documentElement;p=p.parentElement){let S=l.get(p)?.filter(P=>c[P.mark.raw]==="page"||c[P.mark.raw]==="cms"),w=m.get(p);if(w&&b[w]&&(!S||S.every(P=>P.attr==="alt")))return{asset:w,el:p};if(S&&S.length>0)return{places:S,el:p}}return null}function ge(o){let p=Qe(o.mark);if(!p)return null;let S=[];for(let w of d.values())for(let P of w)Qe(P.mark)===p&&S.push(P.el);return Fn(S)}let $e=o=>!!o.node&&o.el.childNodes.length===1&&o.node.data.endsWith(o.mark.raw)&&_e(o.node.data).length===1,V=o=>{let p=o.getBoundingClientRect();return{x:p.left,y:p.top,width:p.width,height:p.height}};function Le(o){if(!o||k){z(H,null),z(j,null),I.style.display="none";return}let p=o.places?.[0],S=p?.mark.via!==void 0,w=p?c[p.mark.raw]:o.asset?b[o.asset]:void 0,P=S?Nn:Nt,U=V(o.el);H.style.borderColor=P,z(H,U);let G=p?ge(p):null;G&&G!==o.el?(j.style.borderColor=P,z(j,V(G),10)):z(j,null);let oe=(p&&x[p.mark.raw])??(o.asset?w==="cms"?"Image \u2022 from Content":"Image":w==="cms"?"From Content":S?"Component \u2022 on every page":"Text");I.textContent=oe,Ae(I,{display:"block",background:P,left:`${U.x-6}px`,top:`${Math.max(U.y-30,0)}px`})}function Ie(o){if(!o.node||k||a)return;let p=o.node.data;k={place:o,before:p},o.el.textContent=be(p),o.el.setAttribute("contenteditable","plaintext-only"),o.el.isContentEditable===!1&&o.el.setAttribute("contenteditable","true"),o.el.addEventListener("keydown",De),o.el.addEventListener("paste",ee),o.el.addEventListener("drop",se),o.el.addEventListener("input",h),o.el.focus(),z(H,null),I.style.display="none",z(B,V(o.el)),h()}function Y(o){if(!k)return;let{place:p,before:S}=k;if(k=null,p.el.removeEventListener("keydown",De),p.el.removeEventListener("paste",ee),p.el.removeEventListener("drop",se),p.el.removeEventListener("input",h),p.el.removeAttribute("contenteditable"),o){let w=(p.el.textContent??"").slice(0,X.text);p.el.textContent=w+p.mark.raw,N({type:"commit",mark:p.mark.raw,text:w})}else p.el.textContent=S,N({type:"cancel",mark:p.mark.raw});z(B,null),ae()}function De(o){o.isComposing||o.keyCode===229||(o.key==="Escape"?(o.preventDefault(),Y(!1)):o.key==="Enter"&&!o.shiftKey&&(o.preventDefault(),Y(!0)))}function he(o){let p=n.getSelection();if(!p||p.rangeCount===0||!k)return;let S=p.getRangeAt(0);if(!k.place.el.contains(S.startContainer)||!k.place.el.contains(S.endContainer))return;S.deleteContents();let w=r.createTextNode(o);S.insertNode(w),S.setStartAfter(w),S.collapse(!0),p.removeAllRanges(),p.addRange(S)}function ee(o){o.preventDefault(),he(be(o.clipboardData?.getData("text/plain")??""))}function se(o){o.preventDefault()}let ye=o=>Le(le(o.target)),ke=o=>{if(k&&k.place.el.contains(o.target))return;let p=le(o.target);if(p){o.preventDefault(),o.stopPropagation(),k&&Y(!0);let w=p.places?.[0];if(w){D={mark:w.mark.raw};let P=ge(w),U=$e(w)&&c[w.mark.raw]==="page";N({type:"select",mark:w.mark.raw,rect:V(p.el),kind:"text",editable:U,...P?{item:V(P)}:{}})}else if(p.asset){D={asset:p.asset};let P=l.get(p.el)?.find(U=>U.attr==="alt"&&(c[U.mark.raw]==="page"||c[U.mark.raw]==="cms"));N({type:"select",asset:p.asset,rect:V(p.el),kind:"image",...P?{alt:P.mark.raw}:{}})}z(B,V(p.el));return}k&&Y(!0);let S=o.target?.closest?.(_t)??null;if(S){o.preventDefault(),o.stopPropagation();try{let w=new URL(S.getAttribute("href")??"",n.location.href);w.origin===n.location.origin&&N({type:"navigate",path:`${w.pathname}${w.search}`})}catch{}}},f=o=>{o.preventDefault(),o.stopImmediatePropagation()},y=o=>{o.target?.closest?.(_t)&&(o.preventDefault(),o.stopImmediatePropagation())},v=0,h=()=>{v||(v=n.requestAnimationFrame(()=>{v=0;let o=[],p=k?{mark:k.place.mark.raw}:D;if(p?.mark)for(let S of d.get(p.mark)??[])o.push({mark:p.mark,rect:V(S.el)});if(p?.asset)for(let S of g.get(p.asset)??[])o.push({asset:p.asset,rect:V(S)});k?z(B,V(k.place.el)):o[0]&&z(B,o[0].rect),z(H,null),z(j,null),I.style.display="none",o.length>0&&N({type:"rects",items:o.slice(0,X.marks)})}))};function E(o){switch(o.type){case"init":c=o.homes,b=o.assets,x=o.labels??Object.create(null);break;case"edit":{let p=d.get(o.mark)??[];if(o.kind==="inline"){let S=c[o.mark]==="page"&&o.text!==void 0?p.find(w=>$e(w)&&be(w.node.data)===o.text):void 0;S&&!k?Ie(S):k?.place.mark.raw!==o.mark&&N({type:"cancel",mark:o.mark});break}p[0]&&z(B,V(p[0].el));break}case"finish":k&&k.place.mark.raw===o.mark&&Y(o.save);break;case"patch":{let p=!0,S=(w,P)=>{let U=w.indexOf(P),G=U-o.previous.length;return U<0||G<0||w.slice(G,U)!==o.previous?null:w.slice(0,G)+o.text+w.slice(U)};for(let w of d.get(o.mark)??[]){if(k?.place===w)continue;let P=S(w.attr?w.el.getAttribute(w.attr)??"":w.node?.data??"",w.mark.raw);P===null?p=!1:w.attr?w.el.setAttribute(w.attr,P):w.node&&(w.node.data=P)}p||e.onRefresh?.();break}case"highlight":{let p=d.get(o.mark)?.[0];p&&(p.el.scrollIntoView?.({block:"center",behavior:"smooth"}),z(B,V(p.el)));break}case"refresh":e.onRefresh?.();break}}let T=o=>{if(!Lt(o,u,{parent:n.parent,opener:n.opener,self:n.self}))return;let p=$t(o.data);p&&E(p)},O,C=0,L=new n.MutationObserver(o=>{if(o.every(S=>K.contains(S.target)))return;clearTimeout(O);let p=Date.now();C||(C=p),O=setTimeout(()=>{C=0,ae()},p-C>=1e3?0:150)});return n.addEventListener("message",T),r.addEventListener("pointermove",ye,!0),r.addEventListener("click",ke,!0),r.addEventListener("auxclick",y,!0),n.addEventListener("submit",f,!0),n.addEventListener("scroll",h,!0),n.addEventListener("resize",h),L.observe(r.documentElement,{subtree:!0,childList:!0,characterData:!0,attributes:!0,attributeFilter:["src","srcset","style",...Ut]}),N({type:"ready",sdk:e.sdk,path:q(),title:be(r.title)}),ae(),()=>{a||(k&&Y(!1),a=!0,clearTimeout(O),v&&n.cancelAnimationFrame(v),L.disconnect(),n.removeEventListener("message",T),r.removeEventListener("pointermove",ye,!0),r.removeEventListener("click",ke,!0),r.removeEventListener("auxclick",y,!0),n.removeEventListener("submit",f,!0),n.removeEventListener("scroll",h,!0),n.removeEventListener("resize",h),K.remove())}}function Qe(e){if(e.via)return`${e.via.record}:${e.via.path}`;let t=e.path.split(".");for(let n=t.length-1;n>0;n-=1)if(t[n].startsWith("@")||/^[0-9]+$/.test(t[n]))return`${e.record}:${t.slice(0,n+1).join(".")}`;return null}function Fn(e){if(e.length===0)return null;let t=e[0];for(let n of e.slice(1))for(;t&&!t.contains(n);)t=t.parentElement;return t}function Ae(e,t){Object.assign(e.style,t)}var tt=/^[a-z0-9][a-z0-9-]{0,63}$/,Ft=new Set;function Kn(e){if(typeof process<"u")return;let t=e?.aliases;if(!(!t||typeof t!="object")){for(let[n,r]of Object.entries(t))if(!(!r||typeof r!="object"||!tt.test(n)))for(let[s,i]of Object.entries(r)){if(typeof i!="string"||!tt.test(s)||!tt.test(i))continue;let u=`${n}.${s}`;Ft.has(u)||(Ft.add(u),console.warn(`[mapled] \u201C${s}\u201D in \u201C${n}\u201D was renamed to \u201C${i}\u201D. The old key keeps working until its alias is removed in Mapled \u2014 use \u201C${i}\u201D instead.`))}}}function Ht(e,t={}){let n=new URLSearchParams;t.width&&n.set("w",String(t.width)),t.height&&n.set("h",String(t.height)),t.fit&&n.set("fit",t.fit),t.format&&n.set("fmt",t.format),t.quality&&n.set("q",String(t.quality));let r=n.toString(),s=t.files?(t.files[e]??t.files[e.toLowerCase()])?.url:void 0;return typeof s=="string"&&s?r?`${s}${s.includes("?")?"&":"?"}${r}`:s:`${(t.apiUrl??"https://api.mapled.io").replace(/\/+$/,"")}/files/${encodeURIComponent(e)}${r?`?${r}`:""}`}var de=class extends Error{constructor(n,r,s){super(r);We(this,"status");We(this,"code");this.name="MapledError",this.status=n,this.code=s}},Kt=e=>Number.isInteger(e)&&e>=1,jt=()=>new Error("Mapled: release must be a positive whole number.");function Bt(e){let t=(e.apiUrl??"https://api.mapled.io").replace(/\/+$/,"");if(!e.key)throw new Error("Mapled: a delivery key is required.");if(e.release!==void 0&&!Kt(e.release))throw jt();let n=(m,c)=>(e.fetch??fetch)(m,c),r,s=new Set;async function i(){return e.draft===null?null:typeof e.draft=="string"?e.draft||null:typeof e.draft=="function"?await e.draft()||null:At({apiUrl:t,appUrl:e.appUrl,fetch:e.fetch})}async function u(m){let c=`Mapled request failed (${m.status}).`,b;try{let x=await m.json();x.error?.message&&(c=x.error.message),typeof x.error?.code=="string"&&(b=x.error.code)}catch{}return new de(m.status,c,b)}async function a(m,c,b){let x=await i(),_=b.release??e.release;if(_!==void 0&&!Kt(_))throw jt();_!==void 0&&!x&&c.set("release",String(_));let D=b.locale||e.locale;D&&c.set("locale",D);let k=c.toString(),N=await n(`${t}${m}${k?`?${k}`:""}`,{headers:x?{"x-mapled-key":e.key,"x-mapled-draft":x}:{"x-mapled-key":e.key},...x?{cache:"no-store"}:{},...b.signal?{signal:b.signal}:{}});if(!N.ok)throw await u(N);let q=await N.json();if(!x){let K=Number(N.headers.get("x-mapled-release"));if(Number.isInteger(K)&&K>=1){r=r===void 0?K:Math.min(r,K);for(let Z of s)Promise.resolve().then(()=>Z(K))}}return Kn(q),q}let d=(m,c)=>(c.expand?.length&&m.set("expand",c.expand.join(",")),c.fields?.length&&m.set("fields",c.fields.join(",")),m),l=async(m,c)=>{try{return(await a(m,d(new URLSearchParams,c),c)).record}catch(b){if(b instanceof de&&b.status===404&&b.code!=="RELEASE_NOT_FOUND")return null;throw b}};return{async getRecords(m,c={}){let b=new URLSearchParams;for(let[x,_]of Object.entries(c.filter??{}))if(_!==null&&typeof _=="object")for(let[D,k]of Object.entries(_))k!==void 0&&b.set(`filter[${x}][${D}]`,Array.isArray(k)?k.join(","):String(k));else b.set(`filter[${x}]`,String(_));return c.sort&&b.set("sort",c.sort),c.limit!==void 0&&b.set("limit",String(c.limit)),c.offset!==void 0&&b.set("offset",String(c.offset)),c.search&&b.set("search",c.search),d(b,c),a(`/v1/delivery/collections/${encodeURIComponent(m)}/records`,b,c)},getRecord(m,c,b={}){return l(`/v1/delivery/collections/${encodeURIComponent(m)}/records/${encodeURIComponent(c)}`,b)},getRecordBySlug(m,c,b={}){return l(`/v1/delivery/collections/${encodeURIComponent(m)}/records/by-slug/${encodeURIComponent(c)}`,b)},getSingle(m,c={}){return l(`/v1/delivery/singles/${encodeURIComponent(m)}`,c)},async isPreview(){return await i()!==null},watch(m,c={}){return Rt({key:e.key,apiUrl:t,interval:c.interval,onPublish:m,fetch:e.fetch},St(c.from,()=>r),b=>(s.add(b),()=>{s.delete(b)}))},async getRelease(m={}){let c=await n(`${t}/v1/delivery/release`,{headers:{"x-mapled-key":e.key},cache:"no-cache",...m.signal?{signal:m.signal}:{}});if(!c.ok)throw await u(c);let b=Xe(await c.json());if(b===void 0)throw new Error("Mapled: the release pointer didn't come back as one \u2014 check the API origin.");return b}}}var jn=/^[a-z0-9][a-z0-9_-]{0,63}$/;function Se(e){if(typeof e!="string")return null;let t=e.trim().split(".");if(t.length>8)return null;for(let n of t)if(!jn.test(n))return null;return t}var ie=(e,t)=>e!==null&&typeof e=="object"&&!Array.isArray(e)&&Object.prototype.hasOwnProperty.call(e,t)?e[t]:void 0;function nt(e,t){let n=e.data,r=e.expanded,s=e.expandedBlocks;for(let i=0;i<t.length;i++){let u=t[i],a=ie(r,u);if(i===t.length-1)return{value:ie(n,u),linked:a,blocks:ie(s,u)};if(a!==void 0){if(a===null||Array.isArray(a))return{value:void 0};n=ie(a,"data"),r=ie(a,"expanded"),s=ie(a,"expandedBlocks");continue}if(n=ie(n,u),r=void 0,s=void 0,n===void 0)return{value:void 0}}return{value:n}}var Re=e=>e==null||e===""||Array.isArray(e)&&e.length===0;function rt(e){return typeof e=="string"?e:typeof e=="number"&&Number.isFinite(e)?String(e):typeof e=="boolean"?e?"true":"false":Array.isArray(e)&&e.every(t=>typeof t=="string"||typeof t=="number")?e.join(", "):null}var Hn=new Set(["http:","https:","mailto:","tel:"]),Bn=new Set(["http:","https:"]),zn=2048;function ne(e,t,n){if(typeof e!="string"||e.length>zn)return null;let r;try{r=new URL(e,t)}catch{return null}return!(n==="link"?Hn:Bn).has(r.protocol)||r.username!==""||r.password!==""?null:r.href}var Wn=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,zt=e=>typeof e=="string"&&Wn.test(e);function Wt(e,t,n){let r=[],s=e.replace(/\{([^{}]*)\}/g,(u,a)=>{let d=Se(a);if(!d)return r.push({ok:!1,reason:"bad-path",path:a.trim().slice(0,80)}),"";let l=n(d);if(typeof l!="string"&&typeof l!="number"||l==="")return r.push({ok:!1,reason:"empty",path:d.join(".")}),"";try{return encodeURIComponent(String(l))}catch{return r.push({ok:!1,reason:"unsafe-url",path:d.join(".")}),""}});if(r[0])return r[0];let i=ne(s,t,"link");return i===null?{ok:!1,reason:"unsafe-url",path:e.slice(0,80)}:{ok:!0,url:i}}var qn=1e5,Vt=8,Gt=2048,Vn="!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",qt={amp:"&",lt:"<",gt:">",quot:'"',apos:"'",nbsp:"\xA0",copy:"\xA9",reg:"\xAE",trade:"\u2122",mdash:"\u2014",ndash:"\u2013",hellip:"\u2026",laquo:"\xAB",raquo:"\xBB"};function Xt(e,t,n){let r=t.createDocumentFragment();if(typeof e!="string"||e==="")return r;let s=e.replace(/\r\n?/g,`
3
+ `).replace(/\t/g," ").replace(/\u0000/g,"\uFFFD"),i={doc:t,base:n};if(s.length>qn){for(let u of s.split(/\n{2,}/))u.trim()!==""&&(W(i,"p",r).textContent=u.trim());return r}return ct(i,s.split(`
4
+ `),r,0),r}function W(e,t,n){let r=e.doc.createElement(t);return n.appendChild(r),r}var st=e=>e.trim()==="",ve=e=>e.length-e.trimStart().length;function Zt(e){let t=ve(e);if(t>3)return null;let n=0;for(;n<7&&e[t+n]==="#";)n++;if(n===0||n>6)return null;let r=e[t+n];if(r!==void 0&&r!==" ")return null;let s=e.slice(t+n).trim(),i=s.length;for(;i>0&&s[i-1]==="#";)i--;return i<s.length&&(i===0||s[i-1]===" ")&&(s=s.slice(0,i).trim()),{level:n,text:s}}function lt(e){if(ve(e)>3)return!1;let t=e.replace(/ /g,""),n=t[0];if(t.length<3||n!=="-"&&n!=="*"&&n!=="_")return!1;for(let r of t)if(r!==n)return!1;return!0}function ot(e){let t=/^ {0,3}(`{3,}|~{3,})/.exec(e);if(!t)return null;let n=t[1][0];return n==="`"&&e.slice(t[0].length).includes("`")?null:{mark:n,size:t[1].length}}function Ee(e){let t=/^( {0,3})([-*+]|\d{1,9}[.)])( +|$)/.exec(e);if(!t)return null;let n=t[2],r=t[3].length,s=n.length>1||/\d/.test(n);return{indent:t[1].length,width:n.length+(r>=1&&r<=4?r:1),ordered:s,start:s?parseInt(n,10):1,rest:e.slice(t[0].length)}}var it=e=>/^ {0,3}>/.test(e);function Gn(e){if(Zt(e)!==null||ot(e)!==null||it(e)||lt(e))return!0;let t=Ee(e);return t!==null&&t.rest!==""&&(!t.ordered||t.start===1)}function ct(e,t,n,r){if(r>=Vt){let i=t.join(`
5
+ `).trim();i!==""&&(W(e,"p",n).textContent=i);return}let s=0;for(;s<t.length;){let i=t[s];if(st(i)){s++;continue}let u=ot(i);if(u){let g=[],m=ve(i);for(s++;s<t.length;){let c=t[s],b=ot(c);if(b&&b.mark===u.mark&&b.size>=u.size&&c.trim().length===b.size)break;g.push(c.slice(Math.min(m,ve(c)))),s++}s++,W(e,"code",W(e,"pre",n)).textContent=g.length>0?`${g.join(`
6
6
  `)}
7
- `:"";continue}let a=mt(o);if(a){ue(e,a.text,P(e,`h${a.level}`,n),r),s++;continue}if(Ce(o)){P(e,"hr",n),s++;continue}if(Pe(o)){let p=[];for(;s<t.length&&Pe(t[s]);)p.push(t[s].replace(/^ {0,3}> ?/,"")),s++;$e(e,p,P(e,"blockquote",n),r+1);continue}let f=J(o);if(f){s=Xt(e,t,s,f,n,r);continue}let i=[o.trimStart()];for(s++;s<t.length&&!Ee(t[s])&&!Gt(t[s]);)i.push(t[s].trimStart()),s++;ue(e,i.join(`
8
- `),P(e,"p",n),r)}}function Xt(e,t,n,r,s,o){let c=P(e,r.ordered?"ol":"ul",s);r.ordered&&r.start!==1&&c.setAttribute("start",String(r.start));let a=[],f=!1;for(;n<t.length;){let i=J(t[n]);if(!i||i.ordered!==r.ordered||i.indent!==r.indent||Ce(t[n]))break;let p=i.indent+i.width,d=[i.rest];n++;let l=!1;for(;n<t.length;){let g=t[n];if(Ee(g)){l=!0,d.push(""),n++;continue}if(Q(g)<p)break;l&&d.some(S=>S!=="")&&!J(g.slice(p))&&(f=!0),l=!1,d.push(g.slice(p)),n++}for(;d.length>0&&d[d.length-1]==="";)d.pop();if(l&&n<t.length){let g=J(t[n]);g&&g.ordered===r.ordered&&g.indent===r.indent&&(f=!0)}a.push({lines:d,el:P(e,"li",c)})}for(let i of a)if($e(e,i.lines,i.el,o+1),!f){for(let p of Array.from(i.el.childNodes))if(p.nodeName==="P"){for(;p.firstChild;)i.el.insertBefore(p.firstChild,p);i.el.removeChild(p)}}return n}var Le=e=>e===void 0||e===" "||e===`
9
- `,gt=e=>e!==void 0&&/[\p{L}\p{N}]/u.test(e);function ae(e,t,n,r,s=""){let o=Math.min(e.length,r);for(let c=n;c<o;c++){if(e[c]===t)return c;if(s.includes(e[c]))return-1}return-1}function ee(e,t,n){let r=t;for(;e[r]===n;)r++;return r}function ht(e,t){if(e[t]==="\\")return t+2;if(e[t]==="`"){let n=ee(e,t,"`"),r=yt(e,n,n-t);return r===-1?n:r+(n-t)}return-1}function yt(e,t,n){let r=e.indexOf("`",t);for(;r!==-1;){let s=ee(e,r,"`");if(s-r===n)return r;r=e.indexOf("`",s)}return-1}function Vt(e,t,n){let r=n[0],s=t;for(;s<e.length;){let o=ht(e,s);if(o!==-1){s=o;continue}if(e[s]!==r){s++;continue}let c=ee(e,s,r),a=c-s;if((n.length===1?a===1||a>=3:a>=n.length)&&s>t&&!Le(e[s-1])&&(r!=="_"||!gt(e[c])))return c-n.length;s=c}return-1}function Zt(e,t){let n=ae(e,";",t+1,t+34,`
10
- &`);if(n===-1)return null;let r=e.slice(t+1,n);if(r[0]==="#"){let o=r[1]==="x"||r[1]==="X",c=r.slice(o?2:1);if(!(o?/^[0-9a-fA-F]{1,6}$/:/^[0-9]{1,7}$/).test(c))return null;let a=parseInt(c,o?16:10);return{char:a>0&&a<=1114111&&!(a>=55296&&a<=57343)?String.fromCodePoint(a):"\uFFFD",end:n+1}}let s=Object.prototype.hasOwnProperty.call(ct,r)?ct[r]:void 0;return s===void 0?null:{char:s,end:n+1}}var bt=e=>e.replace(/\\([!-/:-@[-`{-~])/g,"$1");function Yt(e,t){if(e[t]!=="(")return null;let n=Math.min(e.length,t+ft+1024),r=t+1;for(;r<n&&Le(e[r])&&e[r]!==void 0;)r++;let s="";if(e[r]==="<"){let c=ae(e,">",r+1,n,`
11
- <`);if(c===-1)return null;s=e.slice(r+1,c),r=c+1}else{let c=r,a=0;for(;r<n;){let f=e[r];if(f==="\\"&&r+1<n){r+=2;continue}if(f===" "||f===`
12
- `)break;if(f==="("&&a++,f===")"){if(a===0)break;a--}r++}s=e.slice(c,r)}for(;r<n&&(e[r]===" "||e[r]===`
13
- `);)r++;let o=e[r];if(o==='"'||o==="'"||o==="("){let c=ae(e,o==="("?")":o,r+1,n);if(c===-1)return null;for(r=c+1;r<n&&(e[r]===" "||e[r]===`
14
- `);)r++}return e[r]!==")"?null:{address:bt(s),end:r+1}}function Oe(e,t,n=!1){let r=t+1;for(;r<e.length;){let o=ht(e,r);if(o!==-1){r=o;continue}if(!n&&e[r]==="!"&&e[r+1]==="["){let c=Oe(e,r+1,!0);if(!c)return null;r=c.end;continue}if(e[r]==="[")return null;if(e[r]==="]")break;r++}if(r>=e.length)return null;let s=Yt(e,r+1);return s?{label:e.slice(t+1,r),address:s.address,end:s.end}:null}var Jt=/^(?:[a-z][a-z0-9+.-]{1,31}:[^\s<>]*|[^\s<>@]+@[^\s<>@]+\.[^\s<>@]+)$/i;function ue(e,t,n,r){if(r>=dt){n.appendChild(e.doc.createTextNode(t));return}let s="",o=()=>{s!==""&&n.appendChild(e.doc.createTextNode(s)),s=""},c=new Set,a=0;for(;a<t.length;){let f=t[a];if(f==="\\"){let i=t[a+1];if(i===`
15
- `)for(o(),P(e,"br",n),a+=2;t[a]===" ";)a++;else i!==void 0&&Wt.includes(i)?(s+=i,a+=2):(s+=f,a++);continue}if(f===`
16
- `){let i=s.endsWith(" "),p=s.length;for(;p>0&&s[p-1]===" ";)p--;for(s=s.slice(0,p),i?(o(),P(e,"br",n)):s+=`
17
- `,a++;t[a]===" ";)a++;continue}if(f==="`"){let i=ee(t,a,"`"),p=yt(t,i,i-a);if(p===-1){s+=t.slice(a,i),a=i;continue}let d=t.slice(i,p).replace(/\n/g," ");d.length>1&&d.startsWith(" ")&&d.endsWith(" ")&&d.trim()!==""&&(d=d.slice(1,-1)),o(),P(e,"code",n).textContent=d,a=p+(i-a);continue}if(f==="!"&&t[a+1]==="["){let i=Oe(t,a+1);if(i){let p=bt(i.label),d=q(i.address.trim(),e.base,"media");if(d===null)s+=p;else{o();let l=P(e,"img",n);l.setAttribute("src",d),l.setAttribute("alt",p),l.setAttribute("loading","lazy")}a=i.end;continue}}if(f==="["){let i=Oe(t,a);if(i){let p=q(i.address.trim(),e.base,"link");o();let d=p===null?n:P(e,"a",n);p!==null&&d.setAttribute("href",p),ue(e,i.label,d,r+1),a=i.end;continue}}if(f==="<"){let i=ae(t,">",a+1,a+ft,`
18
- <`),p=i===-1?null:t.slice(a+1,i);if(p!==null&&Jt.test(p)){let d=q(p.includes(":")?p:`mailto:${p}`,e.base,"link");if(d!==null){o();let l=P(e,"a",n);l.setAttribute("href",d),l.textContent=p,a=i+1;continue}}}if(f==="&"){let i=Zt(t,a);if(i){s+=i.char,a=i.end;continue}}if(f==="*"||f==="_"||f==="~"){let i=ee(t,a,f),p=i-a,d=!Le(t[i])&&(f!=="_"||!gt(t[a-1])),l=f==="~"?p>=2?[["~~",["del"]]]:[]:[...p>=3?[[f.repeat(3),["em","strong"]]]:[],...p>=2?[[f.repeat(2),["strong"]]]:[],[f,["em"]]],g=!1;if(d)for(let[S,E]of l){if(c.has(S))continue;let M=a+S.length,b=Vt(t,M,S);if(b===-1){c.add(S);continue}if(b===M)continue;o();let $=n;for(let L of E)$=P(e,L,$);ue(e,t.slice(M,b),$,r+1),a=b+S.length,g=!0;break}g||(s+=t.slice(a,i),a=i);continue}s+=f,a++}o()}var Qt="http://www.w3.org/1999/xhtml",en=new Set(["script","style","iframe","frame","frameset","object","embed","applet","base","link","meta","template","noscript"]),ce={href:{on:["a","area"],holds:"link"},src:{on:["img","video","audio","source"],holds:"media"},alt:{on:["img","area"],holds:"text"},title:{on:null,holds:"text"},"aria-label":{on:null,holds:"text"},placeholder:{on:["input","textarea"],holds:"text"},datetime:{on:["time","del","ins"],holds:"text"}},de=e=>e.namespaceURI===Qt,te=e=>!en.has(e.localName.toLowerCase());function Ue(e,t){if(!te(e))return"refused-element";let n=xe(t);return n===null?"type":(e.textContent=n,null)}function wt(e,t,n){return!te(e)||!de(e)?"refused-element":typeof t!="string"?"type":(e.replaceChildren(pt(t,e.ownerDocument,n.base)),null)}function kt(e,t,n){return typeof e!="string"?null:at(e)?it(e,{...t.apiUrl?{apiUrl:t.apiUrl}:{},...n?{width:n}:{}}):q(e,t.base,"media")}function St(e,t,n,r){if(!de(e)||e.localName!=="img")return"refused-element";if(typeof t!="string")return"type";let s=kt(t,n,r);return s===null?"unsafe-url":(e.removeAttribute("srcset"),e.setAttribute("src",s),null)}function At(e,t,n,r,s){let o=t.toLowerCase(),c=Object.prototype.hasOwnProperty.call(ce,o)?ce[o]:void 0;if(!c)return"unsupported";if(!te(e)||!de(e))return"refused-element";if(c.on!==null&&!c.on.includes(e.localName))return"unsupported";if(c.holds==="text"){let f=xe(n);return f===null?"type":(e.setAttribute(o,f),null)}if(typeof n!="string")return"type";let a=c.holds==="media"?kt(n,r,e.localName==="img"?s:void 0):q(n,r.base,"link");return a===null?"unsafe-url":(e.setAttribute(o,a),null)}function Rt(e,t){return!de(e)||e.localName!=="a"&&e.localName!=="area"?"unsupported":(e.setAttribute("href",t),null)}function G(e,t){t?e.removeAttribute("hidden"):e.setAttribute("hidden","")}var vt=["text","markdown","date","datetime","number"],tn=/^\d{4}-\d{2}-\d{2}$/,nn=/^\d{4}-\d{2}-\d{2}(?:[T ]\d{2}:\d{2}(?::\d{2}(?:\.\d{1,9})?)?(?:Z|[+-]\d{2}:?\d{2})?)?$/;function Tt(e,t,n){let r=n&&/^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$/.test(n)?n:void 0;try{if(t==="number"){let c=typeof e=="number"?e:typeof e=="string"&&e.trim()!==""?Number(e):NaN;return Number.isFinite(c)?new Intl.NumberFormat(r).format(c):null}if(typeof e!="string"||!nn.test(e))return null;let s=new Date(e);if(Number.isNaN(s.getTime()))return null;let o=tn.test(e);return new Intl.DateTimeFormat(r,{dateStyle:"long",...t==="datetime"&&!o?{timeStyle:"short"}:{},...o?{timeZone:"UTC"}:{}}).format(s)}catch{return null}}var A="data-mapled-",rn=new Set(["bind","format","width","show","hide","link","list","each","record","slug","slug-param","sort","limit","filter","expand","empty","form","form-state","form-sent","form-failed","consent","end-preview","state","preview","key","api","live","locale"]),Ie=/^[a-z0-9][a-z0-9_-]{0,63}$/,sn=/^mk_[A-Za-z0-9_]{8,128}$/,on=4,ln=100,an=2;function re(e,t=0){if(e===null||typeof e!="object"||Array.isArray(e))return!1;let{data:n,expanded:r}=e;if(n===null||typeof n!="object"||Array.isArray(n))return!1;if(r===void 0)return!0;if(r===null||typeof r!="object"||Array.isArray(r))return!1;let s=Object.values(r);return t>=an?s.length===0:s.every(o=>o===null||(Array.isArray(o)?o.every(c=>re(c,t+1)):re(o,t+1)))}var un=e=>Array.isArray(e)&&e.every(t=>re(t));function _(e){let t=e.getAttribute("id");return`${e.localName}${t&&/^[\w-]{1,40}$/.test(t)?`#${t}`:""}`}var pe=e=>(e??"").split(",").map(t=>t.trim()).filter(t=>/^[a-z0-9][a-z0-9_.-]{0,127}$/.test(t)),xt=e=>Array.from(e.children).find(t=>t.localName==="template")??null;function Ne(e,t){let n=null,r=()=>n??(n={format:"text",attrs:[],expand:[]});for(let a of Array.from(e.attributes)){if(!a.name.startsWith(A))continue;let f=a.name.slice(A.length);if(f==="bind")r().bind=a.value;else if(f.startsWith("bind-")){let i=f.slice(5);Object.prototype.hasOwnProperty.call(ce,i)?r().attrs.push([i,a.value]):t.push({path:a.value.slice(0,80),reason:"unsupported",on:`${_(e)}[${a.name.slice(0,60)}]`})}else f==="show"?r().show=a.value:f==="hide"?r().hide=a.value:f==="link"?r().link=a.value:rn.has(f)||t.push({path:a.value.slice(0,80),reason:"unsupported",on:`${_(e)}[${a.name.slice(0,60)}]`})}if(!n)return null;let s=n,o=e.getAttribute(`${A}format`);o!==null&&(vt.includes(o)?s.format=o:t.push({path:o.slice(0,80),reason:"bad-path",on:`${_(e)}[${A}format]`}));let c=parseInt(e.getAttribute(`${A}width`)??"",10);return c>=16&&c<=4096&&(s.width=c),s.expand=pe(e.getAttribute(`${A}expand`)),s}function cn(e,t){let n={},r=e.getAttribute(`${A}sort`);r!==null&&(/^-?[a-z0-9][a-z0-9_-]{0,63}$/.test(r.trim())?n.sort=r.trim():t.push({path:r.slice(0,80),reason:"bad-path",on:`${_(e)}[${A}sort]`}));let s=parseInt(e.getAttribute(`${A}limit`)??"",10);s>=1&&s<=100&&(n.limit=s);let o=e.getAttribute(`${A}filter`);if(o!==null)for(let a of o.split(";")){if(a.trim()==="")continue;let f=a.indexOf("="),i=f===-1?"":a.slice(0,f).trim(),p=f===-1?"":a.slice(f+1).trim();Ie.test(i)&&p!==""&&p.length<=200?(n.filter??(n.filter={}))[i]=p:t.push({path:a.trim().slice(0,80),reason:"bad-path",on:`${_(e)}[${A}filter]`})}let c=pe(e.getAttribute(`${A}expand`));return c.length>0&&(n.expand=c),n}function fe(e,t){let n={bound:[],eaches:[],lists:[],records:[],issues:[]},r=s=>{if(s.hasAttributes()){let o=s.getAttribute(`${A}list`),c=s.getAttribute(`${A}record`),a=s.getAttribute(`${A}each`);if(o!==null||c!==null){let i=(o??c??"").trim();if(!t)n.issues.push({path:i.slice(0,80),reason:"unsupported",on:_(s)});else if(!Ie.test(i))n.issues.push({path:i.slice(0,80),reason:"bad-path",on:_(s)});else if(o!==null)n.lists.push({el:s,collection:i,options:cn(s,n.issues)});else{let p=s.getAttribute(`${A}slug-param`),d=s.getAttribute(`${A}slug`)??(p===null?null:new URLSearchParams(s.ownerDocument.location?.search??"").get(p)),l=fe(s,!0);for(let S of l.records)n.issues.push({path:S.collection,reason:"unsupported",on:_(S.el)});n.lists.push(...l.lists),n.issues.push(...l.issues);let g=Ne(s,n.issues);g&&l.bound.unshift({el:s,d:g}),n.records.push({el:s,collection:i,slug:d!==null&&d.trim()!==""&&d.length<=200?d.trim():null,expand:pe(s.getAttribute(`${A}expand`)),block:{...l,lists:[],records:[],issues:[]}})}return}if(a!==null){n.eaches.push({el:s,path:a});return}let f=Ne(s,n.issues);f&&n.bound.push({el:s,d:f})}for(let o of Array.from(s.children))r(o)};for(let s of Array.from(e.children))r(s);return n}function Et(e){let t=new Map,n=(r,s=[])=>{let o=Z(r)?.[0];if(!o)return;let c=t.get(o)??new Set;for(let a of s)c.add(a);t.set(o,c)};for(let{d:r}of e.bound){n(r.bind,r.expand);for(let[,s]of r.attrs)n(s,r.expand);n(r.show,r.expand),n(r.hide,r.expand);for(let s of(r.link??"").matchAll(/\{([^{}]*)\}/g))n(s[1],r.expand)}for(let r of e.eaches)n(r.path,pe(r.el.getAttribute(`${A}expand`)));return t}function ne(e,t){let n=Z(t);if(!n)return{status:"bad-path"};if(e.kind==="record")return{status:"value",value:Te(e.source,n)};if(n.length<2)return{status:"bad-path"};let r=e.singles.get(n[0]);return!r||r.status!=="ok"?{status:r?.status==="failed"?"failed":"missing"}:{status:"value",value:Te(r.value,n.slice(1))}}function Fe(e){if(typeof e?.key!="string"||!sn.test(e.key))throw new Error("Mapled: data-mapled-key takes the delivery key (mk_\u2026) \u2014 the one key that is safe in a page. A server key or a secret never goes into HTML.");if(typeof document>"u")throw new Error("Mapled: @mapled/vanilla fills a page \u2014 it runs in a browser. On a server read with @mapled/client.");let t=e.root??document.documentElement,n=t.ownerDocument,r=lt({key:e.key,apiUrl:e.apiUrl,appUrl:e.appUrl,fetch:e.fetch,...e.locale?{locale:e.locale}:{}}),s={apiUrl:e.apiUrl,base:n.baseURI},o=new Map,c=u=>{let m=o.get(u);return m||o.set(u,m={attrs:new Map}),m},a=u=>{let m=c(u);m.nodes??(m.nodes=Array.from(u.childNodes))},f=(u,m)=>{let R=c(u);R.attrs.has(m)||R.attrs.set(m,u.getAttribute(m))},i=()=>{for(let[u,m]of o){m.nodes&&u.replaceChildren(...m.nodes);for(let[R,h]of m.attrs)h===null?u.removeAttribute(R):u.setAttribute(R,h)}o.clear()},p=[],d=0,l=(u,m,R)=>p.push({path:(m??"").trim().slice(0,120),reason:R,on:_(u)});function g(u,m,R){if(m.bind!==void 0){let h=ne(R,m.bind);if(h.status!=="value")l(u,m.bind,h.status);else if(!te(u))l(u,m.bind,"refused-element");else{let w=u.localName==="img";if(w?(f(u,"src"),f(u,"srcset"),f(u,"hidden")):a(u),Y(h.value))w?G(u,!1):u.textContent="",l(u,m.bind,"empty");else{let k;if(w)k=St(u,h.value,s,m.width);else if(m.format==="markdown")k=wt(u,h.value,s);else if(m.format==="text")k=Ue(u,h.value);else{let v=Tt(h.value,m.format,u.closest("[lang]")?.getAttribute("lang")??void 0);k=v===null?"type":Ue(u,v)}k?l(u,m.bind,k):d++}}}for(let[h,w]of m.attrs){let k=ne(R,w);if(k.status!=="value"){l(u,w,k.status);continue}if(f(u,h),Y(k.value)){h==="alt"?u.setAttribute("alt",""):u.removeAttribute(h),l(u,w,"empty");continue}let v=u.getAttribute(h),T=At(u,h,k.value,s,m.width);T?(v===null&&u.removeAttribute(h),l(u,w,T)):d++}for(let[h,w]of[[m.show,!0],[m.hide,!1]]){if(h===void 0)continue;let k=ne(R,h);if(k.status!=="value"){l(u,h,k.status);continue}f(u,"hidden");let v=!Y(k.value)&&k.value!==!1;G(u,v===w),d++}if(m.link!==void 0){let h=[],w=ut(m.link,s.base,k=>{let v=ne(R,k.join("."));if(v.status==="value")return v.value;h.push(v.status)});if(h[0])l(u,m.link,h[0]);else if(!w.ok)l(u,w.path,w.reason);else{f(u,"href");let k=Rt(u,w.url);k?l(u,m.link,k):d++}}}function S(u,m,R){let h=xt(u);if(!h){l(u,"template","unsupported");return}a(u);let w=[h];for(let v of Array.from(u.children))v.hasAttribute(`${A}empty`)&&(f(v,"hidden"),G(v,m.length===0),w.push(v));let k=[];for(let v of m.slice(0,ln)){let T=h.content.cloneNode(!0);E(fe(T,!1),{kind:"record",source:v},R+1),k.push(...Array.from(T.childNodes))}u.replaceChildren(...w,...k),d++}function E(u,m,R){p.push(...u.issues);for(let{el:h,d:w}of u.bound)g(h,w,m);for(let h of u.eaches){let w=ne(m,h.path);if(w.status!=="value"){l(h.el,h.path,w.status);continue}if(R>=on){l(h.el,h.path,"unsupported");continue}let k=w.value,v=Array.isArray(k)?k:Y(k)?[]:[k];if(v.some(T=>T===null||typeof T!="object"||Array.isArray(T))){l(h.el,h.path,"type");continue}v.length===0&&l(h.el,h.path,"empty"),S(h.el,v.map(T=>({data:T})),R)}}async function M(u,m){try{let R=await u();return R===null?{status:"missing"}:m(R)?{status:"ok",value:R}:{status:"failed",answered:!0}}catch(R){return R instanceof W&&R.status===404&&R.code!=="RELEASE_NOT_FOUND"?{status:"missing"}:{status:"failed"}}}let b=null,$="",L=null,C,z=!1,U=0,N=-1,X=3,O=typeof e.live=="number"?e.live:void 0;function De(){i(),b={state:"fallback",release:null,preview:!1,bound:0,issues:[]},t.setAttribute(`${A}state`,"fallback"),t.removeAttribute(`${A}preview`)}function _e(){U++,clearTimeout(C),b?.preview&&De()}function Ot(){clearTimeout(C);let u=B();if(!u||z)return;let m=Date.parse(u.expiresAt)-Date.now();C=setTimeout(()=>{B()===null&&_e(),ge()},Math.min(Math.max(m,0)+1,2147483647))}async function je(u,m=1){let R=b===null;R&&t.setAttribute(`${A}state`,"loading");let h=U,w=await r.isPreview().catch(()=>!1),k=w?B()?.draftToken??null:null;if(b!==null&&b.preview&&!w&&De(),!w&&u!==void 0&&b!==null&&b.state==="ready"&&!b.preview&&b.release!==null&&u<=b.release)return b;let v=y=>{b=y,N=h,t.setAttribute(`${A}state`,y.state),t.toggleAttribute(`${A}preview`,y.preview);let x=y.issues.filter(D=>D.reason!=="empty"),I=x.map(D=>`${D.path} (${D.reason}) on ${D.on}`).join("; ");return I!==$&&($=I,x.length>0&&console.warn(`[mapled] ${x.length===1?"1 place":`${x.length} places`} couldn't be filled: ${I}`)),n.dispatchEvent(new CustomEvent(R?"mapled:ready":"mapled:update",{detail:y})),y.preview?Ot():(clearTimeout(C),e.live&&L===null&&(L=r.watch(D=>{ge(D.release)},{interval:O,from:y.state==="ready"?y.release:null}))),y},T=null;if(!w)if(u!==void 0)T=u;else try{let y=await r.getRelease();if(y===null)return i(),v({state:"unpublished",release:null,preview:w,bound:0,issues:[]});T=y.release}catch{return b!==null&&b.state==="ready"?b:v({state:"fallback",release:null,preview:w,bound:0,issues:[]})}let F=T===null?{}:{release:T},j=fe(t,!0),We=Ne(t,j.issues);We&&j.bound.unshift({el:t,d:We});let he=new Map,ye=new Map,se=new Map,oe=[];for(let[y,x]of Et(j))oe.push(M(()=>r.getSingle(y,{...F,...x.size>0?{expand:[...x]}:{}}),re).then(I=>he.set(y,I)));for(let y of j.lists){let x=xt(y.el),I=x?[...Et(fe(x.content,!1)).keys()]:[];oe.push(M(async()=>(await r.getRecords(y.collection,{...y.options,...F,...I.length>0?{fields:I}:{}})).records,un).then(D=>ye.set(y,D)))}for(let y of j.records){if(y.slug===null){se.set(y,{status:"missing"});continue}let x=y.slug;oe.push(M(()=>r.getRecordBySlug(y.collection,x,{...F,...y.expand.length>0?{expand:y.expand}:{}}),re).then(I=>se.set(y,I)))}await Promise.all(oe);let Ge=await r.isPreview().catch(()=>!1)?B()?.draftToken??null:null;if(h!==U||Ge!==k)return m<X?je(u,m+1):(i(),v({state:"fallback",release:null,preview:Ge!==null,bound:0,issues:[]}));let Xe=[...he.values(),...ye.values(),...se.values()];if(Xe.length>0&&Xe.every(y=>y.status==="failed"&&!y.answered))return b!==null&&b.state==="ready"?b:v({state:"fallback",release:T,preview:w,bound:0,issues:[]});i(),p=[],d=0,E(j,{kind:"page",singles:he},0);for(let y of j.lists){let x=ye.get(y);x?.status==="ok"?S(y.el,x.value,0):l(y.el,y.collection,x?.status??"failed")}for(let y of j.records){let x=se.get(y);x?.status==="ok"?E(y.block,{kind:"record",source:x.value},0):l(y.el,y.collection,x?.status??"failed")}return qe(),v({state:"ready",release:T,preview:w,bound:d,issues:p})}let Ke=new WeakSet,Be=new WeakSet;function qe(){for(let u of Array.from(t.querySelectorAll(`form[${A}form]`)))Ke.has(u)||(Ke.add(u),u.addEventListener("submit",m=>{m.preventDefault(),Ct(u)}))}async function Ct(u){if(u.getAttribute(`${A}form-state`)==="sending")return;let m=(u.getAttribute(`${A}form`)??"").trim(),R=u.querySelector(`[${A}form-sent]`),h=u.querySelector(`[${A}form-failed]`),w=Array.from(u.querySelectorAll("button, input[type=submit]")).filter(F=>!F.disabled);u.setAttribute(`${A}form-state`,"sending");for(let F of w)F.disabled=!0;let k=u.querySelector(`input[type=checkbox][${A}consent]`),v=k?.checked?(k.labels?.[0]?.textContent??k.closest("label")?.textContent??"").trim().slice(0,500):"",T=Ie.test(m)?await Re(m,u,{key:e.key,apiUrl:e.apiUrl,fetch:e.fetch,...v?{consent:v}:{}}):{ok:!1,status:0,code:"BAD_FORM",message:"This form isn't set up yet."};for(let F of w)F.disabled=!1;u.setAttribute(`${A}form-state`,T.ok?"sent":"failed"),T.ok&&u.reset(),R&&G(R,T.ok),h&&(!T.ok&&(Be.has(h)||(h.textContent??"").trim()==="")&&(Be.add(h),h.textContent=T.message),G(h,!T.ok)),n.dispatchEvent(new CustomEvent("mapled:form",{detail:T.ok?{form:m,ok:!0}:{form:m,ok:!1,status:T.status,code:T.code}}))}qe();let me=async u=>{try{return await je(u)}catch(m){return console.error(`[mapled] ${m instanceof Error?m.message:"The page couldn't be filled."}`),b??{state:"fallback",release:null,preview:!1,bound:0,issues:[]}}},V=me(),ge=u=>V=V.then(()=>me(u)),He=()=>{Se(),_e();let u=U;return V=V.then(()=>N>=u&&b!==null?b:me())},ze=u=>{u.target?.closest?.(`[${A}end-preview]`)&&(u.preventDefault(),He())};return n.addEventListener("click",ze),{ready:V,get report(){return b},refresh:()=>ge(),endPreview:He,stop:()=>{z=!0,L?.(),L=()=>{},clearTimeout(C),n.removeEventListener("click",ze)},client:r}}var Mt="0.2.3";var Pt={version:Mt,mount:Fe,page:null};window.Mapled=Pt;var H=document.currentScript;if(H instanceof HTMLScriptElement&&H.hasAttribute("data-mapled-key")){let e=H.getAttribute("data-mapled-live"),t=e===null?NaN:parseInt(e,10),n=()=>{try{Pt.page=Fe({key:H.getAttribute("data-mapled-key")??"",...H.getAttribute("data-mapled-api")?{apiUrl:H.getAttribute("data-mapled-api")}:{},...H.getAttribute("data-mapled-locale")?{locale:H.getAttribute("data-mapled-locale")}:{},...e===null?{}:{live:Number.isFinite(t)?t:!0}})}catch(r){console.error(r instanceof Error?r.message:"Mapled couldn't start.")}};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",n,{once:!0}):n()}})();
7
+ `:"";continue}let a=Zt(i);if(a){Ke(e,a.text,W(e,`h${a.level}`,n),r),s++;continue}if(lt(i)){W(e,"hr",n),s++;continue}if(it(i)){let g=[];for(;s<t.length&&it(t[s]);)g.push(t[s].replace(/^ {0,3}> ?/,"")),s++;ct(e,g,W(e,"blockquote",n),r+1);continue}let d=Ee(i);if(d){s=Xn(e,t,s,d,n,r);continue}let l=[i.trimStart()];for(s++;s<t.length&&!st(t[s])&&!Gn(t[s]);)l.push(t[s].trimStart()),s++;Ke(e,l.join(`
8
+ `),W(e,"p",n),r)}}function Xn(e,t,n,r,s,i){let u=W(e,r.ordered?"ol":"ul",s);r.ordered&&r.start!==1&&u.setAttribute("start",String(r.start));let a=[],d=!1;for(;n<t.length;){let l=Ee(t[n]);if(!l||l.ordered!==r.ordered||l.indent!==r.indent||lt(t[n]))break;let g=l.indent+l.width,m=[l.rest];n++;let c=!1;for(;n<t.length;){let b=t[n];if(st(b)){c=!0,m.push(""),n++;continue}if(ve(b)<g)break;c&&m.some(x=>x!=="")&&!Ee(b.slice(g))&&(d=!0),c=!1,m.push(b.slice(g)),n++}for(;m.length>0&&m[m.length-1]==="";)m.pop();if(c&&n<t.length){let b=Ee(t[n]);b&&b.ordered===r.ordered&&b.indent===r.indent&&(d=!0)}a.push({lines:m,el:W(e,"li",u)})}for(let l of a)if(ct(e,l.lines,l.el,i+1),!d){for(let g of Array.from(l.el.childNodes))if(g.nodeName==="P"){for(;g.firstChild;)l.el.insertBefore(g.firstChild,g);l.el.removeChild(g)}}return n}var ut=e=>e===void 0||e===" "||e===`
9
+ `,Yt=e=>e!==void 0&&/[\p{L}\p{N}]/u.test(e);function Fe(e,t,n,r,s=""){let i=Math.min(e.length,r);for(let u=n;u<i;u++){if(e[u]===t)return u;if(s.includes(e[u]))return-1}return-1}function Te(e,t,n){let r=t;for(;e[r]===n;)r++;return r}function Jt(e,t){if(e[t]==="\\")return t+2;if(e[t]==="`"){let n=Te(e,t,"`"),r=Qt(e,n,n-t);return r===-1?n:r+(n-t)}return-1}function Qt(e,t,n){let r=e.indexOf("`",t);for(;r!==-1;){let s=Te(e,r,"`");if(s-r===n)return r;r=e.indexOf("`",s)}return-1}function Zn(e,t,n){let r=n[0],s=t;for(;s<e.length;){let i=Jt(e,s);if(i!==-1){s=i;continue}if(e[s]!==r){s++;continue}let u=Te(e,s,r),a=u-s;if((n.length===1?a===1||a>=3:a>=n.length)&&s>t&&!ut(e[s-1])&&(r!=="_"||!Yt(e[u])))return u-n.length;s=u}return-1}function Yn(e,t){let n=Fe(e,";",t+1,t+34,`
10
+ &`);if(n===-1)return null;let r=e.slice(t+1,n);if(r[0]==="#"){let i=r[1]==="x"||r[1]==="X",u=r.slice(i?2:1);if(!(i?/^[0-9a-fA-F]{1,6}$/:/^[0-9]{1,7}$/).test(u))return null;let a=parseInt(u,i?16:10);return{char:a>0&&a<=1114111&&!(a>=55296&&a<=57343)?String.fromCodePoint(a):"\uFFFD",end:n+1}}let s=Object.prototype.hasOwnProperty.call(qt,r)?qt[r]:void 0;return s===void 0?null:{char:s,end:n+1}}var en=e=>e.replace(/\\([!-/:-@[-`{-~])/g,"$1");function Jn(e,t){if(e[t]!=="(")return null;let n=Math.min(e.length,t+Gt+1024),r=t+1;for(;r<n&&ut(e[r])&&e[r]!==void 0;)r++;let s="";if(e[r]==="<"){let u=Fe(e,">",r+1,n,`
11
+ <`);if(u===-1)return null;s=e.slice(r+1,u),r=u+1}else{let u=r,a=0;for(;r<n;){let d=e[r];if(d==="\\"&&r+1<n){r+=2;continue}if(d===" "||d===`
12
+ `)break;if(d==="("&&a++,d===")"){if(a===0)break;a--}r++}s=e.slice(u,r)}for(;r<n&&(e[r]===" "||e[r]===`
13
+ `);)r++;let i=e[r];if(i==='"'||i==="'"||i==="("){let u=Fe(e,i==="("?")":i,r+1,n);if(u===-1)return null;for(r=u+1;r<n&&(e[r]===" "||e[r]===`
14
+ `);)r++}return e[r]!==")"?null:{address:en(s),end:r+1}}function at(e,t,n=!1){let r=t+1;for(;r<e.length;){let i=Jt(e,r);if(i!==-1){r=i;continue}if(!n&&e[r]==="!"&&e[r+1]==="["){let u=at(e,r+1,!0);if(!u)return null;r=u.end;continue}if(e[r]==="[")return null;if(e[r]==="]")break;r++}if(r>=e.length)return null;let s=Jn(e,r+1);return s?{label:e.slice(t+1,r),address:s.address,end:s.end}:null}var Qn=/^(?:[a-z][a-z0-9+.-]{1,31}:[^\s<>]*|[^\s<>@]+@[^\s<>@]+\.[^\s<>@]+)$/i;function Ke(e,t,n,r){if(r>=Vt){n.appendChild(e.doc.createTextNode(t));return}let s="",i=()=>{s!==""&&n.appendChild(e.doc.createTextNode(s)),s=""},u=new Set,a=0;for(;a<t.length;){let d=t[a];if(d==="\\"){let l=t[a+1];if(l===`
15
+ `)for(i(),W(e,"br",n),a+=2;t[a]===" ";)a++;else l!==void 0&&Vn.includes(l)?(s+=l,a+=2):(s+=d,a++);continue}if(d===`
16
+ `){let l=s.endsWith(" "),g=s.length;for(;g>0&&s[g-1]===" ";)g--;for(s=s.slice(0,g),l?(i(),W(e,"br",n)):s+=`
17
+ `,a++;t[a]===" ";)a++;continue}if(d==="`"){let l=Te(t,a,"`"),g=Qt(t,l,l-a);if(g===-1){s+=t.slice(a,l),a=l;continue}let m=t.slice(l,g).replace(/\n/g," ");m.length>1&&m.startsWith(" ")&&m.endsWith(" ")&&m.trim()!==""&&(m=m.slice(1,-1)),i(),W(e,"code",n).textContent=m,a=g+(l-a);continue}if(d==="!"&&t[a+1]==="["){let l=at(t,a+1);if(l){let g=en(l.label),m=ne(l.address.trim(),e.base,"media");if(m===null)s+=g;else{i();let c=W(e,"img",n);c.setAttribute("src",m),c.setAttribute("alt",g),c.setAttribute("loading","lazy")}a=l.end;continue}}if(d==="["){let l=at(t,a);if(l){let g=ne(l.address.trim(),e.base,"link");i();let m=g===null?n:W(e,"a",n);g!==null&&m.setAttribute("href",g),Ke(e,l.label,m,r+1),a=l.end;continue}}if(d==="<"){let l=Fe(t,">",a+1,a+Gt,`
18
+ <`),g=l===-1?null:t.slice(a+1,l);if(g!==null&&Qn.test(g)){let m=ne(g.includes(":")?g:`mailto:${g}`,e.base,"link");if(m!==null){i();let c=W(e,"a",n);c.setAttribute("href",m),c.textContent=g,a=l+1;continue}}}if(d==="&"){let l=Yn(t,a);if(l){s+=l.char,a=l.end;continue}}if(d==="*"||d==="_"||d==="~"){let l=Te(t,a,d),g=l-a,m=!ut(t[l])&&(d!=="_"||!Yt(t[a-1])),c=d==="~"?g>=2?[["~~",["del"]]]:[]:[...g>=3?[[d.repeat(3),["em","strong"]]]:[],...g>=2?[[d.repeat(2),["strong"]]]:[],[d,["em"]]],b=!1;if(m)for(let[x,_]of c){if(u.has(x))continue;let D=a+x.length,k=Zn(t,D,x);if(k===-1){u.add(x);continue}if(k===D)continue;i();let N=n;for(let q of _)N=W(e,q,N);Ke(e,t.slice(D,k),N,r+1),a=k+x.length,b=!0;break}b||(s+=t.slice(a,l),a=l);continue}s+=d,a++}i()}var er="http://www.w3.org/1999/xhtml",tr=new Set(["script","style","iframe","frame","frameset","object","embed","applet","base","link","meta","template","noscript"]),xe={href:{on:["a","area"],holds:"link"},src:{on:["img","video","audio","source"],holds:"media"},alt:{on:["img","area"],holds:"text"},title:{on:null,holds:"text"},"aria-label":{on:null,holds:"text"},placeholder:{on:["input","textarea"],holds:"text"},datetime:{on:["time","del","ins"],holds:"text"}},Me=e=>e.namespaceURI===er,je=e=>!tr.has(e.localName.toLowerCase());function dt(e,t){if(!je(e))return"refused-element";let n=rt(t);return n===null?"type":(e.textContent=n,null)}function tn(e,t,n){return!je(e)||!Me(e)?"refused-element":typeof t!="string"?"type":(e.replaceChildren(Xt(t,e.ownerDocument,n.base)),null)}function nn(e,t,n){return typeof e!="string"?null:zt(e)?Ht(e,{...t.apiUrl?{apiUrl:t.apiUrl}:{},...n?{width:n}:{}}):ne(e,t.base,"media")}function rn(e,t,n,r){if(!Me(e)||e.localName!=="img")return"refused-element";if(typeof t!="string")return"type";let s=nn(t,n,r);return s===null?"unsafe-url":(e.removeAttribute("srcset"),e.setAttribute("src",s),null)}function sn(e,t){return!je(e)||(e.localName==="img"||t==="markdown")&&!Me(e)?"refused-element":null}function ft(e,t){let n=t.toLowerCase(),r=Object.prototype.hasOwnProperty.call(xe,n)?xe[n]:void 0;return r?!je(e)||!Me(e)?"refused-element":r.on!==null&&!r.on.includes(e.localName)?"unsupported":null:"unsupported"}function on(e,t,n,r,s){let i=ft(e,t);if(i)return i;let u=t.toLowerCase(),a=xe[u];if(a.holds==="text"){let l=rt(n);return l===null?"type":(e.setAttribute(u,l),null)}if(typeof n!="string")return"type";let d=a.holds==="media"?nn(n,r,e.localName==="img"?s:void 0):ne(n,r.base,"link");return d===null?"unsafe-url":(e.setAttribute(u,d),null)}function an(e,t){return!Me(e)||e.localName!=="a"&&e.localName!=="area"?"unsupported":(e.setAttribute("href",t),null)}function fe(e,t){t?e.removeAttribute("hidden"):e.setAttribute("hidden","")}var ln=["text","markdown","date","datetime","number"],nr=/^\d{4}-\d{2}-\d{2}$/,rr=/^\d{4}-\d{2}-\d{2}(?:[T ]\d{2}:\d{2}(?::\d{2}(?:\.\d{1,9})?)?(?:Z|[+-]\d{2}:?\d{2})?)?$/;function cn(e,t,n){let r=n&&/^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$/.test(n)?n:void 0;try{if(t==="number"){let u=typeof e=="number"?e:typeof e=="string"&&e.trim()!==""?Number(e):NaN;return Number.isFinite(u)?new Intl.NumberFormat(r).format(u):null}if(typeof e!="string"||!rr.test(e))return null;let s=new Date(e);if(Number.isNaN(s.getTime()))return null;let i=nr.test(e);return new Intl.DateTimeFormat(r,{dateStyle:"long",...t==="datetime"&&!i?{timeStyle:"short"}:{},...i?{timeZone:"UTC"}:{}}).format(s)}catch{return null}}var He="0.4.0";var M="data-mapled-",sr=new Set(["bind","format","width","show","hide","link","list","each","record","slug","slug-param","sort","limit","filter","expand","empty","form","form-state","form-sent","form-failed","consent","end-preview","state","preview","key","api","live","locale","type"]),Ce=/^[a-z0-9][a-z0-9_-]{0,63}$/,or=/^mk_[A-Za-z0-9_]{8,128}$/,ir=4,ar=100,un=2,pe=e=>e!==null&&typeof e=="object"&&!Array.isArray(e);function Pe(e,t=0){if(!pe(e))return!1;let{data:n,expanded:r,expandedBlocks:s}=e;if(!pe(n))return!1;let i=a=>pe(a)&&(t>=un?Object.keys(a).length===0:Object.values(a).every(d=>d===null||(Array.isArray(d)?d.every(l=>Pe(l,t+1)):Pe(d,t+1))));if(r!==void 0&&!i(r))return!1;if(s===void 0)return!0;if(!pe(s))return!1;let u=Object.entries(s);return t>=un?u.length===0:u.every(([a,d])=>{let l=Object.prototype.hasOwnProperty.call(n,a)?n[a]:void 0;return Array.isArray(d)&&(!Array.isArray(l)||d.length===l.length)&&d.every(i)})}var lr=e=>Array.isArray(e)&&e.every(t=>Pe(t));function Q(e){let t=e.getAttribute("id");return`${e.localName}${t&&/^[\w-]{1,40}$/.test(t)?`#${t}`:""}`}var ze=e=>(e??"").split(",").map(t=>t.trim()).filter(t=>/^[a-z0-9][a-z0-9_.-]{0,127}$/.test(t));function dn(e){let t={plain:null,typed:new Map,all:[],bad:[]};for(let n of Array.from(e.children)){if(n.localName!=="template")continue;let r=n;t.all.push(r);let s=r.getAttribute(`${M}type`);s===null?t.plain??(t.plain=r):Ce.test(s.trim())?t.typed.has(s.trim())||t.typed.set(s.trim(),r):t.bad.push(r)}return t}function cr(e){let t=e.data;if(t===null||typeof t!="object"||Array.isArray(t)||!Object.prototype.hasOwnProperty.call(t,"_type"))return null;let n=t._type;return typeof n=="string"&&Ce.test(n)?n:null}function pt(e,t){let n=null,r=()=>n??(n={format:"text",attrs:[],expand:[]});for(let a of Array.from(e.attributes)){if(!a.name.startsWith(M))continue;let d=a.name.slice(M.length);if(d==="bind")r().bind=a.value;else if(d.startsWith("bind-")){let l=d.slice(5);Object.prototype.hasOwnProperty.call(xe,l)?r().attrs.push([l,a.value]):t.push({path:a.value.slice(0,80),reason:"unsupported",on:`${Q(e)}[${a.name.slice(0,60)}]`})}else d==="show"?r().show=a.value:d==="hide"?r().hide=a.value:d==="link"?r().link=a.value:sr.has(d)||t.push({path:a.value.slice(0,80),reason:"unsupported",on:`${Q(e)}[${a.name.slice(0,60)}]`})}if(!n)return null;let s=n,i=e.getAttribute(`${M}format`);i!==null&&(ln.includes(i)?s.format=i:t.push({path:i.slice(0,80),reason:"bad-path",on:`${Q(e)}[${M}format]`}));let u=parseInt(e.getAttribute(`${M}width`)??"",10);return u>=16&&u<=4096&&(s.width=u),s.expand=ze(e.getAttribute(`${M}expand`)),s}function ur(e,t){let n={},r=e.getAttribute(`${M}sort`);r!==null&&(/^-?[a-z0-9][a-z0-9_-]{0,63}$/.test(r.trim())?n.sort=r.trim():t.push({path:r.slice(0,80),reason:"bad-path",on:`${Q(e)}[${M}sort]`}));let s=parseInt(e.getAttribute(`${M}limit`)??"",10);s>=1&&s<=100&&(n.limit=s);let i=e.getAttribute(`${M}filter`);if(i!==null)for(let a of i.split(";")){if(a.trim()==="")continue;let d=a.indexOf("="),l=d===-1?"":a.slice(0,d).trim(),g=d===-1?"":a.slice(d+1).trim();Ce.test(l)&&g!==""&&g.length<=200?(n.filter??(n.filter={}))[l]=g:t.push({path:a.trim().slice(0,80),reason:"bad-path",on:`${Q(e)}[${M}filter]`})}let u=ze(e.getAttribute(`${M}expand`));return u.length>0&&(n.expand=u),n}function Be(e,t){let n={bound:[],eaches:[],lists:[],records:[],issues:[]},r=s=>{if(s.hasAttributes()){let i=s.getAttribute(`${M}list`),u=s.getAttribute(`${M}record`),a=s.getAttribute(`${M}each`);if(i!==null||u!==null){let l=(i??u??"").trim();if(!t)n.issues.push({path:l.slice(0,80),reason:"unsupported",on:Q(s)});else if(!Ce.test(l))n.issues.push({path:l.slice(0,80),reason:"bad-path",on:Q(s)});else if(i!==null)n.lists.push({el:s,collection:l,options:ur(s,n.issues)});else{let g=s.getAttribute(`${M}slug-param`),m=s.getAttribute(`${M}slug`)??(g===null?null:new URLSearchParams(s.ownerDocument.location?.search??"").get(g)),c=Be(s,!0);for(let x of c.records)n.issues.push({path:x.collection,reason:"unsupported",on:Q(x.el)});n.lists.push(...c.lists),n.issues.push(...c.issues);let b=pt(s,n.issues);b&&c.bound.unshift({el:s,d:b}),n.records.push({el:s,collection:l,slug:m!==null&&m.trim()!==""&&m.length<=200?m.trim():null,expand:ze(s.getAttribute(`${M}expand`)),block:{...c,lists:[],records:[],issues:[]}})}return}if(a!==null){n.eaches.push({el:s,path:a});return}let d=pt(s,n.issues);d&&n.bound.push({el:s,d})}for(let i of Array.from(s.children))r(i)};for(let s of Array.from(e.children))r(s);return n}function fn(e){let t=new Map,n=(r,s=[])=>{let i=Se(r)?.[0];if(!i)return;let u=t.get(i)??new Set;for(let a of s)u.add(a);t.set(i,u)};for(let{d:r}of e.bound){n(r.bind,r.expand);for(let[,s]of r.attrs)n(s,r.expand);n(r.show,r.expand),n(r.hide,r.expand);for(let s of(r.link??"").matchAll(/\{([^{}]*)\}/g))n(s[1],r.expand)}for(let r of e.eaches)n(r.path,ze(r.el.getAttribute(`${M}expand`)));return t}function Oe(e,t){let n=Se(t);if(!n)return{status:"bad-path"};if(e.kind==="record")return{status:"value",...nt(e.source,n)};if(n.length<2)return{status:"bad-path"};let r=e.singles.get(n[0]);return!r||r.status!=="ok"?{status:r?.status==="failed"?"failed":"missing"}:{status:"value",...nt(r.value,n.slice(1))}}function mt(e){if(typeof e?.key!="string"||!or.test(e.key))throw new Error("Mapled: data-mapled-key takes the delivery key (mk_\u2026) \u2014 the one key that is safe in a page. A server key or a secret never goes into HTML.");if(typeof document>"u")throw new Error("Mapled: @mapled/vanilla fills a page \u2014 it runs in a browser. On a server read with @mapled/client.");let t=e.root??document.documentElement,n=t.ownerDocument,r=Bt({key:e.key,apiUrl:e.apiUrl,appUrl:e.appUrl,fetch:e.fetch,...e.locale?{locale:e.locale}:{}}),s={apiUrl:e.apiUrl,base:n.baseURI},i=new Map,u=f=>{let y=i.get(f);return y||i.set(f,y={attrs:new Map}),y},a=f=>{let y=u(f);y.nodes??(y.nodes=Array.from(f.childNodes))},d=(f,y)=>{let v=u(f);v.attrs.has(y)||v.attrs.set(y,f.getAttribute(y))},l=()=>{for(let[f,y]of i){y.nodes&&f.replaceChildren(...y.nodes);for(let[v,h]of y.attrs)h===null?f.removeAttribute(v):f.setAttribute(v,h)}i.clear()},g=[],m=0,c=(f,y,v)=>g.push({path:(y??"").trim().slice(0,120),reason:v,on:Q(f)});function b(f,y,v){if(y.bind!==void 0){let h=Oe(v,y.bind),E=sn(f,y.format);if(h.status!=="value")c(f,y.bind,h.status);else if(E)c(f,y.bind,E);else{let T=f.localName==="img";if(T?(d(f,"src"),d(f,"srcset"),d(f,"hidden")):a(f),Re(h.value))T?fe(f,!1):f.textContent="",c(f,y.bind,"empty");else{let O;if(T)O=rn(f,h.value,s,y.width);else if(y.format==="markdown")O=tn(f,h.value,s);else if(y.format==="text")O=dt(f,h.value);else{let C=cn(h.value,y.format,f.closest("[lang]")?.getAttribute("lang")??void 0);O=C===null?"type":dt(f,C)}O?c(f,y.bind,O):m++}}}for(let[h,E]of y.attrs){let T=Oe(v,E);if(T.status!=="value"){c(f,E,T.status);continue}let O=ft(f,h);if(O){c(f,E,O);continue}if(d(f,h),Re(T.value)){h==="alt"?f.setAttribute("alt",""):f.removeAttribute(h),c(f,E,"empty");continue}let C=f.getAttribute(h),L=on(f,h,T.value,s,y.width);L?(C===null&&f.removeAttribute(h),c(f,E,L)):m++}for(let[h,E]of[[y.show,!0],[y.hide,!1]]){if(h===void 0)continue;let T=Oe(v,h);if(T.status!=="value"){c(f,h,T.status);continue}d(f,"hidden");let O=!Re(T.value)&&T.value!==!1;fe(f,O===E),m++}if(y.link!==void 0){let h=[],E=Wt(y.link,s.base,T=>{let O=Oe(v,T.join("."));if(O.status==="value")return O.value;h.push(O.status)});if(h[0])c(f,y.link,h[0]);else if(!E.ok)c(f,E.path,E.reason);else{d(f,"href");let T=an(f,E.url);T?c(f,y.link,T):m++}}}function x(f,y,v,h,E){let T=dn(f);for(let o of T.bad)c(o,o.getAttribute(`${M}type`)??"","bad-path");if(!T.plain&&T.typed.size===0){c(f,"template","unsupported");return}a(f);let O=[...T.all];for(let o of Array.from(f.children))o.hasAttribute(`${M}empty`)&&(d(o,"hidden"),fe(o,y.length===0),O.push(o));let C=[],L=!1;for(let o of y.slice(0,ar)){let p=E?cr(o):null,S=(p===null?void 0:T.typed.get(p))??T.plain;if(!S){L=!0;continue}let w=S.content.cloneNode(!0);_(Be(w,!1),{kind:"record",source:o},v+1),C.push(...Array.from(w.childNodes))}L&&c(f,h,"no-template"),f.replaceChildren(...O,...C),m++}function _(f,y,v){g.push(...f.issues);for(let{el:h,d:E}of f.bound)b(h,E,y);for(let h of f.eaches){let E=Oe(y,h.path);if(E.status!=="value"){c(h.el,h.path,E.status);continue}if(v>=ir){c(h.el,h.path,"unsupported");continue}if(E.linked!==void 0){let L=Array.isArray(E.linked)?E.linked:E.linked===null?[]:[E.linked];L.length===0&&c(h.el,h.path,"empty"),x(h.el,L,v,h.path,!1);continue}let T=E.value,O=Array.isArray(T)?T:Re(T)?[]:[T];if(O.some(L=>!pe(L))){c(h.el,h.path,"type");continue}O.length===0&&c(h.el,h.path,"empty");let C=Array.isArray(T)&&Array.isArray(E.blocks)?E.blocks:[];x(h.el,O.map((L,o)=>pe(C[o])?{data:L,expanded:C[o]}:{data:L}),v,h.path,!0)}}async function D(f,y){try{let v=await f();return v===null?{status:"missing"}:y(v)?{status:"ok",value:v}:{status:"failed",answered:!0}}catch(v){return v instanceof de&&v.status===404&&v.code!=="RELEASE_NOT_FOUND"?{status:"missing"}:{status:"failed"}}}let k=null,N="",q=null,K,Z=!1,H=null,j=null,B=0,I=-1,me=3,z=typeof e.live=="number"?e.live:void 0;function ae(){le(!1),l(),k={state:"fallback",release:null,preview:!1,bound:0,issues:[]},t.setAttribute(`${M}state`,"fallback"),t.removeAttribute(`${M}preview`)}function le(f){let y=f&&!Z?J():null,v=n.defaultView,h=y?.mode==="edit"&&v?y.appOrigin??null:null;h!==j&&(H?.(),H=null,j=h,h&&v&&(H=et({appOrigin:h,sdk:`@mapled/vanilla@${He}`,onRefresh:()=>{se()},window:v})))}function ge(){B++,clearTimeout(K),k?.preview&&ae()}function $e(){clearTimeout(K);let f=J();if(!f||Z)return;let y=Date.parse(f.expiresAt)-Date.now();K=setTimeout(()=>{J()===null&&ge(),se()},Math.min(Math.max(y,0)+1,2147483647))}async function V(f,y=1){let v=k===null;v&&t.setAttribute(`${M}state`,"loading");let h=B,E=await r.isPreview().catch(()=>!1),T=E?J()?.draftToken??null:null;if(k!==null&&k.preview&&!E&&ae(),!E&&f!==void 0&&k!==null&&k.state==="ready"&&!k.preview&&k.release!==null&&f<=k.release)return k;let O=R=>{k=R,I=h,t.setAttribute(`${M}state`,R.state),t.toggleAttribute(`${M}preview`,R.preview);let A=R.issues.filter(F=>F.reason!=="empty"),$=A.map(F=>`${F.path} (${F.reason}) on ${F.on}`).join("; ");return $!==N&&(N=$,A.length>0&&console.warn(`[mapled] ${A.length===1?"1 place":`${A.length} places`} couldn't be filled: ${$}`)),n.dispatchEvent(new CustomEvent(v?"mapled:ready":"mapled:update",{detail:R})),le(R.preview),R.preview?$e():(clearTimeout(K),e.live&&q===null&&(q=r.watch(F=>{se(F.release)},{interval:z,from:R.state==="ready"?R.release:null}))),R},C=null;if(!E)if(f!==void 0)C=f;else try{let R=await r.getRelease();if(R===null)return l(),O({state:"unpublished",release:null,preview:E,bound:0,issues:[]});C=R.release}catch{return k!==null&&k.state==="ready"?k:O({state:"fallback",release:null,preview:E,bound:0,issues:[]})}let L=C===null?{}:{release:C},o=Be(t,!0),p=pt(t,o.issues);p&&o.bound.unshift({el:t,d:p});let S=new Map,w=new Map,P=new Map,U=[];for(let[R,A]of fn(o))U.push(D(()=>r.getSingle(R,{...L,...A.size>0?{expand:[...A]}:{}}),Pe).then($=>S.set(R,$)));for(let R of o.lists){let A=dn(R.el).plain,$=A?[...fn(Be(A.content,!1)).keys()]:[];U.push(D(async()=>(await r.getRecords(R.collection,{...R.options,...L,...$.length>0?{fields:$}:{}})).records,lr).then(F=>w.set(R,F)))}for(let R of o.records){if(R.slug===null){P.set(R,{status:"missing"});continue}let A=R.slug;U.push(D(()=>r.getRecordBySlug(R.collection,A,{...L,...R.expand.length>0?{expand:R.expand}:{}}),Pe).then($=>P.set(R,$)))}await Promise.all(U);let G=await r.isPreview().catch(()=>!1)?J()?.draftToken??null:null;if(h!==B||G!==T)return y<me?V(f,y+1):(l(),O({state:"fallback",release:null,preview:G!==null,bound:0,issues:[]}));let oe=[...S.values(),...w.values(),...P.values()];if(oe.length>0&&oe.every(R=>R.status==="failed"&&!R.answered))return k!==null&&k.state==="ready"?k:O({state:"fallback",release:C,preview:E,bound:0,issues:[]});l(),g=[],m=0,_(o,{kind:"page",singles:S},0);for(let R of o.lists){let A=w.get(R);A?.status==="ok"?x(R.el,A.value,0,R.collection,!1):c(R.el,R.collection,A?.status??"failed")}for(let R of o.records){let A=P.get(R);A?.status==="ok"?_(R.block,{kind:"record",source:A.value},0):c(R.el,R.collection,A?.status??"failed")}return Y(),O({state:"ready",release:C,preview:E,bound:m,issues:g})}let Le=new WeakSet,Ie=new WeakSet;function Y(){for(let f of Array.from(t.querySelectorAll(`form[${M}form]`)))Le.has(f)||(Le.add(f),f.addEventListener("submit",y=>{y.preventDefault(),De(f)}))}async function De(f){if(f.getAttribute(`${M}form-state`)==="sending")return;let y=(f.getAttribute(`${M}form`)??"").trim(),v=f.querySelector(`[${M}form-sent]`),h=f.querySelector(`[${M}form-failed]`),E=Array.from(f.querySelectorAll("button, input[type=submit]")).filter(L=>!L.disabled);f.setAttribute(`${M}form-state`,"sending");for(let L of E)L.disabled=!0;let T=f.querySelector(`input[type=checkbox][${M}consent]`),O=T?.checked?(T.labels?.[0]?.textContent??T.closest("label")?.textContent??"").trim().slice(0,500):"",C=Ce.test(y)?await Ze(y,f,{key:e.key,apiUrl:e.apiUrl,fetch:e.fetch,...O?{consent:O}:{}}):{ok:!1,status:0,code:"BAD_FORM",message:"This form isn't set up yet."};for(let L of E)L.disabled=!1;f.setAttribute(`${M}form-state`,C.ok?"sent":"failed"),C.ok&&f.reset(),v&&fe(v,C.ok),h&&(!C.ok&&(Ie.has(h)||(h.textContent??"").trim()==="")&&(Ie.add(h),h.textContent=C.message),fe(h,!C.ok)),n.dispatchEvent(new CustomEvent("mapled:form",{detail:C.ok?{form:y,ok:!0}:{form:y,ok:!1,status:C.status,code:C.code}}))}Y();let he=async f=>{try{return await V(f)}catch(y){return console.error(`[mapled] ${y instanceof Error?y.message:"The page couldn't be filled."}`),k??{state:"fallback",release:null,preview:!1,bound:0,issues:[]}}},ee=he(),se=f=>ee=ee.then(()=>he(f)),ye=()=>{Ge(),ge();let f=B;return ee=ee.then(()=>I>=f&&k!==null?k:he())},ke=f=>{f.target?.closest?.(`[${M}end-preview]`)&&(f.preventDefault(),ye())};return n.addEventListener("click",ke),{ready:ee,get report(){return k},refresh:()=>se(),endPreview:ye,stop:()=>{Z=!0,le(!1),q?.(),q=()=>{},clearTimeout(K),n.removeEventListener("click",ke)},client:r}}var pn={version:He,mount:mt,page:null};window.Mapled=pn;var re=document.currentScript;if(re instanceof HTMLScriptElement&&re.hasAttribute("data-mapled-key")){let e=re.getAttribute("data-mapled-live"),t=e===null?NaN:parseInt(e,10),n=()=>{try{pn.page=mt({key:re.getAttribute("data-mapled-key")??"",...re.getAttribute("data-mapled-api")?{apiUrl:re.getAttribute("data-mapled-api")}:{},...re.getAttribute("data-mapled-locale")?{locale:re.getAttribute("data-mapled-locale")}:{},...e===null?{}:{live:Number.isFinite(t)?t:!0}})}catch(r){console.error(r instanceof Error?r.message:"Mapled couldn't start.")}};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",n,{once:!0}):n()}})();
@@ -1 +1 @@
1
- sha384-SuKH/yk2hpNI+Ec2QGKpZ7jVxe+0Ep0x/fchL560g+XuzG5hnVCIhG9OKX6BKdpY
1
+ sha384-DgnLLoT4DVtklY1XJM+nCt7FvO1tWtJxmVn4IQM4+yEpV1ttw/1uYuP50+dZN5y7
package/dist/paths.d.ts CHANGED
@@ -4,16 +4,31 @@
4
4
  content, read by own properties only (DOM_SECURITY.md, rule 7). */
5
5
  /** The segments of a path, or null when it is outside the grammar. */
6
6
  export declare function parsePath(text: string | null | undefined): string[] | null;
7
- /** What paths resolve in: a record as Mapled serves it, or an item of a
8
- repeatable group (a plain object of the record's data). */
7
+ /** What paths resolve in: a record as Mapled serves it — the records its
8
+ relations link to under `expanded`, those of its blocks' relations
9
+ under `expandedBlocks` — or an item of a repeatable group or of a
10
+ components field (a plain object of the record's data; a block's
11
+ linked records are its `expanded`). */
9
12
  export type Source = {
10
13
  data: unknown;
11
14
  expanded?: unknown;
15
+ expandedBlocks?: unknown;
12
16
  };
13
- /** The value at a path, or undefined when there is none. A relation the
14
- read expanded is walked into: `author.name` reads the linked record —
15
- one linked record only; a list of them has no single value. */
16
- export declare function valueAt(source: Source, segments: readonly string[]): unknown;
17
+ /** Where a path ends: the value there; `linked` when it ends at a
18
+ relation the read expanded — the linked record, a list of them or
19
+ null; `blocks` when it ends at a components field whose blocks'
20
+ relations the read expanded — one entry per block, in the list's order. */
21
+ export type Walked = {
22
+ value: unknown;
23
+ linked?: unknown;
24
+ blocks?: unknown;
25
+ };
26
+ /** The path walked through a source. A relation the read expanded is
27
+ walked into: `author.name` reads the linked record — one linked
28
+ record only; a list of them has no single value. */
29
+ export declare function walk(source: Source, segments: readonly string[]): Walked;
30
+ /** The value at a path, or undefined when there is none. */
31
+ export declare const valueAt: (source: Source, segments: readonly string[]) => unknown;
17
32
  /** Nothing to show: no value, or an empty one. */
18
33
  export declare const isEmpty: (value: unknown) => boolean;
19
34
  /** A value as the text a person reads, or null when it isn't one —
package/dist/paths.js CHANGED
@@ -19,30 +19,37 @@ export function parsePath(text) {
19
19
  const own = (value, key) => value !== null && typeof value === "object" && !Array.isArray(value) && Object.prototype.hasOwnProperty.call(value, key)
20
20
  ? value[key]
21
21
  : undefined;
22
- /** The value at a path, or undefined when there is none. A relation the
23
- read expanded is walked into: `author.name` reads the linked record —
24
- one linked record only; a list of them has no single value. */
25
- export function valueAt(source, segments) {
22
+ /** The path walked through a source. A relation the read expanded is
23
+ walked into: `author.name` reads the linked record — one linked
24
+ record only; a list of them has no single value. */
25
+ export function walk(source, segments) {
26
26
  let current = source.data;
27
27
  let expanded = source.expanded;
28
+ let blocks = source.expandedBlocks;
28
29
  for (let i = 0; i < segments.length; i++) {
29
30
  const segment = segments[i];
30
- const linked = i < segments.length - 1 ? own(expanded, segment) : undefined;
31
+ const linked = own(expanded, segment);
32
+ if (i === segments.length - 1)
33
+ return { value: own(current, segment), linked, blocks: own(blocks, segment) };
31
34
  if (linked !== undefined) {
32
35
  if (linked === null || Array.isArray(linked))
33
- return undefined;
36
+ return { value: undefined };
34
37
  current = own(linked, "data");
35
38
  expanded = own(linked, "expanded");
39
+ blocks = own(linked, "expandedBlocks");
36
40
  continue;
37
41
  }
38
42
  current = own(current, segment);
39
43
  // below a field there are no records to walk into
40
44
  expanded = undefined;
45
+ blocks = undefined;
41
46
  if (current === undefined)
42
- return undefined;
47
+ return { value: undefined };
43
48
  }
44
- return current;
49
+ return { value: current };
45
50
  }
51
+ /** The value at a path, or undefined when there is none. */
52
+ export const valueAt = (source, segments) => walk(source, segments).value;
46
53
  /** Nothing to show: no value, or an empty one. */
47
54
  export const isEmpty = (value) => value === undefined || value === null || value === "" || (Array.isArray(value) && value.length === 0);
48
55
  /** A value as the text a person reads, or null when it isn't one —
package/dist/runtime.d.ts CHANGED
@@ -19,7 +19,10 @@
19
19
  record: data-mapled-sort,
20
20
  -limit, -filter, -expand
21
21
  data-mapled-each="features" the same for the items of a
22
- repeatable group
22
+ repeatable group, and for the
23
+ blocks of a components field:
24
+ <template data-mapled-type=
25
+ "hero"> per type of block
23
26
  data-mapled-record="posts" one record for what is inside:
24
27
  data-mapled-slug, or
25
28
  data-mapled-slug-param="slug"
@@ -32,8 +35,10 @@ import { type MapledClient } from "@mapled/client";
32
35
  collection in the release; `empty` — the record is there, a value at
33
36
  this path isn't; `failed` — the read didn't come back; `bad-path` —
34
37
  the page's attribute isn't a path, a key or an option Mapled reads;
35
- the rest are the sinks' refusals. */
36
- export declare const ISSUE_REASONS: readonly ["missing", "empty", "failed", "bad-path", "unsafe-url", "type", "refused-element", "unsupported"];
38
+ `no-template` — a block whose type the page has no template for (and
39
+ no template without a type to take it); the rest are the sinks'
40
+ refusals. */
41
+ export declare const ISSUE_REASONS: readonly ["missing", "empty", "failed", "bad-path", "unsafe-url", "type", "refused-element", "unsupported", "no-template"];
37
42
  export type IssueReason = (typeof ISSUE_REASONS)[number];
38
43
  /** A place the runtime couldn't fill: the page's own path, why, and the
39
44
  element as the page names it. Never a value. */
package/dist/runtime.js CHANGED
@@ -19,7 +19,10 @@
19
19
  record: data-mapled-sort,
20
20
  -limit, -filter, -expand
21
21
  data-mapled-each="features" the same for the items of a
22
- repeatable group
22
+ repeatable group, and for the
23
+ blocks of a components field:
24
+ <template data-mapled-type=
25
+ "hero"> per type of block
23
26
  data-mapled-record="posts" one record for what is inside:
24
27
  data-mapled-slug, or
25
28
  data-mapled-slug-param="slug"
@@ -27,21 +30,24 @@
27
30
 
28
31
  Paths start at a single from the document (`home.headline`) and at the
29
32
  record inside a list, an each or a record (`title`, `author.name`). */
30
- import { createClient, endPreview, MapledError, previewSession, submitForm } from "@mapled/client";
31
- import { isEmpty, parsePath, valueAt } from "./paths.js";
32
- import { ATTRIBUTES, FORMATS, formatted, setVisible, writable, writeAttribute, writeImage, writeLink, writeMarkdown, writeText } from "./sinks.js";
33
+ import { createClient, endPreview, MapledError, previewSession, startEditor, submitForm } from "@mapled/client";
34
+ import { isEmpty, parsePath, walk } from "./paths.js";
35
+ import { ATTRIBUTES, attributeRefusal, bindRefusal, FORMATS, formatted, setVisible, writeAttribute, writeImage, writeLink, writeMarkdown, writeText } from "./sinks.js";
33
36
  import { fillTemplate } from "./url.js";
37
+ import { VERSION } from "./version.js";
34
38
  /** Why a place wasn't filled. `missing` — no such single, record or
35
39
  collection in the release; `empty` — the record is there, a value at
36
40
  this path isn't; `failed` — the read didn't come back; `bad-path` —
37
41
  the page's attribute isn't a path, a key or an option Mapled reads;
38
- the rest are the sinks' refusals. */
39
- export const ISSUE_REASONS = ["missing", "empty", "failed", "bad-path", "unsafe-url", "type", "refused-element", "unsupported"];
42
+ `no-template` — a block whose type the page has no template for (and
43
+ no template without a type to take it); the rest are the sinks'
44
+ refusals. */
45
+ export const ISSUE_REASONS = ["missing", "empty", "failed", "bad-path", "unsafe-url", "type", "refused-element", "unsupported", "no-template"];
40
46
  const P = "data-mapled-";
41
47
  /** Every attribute the runtime reads or writes, besides `bind-…`. */
42
48
  export const NAMES = new Set([
43
49
  "bind", "format", "width", "show", "hide", "link", "list", "each", "record", "slug", "slug-param", "sort", "limit", "filter", "expand", "empty",
44
- "form", "form-state", "form-sent", "form-failed", "consent", "end-preview", "state", "preview", "key", "api", "live", "locale",
50
+ "form", "form-state", "form-sent", "form-failed", "consent", "end-preview", "state", "preview", "key", "api", "live", "locale", "type",
45
51
  ]);
46
52
  const KEY = /^[a-z0-9][a-z0-9_-]{0,63}$/;
47
53
  const DELIVERY_KEY = /^mk_[A-Za-z0-9_]{8,128}$/;
@@ -51,24 +57,40 @@ const MAX_EACH_DEPTH = 4;
51
57
  const MAX_ITEMS = 100;
52
58
  /** How deep `expand` reaches: `author`, `related.author`. */
53
59
  const MAX_EXPAND_DEPTH = 2;
60
+ const isObject = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
54
61
  /** A record as Mapled serves one — what every path walks: `data` an
55
62
  object; `expanded`, when there, one linked record, a list of them or
56
- null under each key, no deeper than `expand` can ask. An answer is
57
- data, and so is its shape: what isn't a record is read as no answer. */
63
+ null under each key; `expandedBlocks`, when there, a list under each
64
+ key — one object per block of a components field, as many as the
65
+ record's list holds (each block takes the one in its place), holding
66
+ the block's linked records the same way; none deeper than `expand`
67
+ can ask. An answer is data, and so is its shape: what isn't a record
68
+ is read as no answer. */
58
69
  function isRecord(value, depth = 0) {
59
- if (value === null || typeof value !== "object" || Array.isArray(value))
70
+ if (!isObject(value))
60
71
  return false;
61
- const { data, expanded } = value;
62
- if (data === null || typeof data !== "object" || Array.isArray(data))
72
+ const { data, expanded, expandedBlocks } = value;
73
+ if (!isObject(data))
63
74
  return false;
64
- if (expanded === undefined)
75
+ /** an object of linked records — empty past the depth `expand` reaches */
76
+ const linkedIn = (links) => isObject(links) &&
77
+ (depth >= MAX_EXPAND_DEPTH
78
+ ? Object.keys(links).length === 0
79
+ : Object.values(links).every((one) => one === null || (Array.isArray(one) ? one.every((r) => isRecord(r, depth + 1)) : isRecord(one, depth + 1))));
80
+ if (expanded !== undefined && !linkedIn(expanded))
81
+ return false;
82
+ if (expandedBlocks === undefined)
65
83
  return true;
66
- if (expanded === null || typeof expanded !== "object" || Array.isArray(expanded))
84
+ if (!isObject(expandedBlocks))
67
85
  return false;
68
- const linked = Object.values(expanded);
86
+ const lists = Object.entries(expandedBlocks);
69
87
  if (depth >= MAX_EXPAND_DEPTH)
70
- return linked.length === 0;
71
- return linked.every((one) => one === null || (Array.isArray(one) ? one.every((r) => isRecord(r, depth + 1)) : isRecord(one, depth + 1)));
88
+ return lists.length === 0;
89
+ return lists.every(([key, entries]) => {
90
+ // a key the record doesn't hold as a list — a field the read left out — has no blocks to pair with
91
+ const blocks = Object.prototype.hasOwnProperty.call(data, key) ? data[key] : undefined;
92
+ return Array.isArray(entries) && (!Array.isArray(blocks) || entries.length === blocks.length) && entries.every(linkedIn);
93
+ });
72
94
  }
73
95
  const isRecordList = (value) => Array.isArray(value) && value.every((r) => isRecord(r));
74
96
  /** The element as the page names it: `a#cta`. The id is the author's. */
@@ -80,7 +102,33 @@ const listOf = (text) => (text ?? "")
80
102
  .split(",")
81
103
  .map((t) => t.trim())
82
104
  .filter((t) => /^[a-z0-9][a-z0-9_.-]{0,127}$/.test(t));
83
- const templateOf = (el) => Array.from(el.children).find((c) => c.localName === "template") ?? null;
105
+ function templatesOf(el) {
106
+ const out = { plain: null, typed: new Map(), all: [], bad: [] };
107
+ for (const child of Array.from(el.children)) {
108
+ if (child.localName !== "template")
109
+ continue;
110
+ const template = child;
111
+ out.all.push(template);
112
+ const type = template.getAttribute(`${P}type`);
113
+ if (type === null)
114
+ out.plain ??= template;
115
+ else if (!KEY.test(type.trim()))
116
+ out.bad.push(template);
117
+ else if (!out.typed.has(type.trim()))
118
+ out.typed.set(type.trim(), template);
119
+ }
120
+ return out;
121
+ }
122
+ /** The type a block names — or a JSON field's object, the same way —
123
+ read as its own property and held to the grammar of Mapled's keys;
124
+ null for a group's item or a record, whose keys never start with `_`. */
125
+ function typeOf(source) {
126
+ const data = source.data;
127
+ if (data === null || typeof data !== "object" || Array.isArray(data) || !Object.prototype.hasOwnProperty.call(data, "_type"))
128
+ return null;
129
+ const type = data._type;
130
+ return typeof type === "string" && KEY.test(type) ? type : null;
131
+ }
84
132
  function declaredOn(el, issues) {
85
133
  let d = null;
86
134
  const get = () => (d ??= { format: "text", attrs: [], expand: [] });
@@ -241,14 +289,14 @@ function look(scope, path) {
241
289
  if (!segments)
242
290
  return { status: "bad-path" };
243
291
  if (scope.kind === "record")
244
- return { status: "value", value: valueAt(scope.source, segments) };
292
+ return { status: "value", ...walk(scope.source, segments) };
245
293
  // from the document a path names a single, then a field of it
246
294
  if (segments.length < 2)
247
295
  return { status: "bad-path" };
248
296
  const single = scope.singles.get(segments[0]);
249
297
  if (!single || single.status !== "ok")
250
298
  return { status: single?.status === "failed" ? "failed" : "missing" };
251
- return { status: "value", value: valueAt(single.value, segments.slice(1)) };
299
+ return { status: "value", ...walk(single.value, segments.slice(1)) };
252
300
  }
253
301
  /* ---- mount ---- */
254
302
  export function mount(options) {
@@ -304,10 +352,12 @@ export function mount(options) {
304
352
  function fillElement(el, d, scope) {
305
353
  if (d.bind !== undefined) {
306
354
  const found = look(scope, d.bind);
355
+ // a place the sink refuses stays as written, an empty value or not
356
+ const refused = bindRefusal(el, d.format);
307
357
  if (found.status !== "value")
308
358
  note(el, d.bind, found.status);
309
- else if (!writable(el))
310
- note(el, d.bind, "refused-element");
359
+ else if (refused)
360
+ note(el, d.bind, refused);
311
361
  else {
312
362
  const image = el.localName === "img";
313
363
  if (image) {
@@ -350,6 +400,11 @@ export function mount(options) {
350
400
  note(el, path, found.status);
351
401
  continue;
352
402
  }
403
+ const refused = attributeRefusal(el, name);
404
+ if (refused) {
405
+ note(el, path, refused);
406
+ continue;
407
+ }
353
408
  keepAttr(el, name);
354
409
  if (isEmpty(found.value)) {
355
410
  // an image without a description is a decorative one; any other attribute goes
@@ -406,15 +461,19 @@ export function mount(options) {
406
461
  }
407
462
  }
408
463
  }
409
- /** The element's template, once per item; what else it held is its fallback. */
410
- function repeat(el, sources, depth) {
411
- const template = templateOf(el);
412
- if (!template) {
464
+ /** The element's template, once per item — an each's block takes the
465
+ one of its type; what else it held is its fallback. `path` is the
466
+ page's own, for the report. */
467
+ function repeat(el, sources, depth, path, blocks) {
468
+ const templates = templatesOf(el);
469
+ for (const bad of templates.bad)
470
+ note(bad, bad.getAttribute(`${P}type`) ?? "", "bad-path");
471
+ if (!templates.plain && templates.typed.size === 0) {
413
472
  note(el, "template", "unsupported");
414
473
  return;
415
474
  }
416
475
  keepContent(el);
417
- const kept = [template];
476
+ const kept = [...templates.all];
418
477
  for (const child of Array.from(el.children)) {
419
478
  if (!child.hasAttribute(`${P}empty`))
420
479
  continue;
@@ -423,11 +482,23 @@ export function mount(options) {
423
482
  kept.push(child);
424
483
  }
425
484
  const items = [];
485
+ let untemplated = false;
426
486
  for (const source of sources.slice(0, MAX_ITEMS)) {
487
+ // a list's record has no type: only an each's item picks among the typed templates —
488
+ // a block, or a JSON field's object that names its _type (the page doesn't see the schema)
489
+ const type = blocks ? typeOf(source) : null;
490
+ const template = (type === null ? undefined : templates.typed.get(type)) ?? templates.plain;
491
+ // a block of a type the page doesn't show: content picks among the author's templates, never adds one
492
+ if (!template) {
493
+ untemplated = true;
494
+ continue;
495
+ }
427
496
  const clone = template.content.cloneNode(true);
428
497
  fill(compile(clone, false), { kind: "record", source }, depth + 1);
429
498
  items.push(...Array.from(clone.childNodes));
430
499
  }
500
+ if (untemplated)
501
+ note(el, path, "no-template");
431
502
  el.replaceChildren(...kept, ...items);
432
503
  bound++;
433
504
  }
@@ -445,16 +516,26 @@ export function mount(options) {
445
516
  note(each.el, each.path, "unsupported");
446
517
  continue;
447
518
  }
519
+ // a relation the read expanded: its linked records, one for a relation to one — records have no type
520
+ if (found.linked !== undefined) {
521
+ const records = (Array.isArray(found.linked) ? found.linked : found.linked === null ? [] : [found.linked]);
522
+ if (records.length === 0)
523
+ note(each.el, each.path, "empty");
524
+ repeat(each.el, records, depth, each.path, false);
525
+ continue;
526
+ }
448
527
  // a repeatable group is a list of items; one that isn't repeatable is a single item
449
528
  const value = found.value;
450
529
  const items = Array.isArray(value) ? value : isEmpty(value) ? [] : [value];
451
- if (items.some((item) => item === null || typeof item !== "object" || Array.isArray(item))) {
530
+ if (items.some((item) => !isObject(item))) {
452
531
  note(each.el, each.path, "type");
453
532
  continue;
454
533
  }
455
534
  if (items.length === 0)
456
535
  note(each.el, each.path, "empty");
457
- repeat(each.el, items.map((item) => ({ data: item })), depth);
536
+ // the blocks' linked records, when the read expanded their relations: one entry a block, in the list's order
537
+ const links = Array.isArray(value) && Array.isArray(found.blocks) ? found.blocks : [];
538
+ repeat(each.el, items.map((item, i) => (isObject(links[i]) ? { data: item, expanded: links[i] } : { data: item })), depth, each.path, true);
458
539
  }
459
540
  }
460
541
  async function read(load, wellFormed) {
@@ -475,6 +556,9 @@ export function mount(options) {
475
556
  let stopWatching = null;
476
557
  let expiry;
477
558
  let stopped = false;
559
+ /** the editing overlay, while the page is open in Mapled's editor (Edit site) */
560
+ let stopEditor = null;
561
+ let editorOrigin = null;
478
562
  /** moves when preview is left: a fill that began before it commits nothing */
479
563
  let generation = 0;
480
564
  /** the generation of the last fill that committed: an exit's own fill is skipped when one already has */
@@ -486,11 +570,26 @@ export function mount(options) {
486
570
  page is as written again, and says so, before anything is asked of
487
571
  Mapled; what is published follows when it is in hand. */
488
572
  function leave() {
573
+ editor(false);
489
574
  restore();
490
575
  last = { state: "fallback", release: null, preview: false, bound: 0, issues: [] };
491
576
  root.setAttribute(`${P}state`, "fallback");
492
577
  root.removeAttribute(`${P}preview`);
493
578
  }
579
+ /** The overlay runs while the drafts shown are an editing session's, and only then. */
580
+ function editor(on) {
581
+ const session = on && !stopped ? previewSession() : null;
582
+ const view = doc.defaultView;
583
+ const origin = session?.mode === "edit" && view ? (session.appOrigin ?? null) : null;
584
+ if (origin === editorOrigin)
585
+ return;
586
+ stopEditor?.();
587
+ stopEditor = null;
588
+ editorOrigin = origin;
589
+ // a new editing session with another Mapled is a new overlay, listening to that one alone
590
+ if (origin && view)
591
+ stopEditor = startEditor({ appOrigin: origin, sdk: `@mapled/vanilla@${VERSION}`, onRefresh: () => void refresh(), window: view });
592
+ }
494
593
  /** Preview ends now, not after the fill in flight: the draft goes at
495
594
  once, and whatever that fill brings back is dropped. */
496
595
  function drop() {
@@ -540,6 +639,7 @@ export function mount(options) {
540
639
  console.warn(`[mapled] ${loud.length === 1 ? "1 place" : `${loud.length} places`} couldn't be filled: ${text}`);
541
640
  }
542
641
  doc.dispatchEvent(new CustomEvent(first ? "mapled:ready" : "mapled:update", { detail: report }));
642
+ editor(report.preview);
543
643
  if (report.preview)
544
644
  watchExpiry();
545
645
  else {
@@ -589,7 +689,8 @@ export function mount(options) {
589
689
  reads.push(read(() => client.getSingle(key, { ...pin, ...(expand.size > 0 ? { expand: [...expand] } : {}) }), isRecord).then((r) => singles.set(key, r)));
590
690
  }
591
691
  for (const list of page.lists) {
592
- const template = templateOf(list.el);
692
+ // a record has no type: it takes the template without one, and the read asks for what that one reads
693
+ const template = templatesOf(list.el).plain;
593
694
  const fields = template ? [...heads(compile(template.content, false)).keys()] : [];
594
695
  reads.push(read(async () => (await client.getRecords(list.collection, { ...list.options, ...pin, ...(fields.length > 0 ? { fields } : {}) })).records, isRecordList).then((r) => lists.set(list, r)));
595
696
  }
@@ -625,7 +726,7 @@ export function mount(options) {
625
726
  for (const list of page.lists) {
626
727
  const answer = lists.get(list);
627
728
  if (answer?.status === "ok")
628
- repeat(list.el, answer.value, 0);
729
+ repeat(list.el, answer.value, 0, list.collection, false);
629
730
  else
630
731
  note(list.el, list.collection, answer?.status ?? "failed");
631
732
  }
@@ -723,6 +824,7 @@ export function mount(options) {
723
824
  endPreview: exit,
724
825
  stop: () => {
725
826
  stopped = true;
827
+ editor(false);
726
828
  stopWatching?.();
727
829
  stopWatching = () => { };
728
830
  clearTimeout(expiry);
package/dist/sinks.d.ts CHANGED
@@ -27,6 +27,15 @@ export declare function writeText(el: Element, value: unknown): Refusal | null;
27
27
  export declare function writeMarkdown(el: Element, value: unknown, ctx: SinkContext): Refusal | null;
28
28
  /** `<img data-mapled-bind>`: the picture. */
29
29
  export declare function writeImage(el: Element, value: unknown, ctx: SinkContext, width?: number): Refusal | null;
30
+ /** Why `data-mapled-bind` never writes into this element, whatever the
31
+ value — or null: a refused element (rule 2), and a picture or rich
32
+ text outside HTML (writeImage, writeMarkdown). The runtime asks before
33
+ an empty value empties the place, so a place it refuses stays as the
34
+ author wrote it. */
35
+ export declare function bindRefusal(el: Element, format: Format): Refusal | null;
36
+ /** Why the attribute never goes onto this element, whatever the value —
37
+ or null (rule 3). The runtime asks before an empty value removes it. */
38
+ export declare function attributeRefusal(el: Element, name: string): Refusal | null;
30
39
  /** One attribute of the table. `name` is the page's spelling: it is
31
40
  looked up, never written as it came. */
32
41
  export declare function writeAttribute(el: Element, name: string, value: unknown, ctx: SinkContext, width?: number): Refusal | null;
package/dist/sinks.js CHANGED
@@ -70,9 +70,21 @@ export function writeImage(el, value, ctx, width) {
70
70
  el.setAttribute("src", url);
71
71
  return null;
72
72
  }
73
- /** One attribute of the table. `name` is the page's spelling: it is
74
- looked up, never written as it came. */
75
- export function writeAttribute(el, name, value, ctx, width) {
73
+ /** Why `data-mapled-bind` never writes into this element, whatever the
74
+ value — or null: a refused element (rule 2), and a picture or rich
75
+ text outside HTML (writeImage, writeMarkdown). The runtime asks before
76
+ an empty value empties the place, so a place it refuses stays as the
77
+ author wrote it. */
78
+ export function bindRefusal(el, format) {
79
+ if (!writable(el))
80
+ return "refused-element";
81
+ if ((el.localName === "img" || format === "markdown") && !isHtml(el))
82
+ return "refused-element";
83
+ return null;
84
+ }
85
+ /** Why the attribute never goes onto this element, whatever the value —
86
+ or null (rule 3). The runtime asks before an empty value removes it. */
87
+ export function attributeRefusal(el, name) {
76
88
  const key = name.toLowerCase();
77
89
  const rule = Object.prototype.hasOwnProperty.call(ATTRIBUTES, key) ? ATTRIBUTES[key] : undefined;
78
90
  if (!rule)
@@ -81,6 +93,16 @@ export function writeAttribute(el, name, value, ctx, width) {
81
93
  return "refused-element";
82
94
  if (rule.on !== null && !rule.on.includes(el.localName))
83
95
  return "unsupported";
96
+ return null;
97
+ }
98
+ /** One attribute of the table. `name` is the page's spelling: it is
99
+ looked up, never written as it came. */
100
+ export function writeAttribute(el, name, value, ctx, width) {
101
+ const refusal = attributeRefusal(el, name);
102
+ if (refusal)
103
+ return refusal;
104
+ const key = name.toLowerCase();
105
+ const rule = ATTRIBUTES[key];
84
106
  if (rule.holds === "text") {
85
107
  const text = asText(value);
86
108
  if (text === null)
package/dist/version.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  /** The package's version — what the banner of the single file and
2
2
  `Mapled.version` say. Kept equal to package.json by version.test.ts. */
3
- export declare const VERSION = "0.2.3";
3
+ export declare const VERSION = "0.4.0";
package/dist/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  /** The package's version — what the banner of the single file and
2
2
  `Mapled.version` say. Kept equal to package.json by version.test.ts. */
3
- export const VERSION = "0.2.3";
3
+ export const VERSION = "0.4.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mapled/vanilla",
3
- "version": "0.2.3",
3
+ "version": "0.4.0",
4
4
  "description": "The browser runtime of Mapled, the hosted headless CMS for sites built with AI — published content in a plain HTML site: one script tag and data-mapled attributes, no framework and no build step.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://mapled.io",
@@ -41,7 +41,7 @@
41
41
  "typecheck": "tsc --noEmit -p tsconfig.json"
42
42
  },
43
43
  "dependencies": {
44
- "@mapled/client": "^0.4.0"
44
+ "@mapled/client": "^0.5.2"
45
45
  },
46
46
  "devDependencies": {
47
47
  "esbuild": "^0.28.2",