pandorga 1.3.9 → 1.3.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/_layouts/home.html +64 -2
- data/assets/css/ledger/home.css +7 -6
- data/lib/pandorga/commands/new.rb +1 -1
- data/lib/pandorga/version.rb +1 -1
- data/studio/assets/{index-dPB8Vpbd.js → index-CaMlZpH1.js} +1 -1
- data/studio/index.html +1 -1
- data/studio-app/vite.config.js +70 -3
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6d62365b31603606857b41d2e29f212a33af07c0f0c8df530b8273f98b99433d
|
|
4
|
+
data.tar.gz: b878bb51283576f31fd00929cb2558d6afbef7218e5beb35856b1dae91719d4a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 19567d9c89c49aca581ec8816e0132469d914b59f34f993af14b22bfd15c30e9b6ea08e13557dade0ce2f6dc8e287d2ddee83a424da11f44adf96923578d9ed0
|
|
7
|
+
data.tar.gz: 8f3540cc7661664710ef2e16d1cf1a4d6b88120ee2f8a23af0a3a67095da5fdf1017ad6cc02645017dedd9b3235f7ee23a782cb062293712e66473e6471363fd
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.3.11] — 2026-10-06
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Studio SPA rebuild embeds the real Clerk Frontend API host again (was baking
|
|
8
|
+
`clerk.example.com` into `studio/`); Vite refuses placeholder publishable keys
|
|
9
|
+
|
|
10
|
+
## [1.3.10] — 2026-10-06
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Home specimen height is measured from the tallest project and locked, so
|
|
15
|
+
swapping projects no longer resizes the bench or the inventory; taglines
|
|
16
|
+
and wrapping chips still fit without clipping
|
|
17
|
+
|
|
3
18
|
## [1.3.9] — 2026-10-06
|
|
4
19
|
|
|
5
20
|
### Changed
|
data/_layouts/home.html
CHANGED
|
@@ -247,8 +247,9 @@ layout: shell
|
|
|
247
247
|
return 0;
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
-
/*
|
|
251
|
-
|
|
250
|
+
/* Lock height to the tallest project so swapping never moves the
|
|
251
|
+
inventory. Remeasure on resize when the specimen column width
|
|
252
|
+
changes (chip wrap / plate width). */
|
|
252
253
|
function paintSpecimen(entry) {
|
|
253
254
|
specimenSlot.innerHTML = '';
|
|
254
255
|
specimenSlot.appendChild(runtime.renderProjectSpecimen(asItem(entry), {
|
|
@@ -259,6 +260,53 @@ layout: shell
|
|
|
259
260
|
}));
|
|
260
261
|
}
|
|
261
262
|
|
|
263
|
+
function measureTallestSpecimen() {
|
|
264
|
+
var bench = specimenSlot.closest('.home-projects-bench');
|
|
265
|
+
if (!bench) return 0;
|
|
266
|
+
var width = specimenSlot.getBoundingClientRect().width;
|
|
267
|
+
if (width < 1) return 0;
|
|
268
|
+
|
|
269
|
+
var probe = document.createElement('div');
|
|
270
|
+
probe.setAttribute('aria-hidden', 'true');
|
|
271
|
+
probe.style.cssText = [
|
|
272
|
+
'position:absolute',
|
|
273
|
+
'visibility:hidden',
|
|
274
|
+
'pointer-events:none',
|
|
275
|
+
'left:0',
|
|
276
|
+
'top:0',
|
|
277
|
+
'width:' + Math.round(width) + 'px',
|
|
278
|
+
'height:auto',
|
|
279
|
+
'overflow:visible'
|
|
280
|
+
].join(';');
|
|
281
|
+
bench.appendChild(probe);
|
|
282
|
+
|
|
283
|
+
var max = 0;
|
|
284
|
+
portfolio.forEach(function (entry, i) {
|
|
285
|
+
probe.innerHTML = '';
|
|
286
|
+
var card = runtime.renderProjectSpecimen(asItem(entry), {
|
|
287
|
+
href: entry.url || runtime.projectUrl(entry.slug),
|
|
288
|
+
tagHref: systemTagHref,
|
|
289
|
+
folio: i + 1,
|
|
290
|
+
openLabel: 'Open project'
|
|
291
|
+
});
|
|
292
|
+
card.style.height = 'auto';
|
|
293
|
+
card.style.minHeight = '0';
|
|
294
|
+
probe.appendChild(card);
|
|
295
|
+
max = Math.max(max, Math.ceil(card.getBoundingClientRect().height));
|
|
296
|
+
});
|
|
297
|
+
probe.remove();
|
|
298
|
+
return max;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function lockSpecimenHeight() {
|
|
302
|
+
var bench = specimenSlot.closest('.home-projects-bench');
|
|
303
|
+
if (!bench) return;
|
|
304
|
+
var tallest = measureTallestSpecimen();
|
|
305
|
+
if (tallest > 0) {
|
|
306
|
+
bench.style.setProperty('--home-specimen-height', tallest + 'px');
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
262
310
|
function select(slug) {
|
|
263
311
|
if (selectedSlug === slug) return;
|
|
264
312
|
selectedSlug = slug;
|
|
@@ -293,8 +341,22 @@ layout: shell
|
|
|
293
341
|
});
|
|
294
342
|
}
|
|
295
343
|
|
|
344
|
+
lockSpecimenHeight();
|
|
296
345
|
paintSpecimen(entryBySlug(selectedSlug));
|
|
297
346
|
paintInventory();
|
|
347
|
+
|
|
348
|
+
var resizeTimer = null;
|
|
349
|
+
var lastMeasureWidth = Math.round(specimenSlot.getBoundingClientRect().width);
|
|
350
|
+
window.addEventListener('resize', function () {
|
|
351
|
+
window.clearTimeout(resizeTimer);
|
|
352
|
+
resizeTimer = window.setTimeout(function () {
|
|
353
|
+
var nextWidth = Math.round(specimenSlot.getBoundingClientRect().width);
|
|
354
|
+
if (nextWidth === lastMeasureWidth) return;
|
|
355
|
+
lastMeasureWidth = nextWidth;
|
|
356
|
+
lockSpecimenHeight();
|
|
357
|
+
paintSpecimen(entryBySlug(selectedSlug));
|
|
358
|
+
}, 120);
|
|
359
|
+
});
|
|
298
360
|
return;
|
|
299
361
|
}
|
|
300
362
|
|
data/assets/css/ledger/home.css
CHANGED
|
@@ -944,9 +944,11 @@ html[data-theme="light"] .home-hero-plate {
|
|
|
944
944
|
}
|
|
945
945
|
|
|
946
946
|
/* ── Engineering artifacts: specimen bench ──
|
|
947
|
-
A specimen card beside a filing rack of project cards.
|
|
948
|
-
|
|
949
|
-
|
|
947
|
+
A specimen card beside a filing rack of project cards. Height is locked to
|
|
948
|
+
the tallest project (home.html measures once, then sets
|
|
949
|
+
`--home-specimen-height`), so swapping projects never resizes the band or
|
|
950
|
+
the inventory. Taglines stay full length and chips wrap whole pills like
|
|
951
|
+
the projects index; spare height parks chips and the foot on the floor.
|
|
950
952
|
Every plate is 16:9, the ratio the thumbnails are drawn at, with the title
|
|
951
953
|
below it. From 900px the specimen is half the band and the rack a narrower
|
|
952
954
|
column beside it, the rest left blank. Below 900px the rack is an icon strip
|
|
@@ -966,8 +968,7 @@ html[data-theme="light"] .home-hero-plate {
|
|
|
966
968
|
}
|
|
967
969
|
|
|
968
970
|
.home-project-specimen {
|
|
969
|
-
|
|
970
|
-
height: auto;
|
|
971
|
+
height: var(--home-specimen-height);
|
|
971
972
|
overflow: hidden;
|
|
972
973
|
gap: var(--space-sm);
|
|
973
974
|
padding: var(--space-md);
|
|
@@ -1266,7 +1267,7 @@ html[data-theme="light"] .home-hero-plate {
|
|
|
1266
1267
|
|
|
1267
1268
|
@media (min-width: 900px) {
|
|
1268
1269
|
|
|
1269
|
-
/*
|
|
1270
|
+
/* Desktop fallback before JS measures the tallest specimen. */
|
|
1270
1271
|
.home-projects-bench {
|
|
1271
1272
|
--home-specimen-height: 36rem;
|
|
1272
1273
|
display: grid;
|
|
@@ -24,7 +24,7 @@ module Pandorga
|
|
|
24
24
|
|
|
25
25
|
gem "pandorga", "~> 1.3"
|
|
26
26
|
# Local checkout: gem "pandorga", path: "../pandorga"
|
|
27
|
-
# GitHub tag: gem "pandorga", github: "alexandrelheinen/pandorga", tag: "v1.3.
|
|
27
|
+
# GitHub tag: gem "pandorga", github: "alexandrelheinen/pandorga", tag: "v1.3.11"
|
|
28
28
|
gem "csv"
|
|
29
29
|
gem "base64"
|
|
30
30
|
RUBY
|
data/lib/pandorga/version.rb
CHANGED
|
@@ -265,7 +265,7 @@ Please report this to https://github.com/markedjs/marked.`,t){const r="<p>An err
|
|
|
265
265
|
`)}function ev(t){const e=String(t.body||"").trim();if(!e)return"";const n=String(t.handle||"").trim().replace(/^@/,""),r=String(t.icon||"chat").trim()||"chat",i=String(t.url||"").trim(),s=String(t.date||"").trim(),o=String(t.note||"").trim(),l=String(t.name||"").trim(),a=i.replace(/^https?:\/\//,""),c=['<article class="sov-tweet article-tweet">','<div class="sov-tweet__head article-tweet__head">',`<span class="sov-tweet__avatar article-tweet__avatar" aria-hidden="true"><span class="material-symbols-outlined">${Se(r)}</span></span>`,'<span class="sov-tweet__id article-tweet__id">'];if(l&&c.push(`<span class="sov-tweet__name article-tweet__name">${Se(l)}</span>`),n&&c.push(`<span class="sov-tweet__handle article-tweet__handle">@${Se(n)}</span>`),c.push("</span></div>"),c.push(`<p class="sov-tweet__body article-tweet__body">${e}</p>`),i||s){let u="";i&&(u+=`<a href="${Ie(i)}">${Se(a)}</a>`),i&&s&&(u+=" | "),s&&(u+=Se(s)),c.push(`<p class="sov-tweet__cite article-tweet__cite">${u}</p>`)}return o&&c.push(`<p class="sov-tweet__note article-tweet__note">${o}</p>`),c.push("</article>"),c.join("")}function Fd(t){const e=String(t||"").trim();if(!e)return'<div class="article-note"></div>';let n="";try{n=ie.parse(e,{gfm:!0,breaks:!1})}catch{n=`<p>${Se(e)}</p>`}return`<div class="article-note">${n}</div>`}function tv(t,e){return Vm(String(t||"").trim(),{variant:"latex",display:!!e})}function Hd(t){return String(t||"").replace(/\\\s/g,"\\\\ ")}function nv(t){const e=[];let n=String(t||"");const r=(i,s)=>{const o=e.length;return e.push({display:i,math:s}),`MATH${o}`};return n=n.replace(/\$\$([\s\S]+?)\$\$/g,(i,s)=>r(!0,Hd(s))),n=n.replace(/\\\[([\s\S]+?)\\\]/g,(i,s)=>r(!0,Hd(s))),n=n.replace(/\\\(([\s\S]+?)\\\)/g,(i,s)=>r(!1,s)),n=n.replace(/(^|[^\\$])\$(?!\$)([^$\n]+?)\$(?!\$)/g,(i,s,o)=>s+r(!1,o)),{text:n,store:e}}function rv(t,e){return String(t||"").replace(/\uE000MATH(\d+)\uE001/g,(n,r)=>{const i=e[Number(r)];return i?tv(i.math,i.display):""})}const iv={"figure.html":VC,"cut-in.html":UC,"youtube.html":qC,"youtube-short.html":WC,"video.html":KC,"plotly.html":YC,"xcite.html":GC,"cite.html":JC,"dict-card.html":ZC,"tweet.html":ev};function sv(t){let e=String(t||"");return e=e.replace(/\{%-?\s*include\s+article-note(?:\.html)?\b(?:(?!%\})[\s\S])*?-?%\}\s*([\s\S]*?)\s*\{%-?\s*endinclude\s*-?%\}/gi,(n,r)=>Fd(r)),e=e.replace(/<div\s+([^>]*\barticle-note\b[^>]*)>([\s\S]*?)<\/div>/gi,(n,r,i)=>Fd(i)),e=e.replace(/\{%-?\s*cite\s+([^\s%]+)[\s\S]*?-?%\}/g,(n,r)=>gc("cite",r)),e=e.replace(/\{%-?\s*include\s+([\w.-]+)\s*((?:(?!%\})[\s\S])*?)\s*-?%\}/g,(n,r,i)=>{const s=iv[r];return s?s(jC(i)):`<div class="studio-unknown-include" data-include="${Ie(r)}"></div>`}),e}function ov(t){const e=nv(String(t||"")),n=sv(e.text);let r;try{r=ie.parse(n,{gfm:!0,breaks:!1})}catch{r=`<p>${Se(n)}</p>`}return QC(rv(r,e.store))}function kn(t,e,n=1){return String(t||"").localeCompare(String(e||""),void 0,{sensitivity:"base",numeric:!0})*n}function jd(t,e,n=1){const r=String(t||""),i=String(e||"");return!r&&!i?0:r?i?r.localeCompare(i)*n:-1:1}const eo=[{id:"date-desc",label:"Date | newest first",compare:(t,e)=>jd(t.date,e.date,-1)||kn(t.title||t.name,e.title||e.name)},{id:"date-asc",label:"Date | oldest first",compare:(t,e)=>jd(t.date,e.date,1)||kn(t.title||t.name,e.title||e.name)},{id:"title-asc",label:"Title | A–Z",compare:(t,e)=>kn(t.title||t.name,e.title||e.name,1)},{id:"title-desc",label:"Title | Z–A",compare:(t,e)=>kn(t.title||t.name,e.title||e.name,-1)},{id:"path-asc",label:"Path | A–Z",compare:(t,e)=>kn(t.path||t.name,e.path||e.name,1)},{id:"path-desc",label:"Path | Z–A",compare:(t,e)=>kn(t.path||t.name,e.path||e.name,-1)},{id:"key-asc",label:"Key | A–Z",compare:(t,e)=>kn(t.key||t.name,e.key||e.name,1)}],to="date-desc",no=[{id:"10",label:"10",size:10},{id:"20",label:"20",size:20},{id:"30",label:"30",size:30},{id:"all",label:"ALL",size:null}],ro="10",Um="studio-list-sort:",qm="studio-list-page-size:";function lv(t){return eo.find(e=>e.id===t)||eo[0]}function av(t){return no.find(e=>e.id===t)||no[0]}function Mi(t){const e=t==null?void 0:t.tags;return Array.isArray(e)?e.map(n=>String(n??"").trim()).filter(Boolean):typeof e=="string"&&e.trim()?[e.trim()]:[]}function cv(t,e){const n=String(e||"").trim().toLowerCase();return n?t.filter(r=>[r.title,r.name,r.key,r.path,r.date,Mi(r).join(" ")].filter(Boolean).join(`
|
|
266
266
|
`).toLowerCase().includes(n)):t.slice()}function uv(t,e){const n=String(e||"").trim().toLowerCase();return n?t.filter(r=>Mi(r).some(i=>i.toLowerCase()===n)):t.slice()}function dv(t){const e=new Map;for(const n of t||[])for(const r of Mi(n)){const i=r.toLowerCase();e.has(i)||e.set(i,r)}return[...e.values()].sort((n,r)=>n.localeCompare(r,void 0,{sensitivity:"base"}))}function fv(t,{query:e="",sortId:n=to,tag:r=""}={}){const i=uv(cv(t,e),r),s=lv(n);return i.sort((o,l)=>s.compare(o,l))}function pv(t,{pageSizeId:e=ro,page:n=1}={}){const r=av(e),i=t.length,s=r.size;if(s==null||s<=0)return{items:t.slice(),page:1,pageCount:1,pageSize:null,total:i,from:i?1:0,to:i};const o=Math.max(1,Math.ceil(i/s)),l=Math.min(Math.max(1,Number(n)||1),o),a=(l-1)*s,c=t.slice(a,a+s);return{items:c,page:l,pageCount:o,pageSize:s,total:i,from:i?a+1:0,to:a+c.length}}function hv(t,e=to){try{const n=localStorage.getItem(Um+t);if(n&&eo.some(r=>r.id===n))return n}catch{}return e}function mv(t,e){try{localStorage.setItem(Um+t,e)}catch{}}function gv(t,e=ro){try{const n=localStorage.getItem(qm+t);if(n&&no.some(r=>r.id===n))return n}catch{}return e}function yv(t,e){try{localStorage.setItem(qm+t,e)}catch{}}const Vd={posts:["date"],articles:["date"],resources:["category","type","language"],bibliography:["key"],products:["company","start_date","end_date"],projects:["status","start_date","end_date"],jobs:["company","engagement","start","end"]},bv=new Set(["name","filename"]);function kv(t){const e=String(t||"").split("/").filter(Boolean);return e.length?e[e.length-1]:""}function xv(t,e){if(t==="path")return String(e.path||"").split("/").filter(Boolean).join(" | ")||"";const n=e==null?void 0:e[t];return n==null?"":Array.isArray(n)?n.map(r=>String(r??"").trim()).filter(Boolean).join(", "):String(n).trim()}function Sv(t){if(Array.isArray(t==null?void 0:t.listMetaFields)&&t.listMetaFields.length)return t.listMetaFields.map(String);const e=t==null?void 0:t.name;return e&&Vd[e]?Vd[e].slice():[]}function wv(t,e){const n=Array.isArray(e)?e.map(String):Sv(e),r=[];for(const s of n){if(bv.has(s))continue;const o=xv(s,t);o&&r.push(o)}const i=String((t==null?void 0:t.name)||"").trim()||kv(t==null?void 0:t.path);return i&&r[r.length-1]!==i&&r.push(i),r.join(" | ")}const Cv={lineWidth:100,noRefs:!0,sortKeys:!1};function mr(t){return!t||t.format!=="yaml"?null:t.list?"list":t.root_key||(t.fields||[]).length?"map":"source"}function Bt(t){const e=un.dump(t??null,Cv);return e.endsWith(`
|
|
267
267
|
`)?e:e+`
|
|
268
|
-
`}function Xr(t){try{return un.load(t)}catch(e){const n=new Error((e==null?void 0:e.message)||"Invalid YAML");throw n.cause=e,n}}function Wm(t){const e={};for(const n of t||[])!(n!=null&&n.name)||n.hidden||(Object.prototype.hasOwnProperty.call(n,"default")?e[n.name]=vv(n.default):n.list?e[n.name]=[]:n.type==="boolean"?e[n.name]=!1:e[n.name]="");return e}function vv(t){if(t==null||typeof t!="object")return t;try{return structuredClone(t)}catch{return JSON.parse(JSON.stringify(t))}}function dr(t,e){if(!t||typeof t!="object"||Array.isArray(t))return t;const n=new Set((e||[]).map(i=>i.name).filter(Boolean)),r={...t};for(const i of Object.keys(r)){if(!n.has(i))continue;const s=r[i];(s===""||s==null||Array.isArray(s)&&s.length===0)&&delete r[i]}return r}function Km(t){return Array.isArray(t)?t.map(e=>e&&typeof e=="object"&&!Array.isArray(e)?{...e}:{}):[]}function nr(t){return t&&typeof t=="object"&&!Array.isArray(t)?{...t}:{}}const bt="content/media",Ud=25*1024*1024,Mv=/\.(png|jpe?g|gif|webp|svg|avif|bmp|ico)$/i,Tv=/\.(mp4|webm|mov|m4v)$/i,Av=/\.html?$/i,Ym=/^[A-Za-z0-9][A-Za-z0-9._-]*$/;function Ev(t){var n;const e=String(((n=t==null?void 0:t.media)==null?void 0:n.input)||bt).replace(/\/+$/,"");return e===bt||e.startsWith(`${bt}/`),bt}function Mo(t){const e=String(t||"");return e.startsWith("content/media")?e.replace(/^content/,"")||"/media":""}function Gm(t){return Mv.test(String(t||""))}function Jm(t){return Tv.test(String(t||""))}function Xm(t){return Av.test(String(t||""))}function Zm(t){return Gm(t)?"image":Jm(t)?"video":Xm(t)?"html":null}function Qm(t){const e=Number(t)||0;return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}function Nv(t){const e=String(t||"").split(/[/\\]/).pop().trim();if(!e)return null;const n=e.replace(/\s+/g,"-").replace(/[^A-Za-z0-9._-]/g,"");return Ym.test(n)?n:null}function Ov(t){const e=String(t||"").trim().replace(/\s+/g,"-").replace(/[^A-Za-z0-9._-]/g,"");return!Ym.test(e)||e===".gitkeep"?null:e}function Lv(t){return new Promise((e,n)=>{const r=new FileReader;r.onload=()=>{const i=String(r.result||""),s=i.indexOf(",");e(s>=0?i.slice(s+1):i)},r.onerror=()=>n(r.error||new Error("read_failed")),r.readAsDataURL(t)})}function Iv(t,e=bt){const r=String(t).split("/").filter(Boolean),i=e.split("/").filter(Boolean),s=[];let o="";for(let l=0;l<r.length;l++){o=o?`${o}/${r[l]}`:r[l];const a=l===i.length-1&&o===e;!(l>=i.length-1)&&!a||s.push({label:a||o===e?"media":r[l],path:o})}return s.length||s.push({label:"media",path:e}),s}function Rv(t){const{api:e,state:n,el:r,materialIcon:i,resolveMediaUrl:s,render:o,captureError:l,clearError:a,goHome:c}=t,u=n.mediaPath||bt,d=n.mediaItems||[],p=Iv(u),h=r("nav",{className:"media-breadcrumb","aria-label":"Media path"});p.forEach((N,R)=>{R>0&&h.append(r("span",{className:"media-breadcrumb-sep",text:"/"})),R===p.length-1?h.append(r("span",{className:"media-breadcrumb-current",text:N.label})):h.append(r("button",{className:"media-breadcrumb-link",type:"button",text:N.label,onClick:()=>void Ti(N.path,t)}))});const g=r("input",{type:"file",className:"media-file-input",multiple:"multiple",accept:"image/*,video/*,.html,.svg,.pdf",hidden:!0,onChange:async N=>{const R=Array.from(N.target.files||[]);N.target.value="",R.length&&await _v(R,t)}}),b=r("div",{className:"media-toolbar"},[r("button",{className:"btn btn-nav",type:"button",title:"Back to Studio map",onClick:()=>c()},[i("chevron_left","btn-nav-icon"),r("span",{text:"Studio map"})]),r("span",{className:"spacer"}),r("button",{className:"btn",type:"button",text:"New folder",disabled:!!n.mediaBusy,onClick:()=>void Bv(t)}),r("button",{className:"btn btn-primary",type:"button",text:n.mediaBusy?"Working…":"Upload",disabled:!!n.mediaBusy,onClick:()=>g.click()}),g]),x=r("p",{className:"media-hint",text:"Click an image, video, or HTML file to preview it. Copy the public path into includes (e.g. /media/images/…). Deletes stay in GitHub/IDE."});let w;if(n.mediaLoading)w=r("p",{className:"loading-msg",text:"Loading media…"});else if(!d.length)w=r("p",{className:"empty-msg",text:"This folder is empty. Upload a file or create a subfolder."});else{const N=d.map(R=>Pv(R,t));w=r("div",{className:"media-grid",role:"list"},N)}return r("div",{className:"pane media-pane"},[r("header",{className:"media-header"},[r("h1",{className:"media-title",text:"Media"}),h,x]),b,w])}function Pv(t,e){const{el:n,materialIcon:r,resolveMediaUrl:i,state:s}=e,o=t.type==="dir",l=o?null:Zm(t.name),a=t.public_path||(o?null:Mo(t.path)),c=!o&&Gm(t.name)&&a?i(a):"";let u;if(o)u=n("span",{className:"media-thumb media-thumb--folder"},[r("folder","media-thumb-icon")]);else if(c){const g=n("img",{className:"media-thumb-img",src:c,alt:"",loading:"lazy",referrerpolicy:"no-referrer"});g.addEventListener("error",()=>{g.replaceWith(n("span",{className:"media-thumb media-thumb--file"},[r("image","media-thumb-icon")]))}),u=n("span",{className:"media-thumb media-thumb--image"},[g])}else Jm(t.name)?u=n("span",{className:"media-thumb media-thumb--file"},[r("movie","media-thumb-icon")]):Xm(t.name)?u=n("span",{className:"media-thumb media-thumb--file"},[r("html","media-thumb-icon")]):u=n("span",{className:"media-thumb media-thumb--file"},[r("draft","media-thumb-icon")]);const d=[];!o&&t.size&&d.push(Qm(t.size)),a&&d.push(a);const p=o?()=>void Ti(t.path,e):l?g=>$v(t,g.currentTarget,e):()=>void qd(a,e),h=o?`Open ${t.name}`:l?`Preview ${t.name}`:`Copy ${a}`;return n("div",{className:"media-row"+(o?" media-row--dir":""),role:"listitem"},[n("button",{className:"media-row-main"+(l?" media-row-main--preview":""),type:"button",title:h,disabled:!!s.mediaBusy,onClick:p},[u,n("span",{className:"media-row-body"},[n("span",{className:"media-row-name",text:t.name}),n("span",{className:"media-row-meta",text:d.join(" · ")||(o?"Folder":"")})])]),!o&&a?n("button",{className:"btn media-copy-btn",type:"button",text:"Copy path",title:a,disabled:!!s.mediaBusy,onClick:()=>void qd(a,e)}):null].filter(Boolean))}let yt=null,xa=null;function Dv(t,e){if(yt)return yt;const n=t("img",{className:"figure-lightbox-img",alt:""}),r=t("video",{className:"figure-lightbox-video",controls:!0,playsinline:!0}),i=t("iframe",{className:"figure-lightbox-frame",title:"Media preview"}),s=t("p",{className:"figure-lightbox-caption"});n.hidden=!0,r.hidden=!0,i.hidden=!0,s.hidden=!0,r.controls=!0;const o=t("button",{type:"button",className:"figure-lightbox-close","data-lightbox-close":"true","aria-label":"Close",onClick:a=>{a.preventDefault(),Nl()}},[e("close")]),l=t("div",{id:"figure-lightbox",className:"figure-lightbox",role:"dialog","aria-modal":"true","aria-label":"Media preview","aria-hidden":"true"},[t("div",{className:"figure-lightbox-backdrop","data-lightbox-close":"true",tabindex:"-1",onClick:()=>Nl()}),t("div",{className:"figure-lightbox-panel"},[o,n,r,i,s])]);return l.hidden=!0,document.body.append(l),document.addEventListener("keydown",a=>{!yt||yt.root.hidden||a.key==="Escape"&&(a.preventDefault(),Nl())}),yt={root:l,img:n,video:r,frame:i,caption:s,closeBtn:o},yt}function eg(t){t.img.removeAttribute("src"),t.img.alt="",t.img.hidden=!0,t.video.pause(),t.video.removeAttribute("src"),t.video.load(),t.video.hidden=!0,t.frame.removeAttribute("src"),t.frame.hidden=!0,t.caption.textContent="",t.caption.hidden=!0}function tg(t,e){t.root.hidden=!e,t.root.setAttribute("aria-hidden",String(!e)),document.documentElement.classList.toggle("figure-lightbox-open",e),document.body.classList.toggle("figure-lightbox-open",e)}function Nl(){if(!yt||yt.root.hidden)return;eg(yt),tg(yt,!1);const t=xa;if(xa=null,t&&typeof t.focus=="function")try{t.focus()}catch{}}function $v(t,e,n){const{el:r,materialIcon:i,resolveMediaUrl:s}=n,o=Zm(t.name),l=t.public_path||Mo(t.path),a=l?s(l):"";if(!o||!a)return;const c=Dv(r,i);xa=e||null,eg(c),o==="image"?(c.img.hidden=!1,c.img.referrerPolicy="no-referrer",c.img.alt=t.name||"",c.img.src=a):o==="video"?(c.video.hidden=!1,c.video.referrerPolicy="no-referrer",c.video.src=a):(c.frame.hidden=!1,c.frame.title=t.name||"HTML preview",c.frame.src=a),c.caption.textContent=t.name||"",c.caption.hidden=!t.name,tg(c,!0),c.closeBtn.focus()}async function qd(t,e){const{state:n,render:r,captureError:i,clearError:s}=e;if(t){s();try{await navigator.clipboard.writeText(t),n.status=`Copied ${t}`}catch(o){i(o),n.status=t}r()}}async function Ti(t,e){const{api:n,state:r,render:i,captureError:s,clearError:o}=e;o(),r.mediaPath=t||bt,r.mediaLoading=!0,r.mediaBusy=!1,r.status=`Loading ${r.mediaPath}…`,i();try{const l=await n.listMedia(r.mediaPath);r.mediaItems=l.items||[],r.mediaPath=l.path||r.mediaPath,r.mediaLoading=!1;const a=r.mediaItems.filter(u=>u.type==="dir").length,c=r.mediaItems.filter(u=>u.type==="file").length;r.status=`${a} folders · ${c} files`}catch(l){r.mediaItems=[],r.mediaLoading=!1,s(l)}i()}async function Bv(t){const{api:e,state:n,render:r,captureError:i,clearError:s}=t,o=window.prompt("New folder name (letters, numbers, .-_)");if(o==null)return;const l=Ov(o);if(!l){n.error="Invalid folder name",n.status="",r();return}const a=`${n.mediaPath||bt}/${l}`;s(),n.mediaBusy=!0,n.status=`Creating ${l}…`,r();try{await e.createMediaFolder({path:a,message:`studio: mkdir ${a}`}),n.mediaBusy=!1,n.status=`Created ${Mo(a)||a}`,await Ti(n.mediaPath,t)}catch(c){n.mediaBusy=!1,i(c),r()}}async function _v(t,e){const{api:n,state:r,render:i,captureError:s,clearError:o}=e;o();const l=r.mediaPath||bt;let a=0;r.mediaBusy=!0;for(const c of t){const u=Nv(c.name);if(!u){r.error=`Skipped invalid name: ${c.name}`;continue}if(c.size>Ud){r.error=`${u} exceeds ${Qm(Ud)} (GitHub Contents API soft limit in Studio)`;continue}r.status=`Uploading ${u}…`,i();try{const d=await Lv(c),p=`${l}/${u}`,h=await n.uploadMedia({path:p,content_base64:d,message:`studio: upload ${p}`});a+=1,r.status=`Uploaded ${h.public_path||Mo(p)}`}catch(d){s(d),r.mediaBusy=!1,i();return}}r.mediaBusy=!1,a&&(r.status=a===1?r.status:`Uploaded ${a} files`),await Ti(l,e)}const zv="pk_test_Y2xlcmsuZXhhbXBsZS5jb20k",Zt="/studio/",Wd="",ng={forceRedirectUrl:Zt,fallbackRedirectUrl:Zt,signInForceRedirectUrl:Zt,signInFallbackRedirectUrl:Zt,signUpForceRedirectUrl:Zt,signUpFallbackRedirectUrl:Zt};function Fv(t){const e=String(t).replace(/^pk_(test|live)_/,"");if(!e)return"";try{const n="=".repeat((4-e.length%4)%4),r=(e+n).replace(/-/g,"+").replace(/_/g,"/");return atob(r).replace(/\$$/,"").trim()}catch{return""}}function Kd(t,e={}){return new Promise((n,r)=>{const i=document.querySelector(`script[src="${t}"]`);if(i){if(i.dataset.loaded==="1")return n();i.addEventListener("load",()=>n(),{once:!0}),i.addEventListener("error",()=>r(new Error(`Failed to load ${t}`)),{once:!0});return}const s=document.createElement("script");s.src=t,s.async=!0,s.defer=!0,s.crossOrigin="anonymous";for(const[o,l]of Object.entries(e))if(o==="dataset"&&l&&typeof l=="object")for(const[a,c]of Object.entries(l))s.dataset[a]=c;else l!=null&&s.setAttribute(o,l);s.onload=()=>{s.dataset.loaded="1",n()},s.onerror=()=>r(new Error(`Failed to load ${t}`)),document.head.appendChild(s)})}async function Hv(t){if(window.Clerk&&typeof window.Clerk.load=="function"&&window.__internal_ClerkUICtor)return window.Clerk;const e="".replace(/^https?:\/\//,"").replace(/\/$/,"")||Fv(t);if(!e)throw new Error("Cannot resolve Clerk Frontend API host from publishable key");const n=`https://${e}/npm`;await Kd(`${n}/@clerk/ui@1/dist/ui.browser.js`),await Kd(`${n}/@clerk/clerk-js@6/dist/clerk.browser.js`,{dataset:{clerkPublishableKey:t}});for(let r=0;r<80;r++){if(window.Clerk&&typeof window.Clerk.load=="function"&&window.__internal_ClerkUICtor)return window.Clerk;await new Promise(s=>setTimeout(s,25))}throw new Error("Clerk / ClerkUI global missing after script load")}async function jv(){const t=await Hv(zv);return await t.load({clerkUICtor:window.__internal_ClerkUICtor,...ng}),Dg(async()=>t.session?t.session.getToken():null),t}const ot=document.getElementById("app"),m={schema:null,session:null,collection:null,items:[],file:null,sha:null,fields:{},body:"",yamlDoc:null,yamlList:null,yamlUiMode:"structured",bodyMode:"visual",lastEditorMode:"visual",baseline:null,dirty:!1,saving:!1,status:"",error:"",errorCode:"",errorDetail:"",listLoading:!1,fileLoading:!1,previewHtml:"",bodyEditor:null,insertMenuOpen:!1,aiProofHint:"",aiProofBusy:!1,aiProofSelection:null,navOpenGroups:new Set,navMenuOpen:!1,themeMenuOpen:!1,listQueryByCollection:Object.create(null),listSortByCollection:Object.create(null),listPageSizeByCollection:Object.create(null),listPageByCollection:Object.create(null),listTagByCollection:Object.create(null),navCountByCollection:Object.create(null),treeCacheByCollection:Object.create(null),treePrefetchGen:0,frontMatterOpen:null,mediaOpen:!1,mediaPath:"content/media",mediaItems:[],mediaLoading:!1,mediaBusy:!1},Vv={figure:"image",cutIn:"transition_push",youtube:"smart_display",youtubeShort:"mobile_screen_share",video:"videocam",plotly:"analytics",xcite:"format_quote",cite:"bookmark",articleNote:"sticky_note_2",poem:"history_edu"},Sa={Writing:"edit_note",References:"menu_book",Portfolio:"work",Media:"photo_library",Pages:"description","CV Summary":"badge",Presentation:"campaign",Profile:"person"},Uv=[{label:"Default",value:""},{label:"Primary",value:"var(--primary)"},{label:"Secondary",value:"var(--secondary)"},{label:"Tertiary",value:"var(--tertiary)"},{label:"Muted",value:"var(--on-surface-variant)"},{label:"Error",value:"var(--error)"}],qv={Writing:"Articles and Portuguese rascunhos",References:"Source cards and bibliography entries",Portfolio:"Products, projects, and CV jobs",Media:"Upload and browse content/media — cite /media/… in includes",Pages:"Listing page headers and furniture copy","CV Summary":"Public and PDF CV summary variants",Presentation:"Home catch phrase and CV side notes",Profile:"Contacts, education, languages, and skills"};function Ai(t){return String(t||"").split("/").filter(Boolean).join(" | ")}function rg(t){return qv[t]||`Browse ${t} collections`}function ig(t){return"nav-group-"+String(t).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")}function sg(t){const e=og(t.description);if(e)return e;const n=Ai(t.path)||t.name;return t.type==="file"?`Open ${t.label} | ${n}`:`List entries in ${t.label} | ${n}`}function og(t){let e=String(t||"").trim();if(!e)return"";const n=[/\s*The filename uses Key as YYYY-MM-DD-key[^.]*\./gi,/\s*Also the filename stem:[^.]*\./gi,/\s*Also the filename:[^.]*\./gi,/\s*Must match the YYYY-MM-DD in the filename[^.]*\./gi,/\s*;?\s*must match the YYYY-MM-DD in the filename\./gi,/\s*The Updated date is read from Git, never set here\./gi,/\s*ASCII kebab-case\./gi,/\s*\(44 characters total for the key segment is a good ceiling\)\.?/gi,/Metadata-first forms[^.]*\./gi,/TipTap with Liquid blocks[^.]*\./gi,/preview via content-runtime contract\.?/gi,/Paste Liquid \{%\s*include\s*%\} markers[^.]*\./gi,/Do not use rich-text:[^.]*\./gi,/its Editor mode rewrites URLs inside includes\.?/gi,/Markdown source \(code editor\)\.?/gi];for(const r of n)e=e.replace(r,"");return e=e.replace(/\s{2,}/g," ").replace(/\s+\./g,".").trim(),/filename|YYYY-MM-DD-key|content-runtime|autolink|TipTap/i.test(e)?"":e}function Yd(t){return og(t==null?void 0:t.description)}function zn(t){var i,s;const e=String((t==null?void 0:t.message)||t||"Request failed"),n=[];t!=null&&t.status&&n.push(`HTTP ${t.status}`);const r=(i=t==null?void 0:t.data)==null?void 0:i.detail;if(r)n.push(String(r));else if(t!=null&&t.data&&typeof t.data=="object")try{n.push(JSON.stringify(t.data,null,2))}catch{}else t!=null&&t.stack&&!String(t.stack).includes(e)&&n.push(String(t.stack).split(`
|
|
268
|
+
`}function Xr(t){try{return un.load(t)}catch(e){const n=new Error((e==null?void 0:e.message)||"Invalid YAML");throw n.cause=e,n}}function Wm(t){const e={};for(const n of t||[])!(n!=null&&n.name)||n.hidden||(Object.prototype.hasOwnProperty.call(n,"default")?e[n.name]=vv(n.default):n.list?e[n.name]=[]:n.type==="boolean"?e[n.name]=!1:e[n.name]="");return e}function vv(t){if(t==null||typeof t!="object")return t;try{return structuredClone(t)}catch{return JSON.parse(JSON.stringify(t))}}function dr(t,e){if(!t||typeof t!="object"||Array.isArray(t))return t;const n=new Set((e||[]).map(i=>i.name).filter(Boolean)),r={...t};for(const i of Object.keys(r)){if(!n.has(i))continue;const s=r[i];(s===""||s==null||Array.isArray(s)&&s.length===0)&&delete r[i]}return r}function Km(t){return Array.isArray(t)?t.map(e=>e&&typeof e=="object"&&!Array.isArray(e)?{...e}:{}):[]}function nr(t){return t&&typeof t=="object"&&!Array.isArray(t)?{...t}:{}}const bt="content/media",Ud=25*1024*1024,Mv=/\.(png|jpe?g|gif|webp|svg|avif|bmp|ico)$/i,Tv=/\.(mp4|webm|mov|m4v)$/i,Av=/\.html?$/i,Ym=/^[A-Za-z0-9][A-Za-z0-9._-]*$/;function Ev(t){var n;const e=String(((n=t==null?void 0:t.media)==null?void 0:n.input)||bt).replace(/\/+$/,"");return e===bt||e.startsWith(`${bt}/`),bt}function Mo(t){const e=String(t||"");return e.startsWith("content/media")?e.replace(/^content/,"")||"/media":""}function Gm(t){return Mv.test(String(t||""))}function Jm(t){return Tv.test(String(t||""))}function Xm(t){return Av.test(String(t||""))}function Zm(t){return Gm(t)?"image":Jm(t)?"video":Xm(t)?"html":null}function Qm(t){const e=Number(t)||0;return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}function Nv(t){const e=String(t||"").split(/[/\\]/).pop().trim();if(!e)return null;const n=e.replace(/\s+/g,"-").replace(/[^A-Za-z0-9._-]/g,"");return Ym.test(n)?n:null}function Ov(t){const e=String(t||"").trim().replace(/\s+/g,"-").replace(/[^A-Za-z0-9._-]/g,"");return!Ym.test(e)||e===".gitkeep"?null:e}function Lv(t){return new Promise((e,n)=>{const r=new FileReader;r.onload=()=>{const i=String(r.result||""),s=i.indexOf(",");e(s>=0?i.slice(s+1):i)},r.onerror=()=>n(r.error||new Error("read_failed")),r.readAsDataURL(t)})}function Iv(t,e=bt){const r=String(t).split("/").filter(Boolean),i=e.split("/").filter(Boolean),s=[];let o="";for(let l=0;l<r.length;l++){o=o?`${o}/${r[l]}`:r[l];const a=l===i.length-1&&o===e;!(l>=i.length-1)&&!a||s.push({label:a||o===e?"media":r[l],path:o})}return s.length||s.push({label:"media",path:e}),s}function Rv(t){const{api:e,state:n,el:r,materialIcon:i,resolveMediaUrl:s,render:o,captureError:l,clearError:a,goHome:c}=t,u=n.mediaPath||bt,d=n.mediaItems||[],p=Iv(u),h=r("nav",{className:"media-breadcrumb","aria-label":"Media path"});p.forEach((N,R)=>{R>0&&h.append(r("span",{className:"media-breadcrumb-sep",text:"/"})),R===p.length-1?h.append(r("span",{className:"media-breadcrumb-current",text:N.label})):h.append(r("button",{className:"media-breadcrumb-link",type:"button",text:N.label,onClick:()=>void Ti(N.path,t)}))});const g=r("input",{type:"file",className:"media-file-input",multiple:"multiple",accept:"image/*,video/*,.html,.svg,.pdf",hidden:!0,onChange:async N=>{const R=Array.from(N.target.files||[]);N.target.value="",R.length&&await _v(R,t)}}),b=r("div",{className:"media-toolbar"},[r("button",{className:"btn btn-nav",type:"button",title:"Back to Studio map",onClick:()=>c()},[i("chevron_left","btn-nav-icon"),r("span",{text:"Studio map"})]),r("span",{className:"spacer"}),r("button",{className:"btn",type:"button",text:"New folder",disabled:!!n.mediaBusy,onClick:()=>void Bv(t)}),r("button",{className:"btn btn-primary",type:"button",text:n.mediaBusy?"Working…":"Upload",disabled:!!n.mediaBusy,onClick:()=>g.click()}),g]),x=r("p",{className:"media-hint",text:"Click an image, video, or HTML file to preview it. Copy the public path into includes (e.g. /media/images/…). Deletes stay in GitHub/IDE."});let w;if(n.mediaLoading)w=r("p",{className:"loading-msg",text:"Loading media…"});else if(!d.length)w=r("p",{className:"empty-msg",text:"This folder is empty. Upload a file or create a subfolder."});else{const N=d.map(R=>Pv(R,t));w=r("div",{className:"media-grid",role:"list"},N)}return r("div",{className:"pane media-pane"},[r("header",{className:"media-header"},[r("h1",{className:"media-title",text:"Media"}),h,x]),b,w])}function Pv(t,e){const{el:n,materialIcon:r,resolveMediaUrl:i,state:s}=e,o=t.type==="dir",l=o?null:Zm(t.name),a=t.public_path||(o?null:Mo(t.path)),c=!o&&Gm(t.name)&&a?i(a):"";let u;if(o)u=n("span",{className:"media-thumb media-thumb--folder"},[r("folder","media-thumb-icon")]);else if(c){const g=n("img",{className:"media-thumb-img",src:c,alt:"",loading:"lazy",referrerpolicy:"no-referrer"});g.addEventListener("error",()=>{g.replaceWith(n("span",{className:"media-thumb media-thumb--file"},[r("image","media-thumb-icon")]))}),u=n("span",{className:"media-thumb media-thumb--image"},[g])}else Jm(t.name)?u=n("span",{className:"media-thumb media-thumb--file"},[r("movie","media-thumb-icon")]):Xm(t.name)?u=n("span",{className:"media-thumb media-thumb--file"},[r("html","media-thumb-icon")]):u=n("span",{className:"media-thumb media-thumb--file"},[r("draft","media-thumb-icon")]);const d=[];!o&&t.size&&d.push(Qm(t.size)),a&&d.push(a);const p=o?()=>void Ti(t.path,e):l?g=>$v(t,g.currentTarget,e):()=>void qd(a,e),h=o?`Open ${t.name}`:l?`Preview ${t.name}`:`Copy ${a}`;return n("div",{className:"media-row"+(o?" media-row--dir":""),role:"listitem"},[n("button",{className:"media-row-main"+(l?" media-row-main--preview":""),type:"button",title:h,disabled:!!s.mediaBusy,onClick:p},[u,n("span",{className:"media-row-body"},[n("span",{className:"media-row-name",text:t.name}),n("span",{className:"media-row-meta",text:d.join(" · ")||(o?"Folder":"")})])]),!o&&a?n("button",{className:"btn media-copy-btn",type:"button",text:"Copy path",title:a,disabled:!!s.mediaBusy,onClick:()=>void qd(a,e)}):null].filter(Boolean))}let yt=null,xa=null;function Dv(t,e){if(yt)return yt;const n=t("img",{className:"figure-lightbox-img",alt:""}),r=t("video",{className:"figure-lightbox-video",controls:!0,playsinline:!0}),i=t("iframe",{className:"figure-lightbox-frame",title:"Media preview"}),s=t("p",{className:"figure-lightbox-caption"});n.hidden=!0,r.hidden=!0,i.hidden=!0,s.hidden=!0,r.controls=!0;const o=t("button",{type:"button",className:"figure-lightbox-close","data-lightbox-close":"true","aria-label":"Close",onClick:a=>{a.preventDefault(),Nl()}},[e("close")]),l=t("div",{id:"figure-lightbox",className:"figure-lightbox",role:"dialog","aria-modal":"true","aria-label":"Media preview","aria-hidden":"true"},[t("div",{className:"figure-lightbox-backdrop","data-lightbox-close":"true",tabindex:"-1",onClick:()=>Nl()}),t("div",{className:"figure-lightbox-panel"},[o,n,r,i,s])]);return l.hidden=!0,document.body.append(l),document.addEventListener("keydown",a=>{!yt||yt.root.hidden||a.key==="Escape"&&(a.preventDefault(),Nl())}),yt={root:l,img:n,video:r,frame:i,caption:s,closeBtn:o},yt}function eg(t){t.img.removeAttribute("src"),t.img.alt="",t.img.hidden=!0,t.video.pause(),t.video.removeAttribute("src"),t.video.load(),t.video.hidden=!0,t.frame.removeAttribute("src"),t.frame.hidden=!0,t.caption.textContent="",t.caption.hidden=!0}function tg(t,e){t.root.hidden=!e,t.root.setAttribute("aria-hidden",String(!e)),document.documentElement.classList.toggle("figure-lightbox-open",e),document.body.classList.toggle("figure-lightbox-open",e)}function Nl(){if(!yt||yt.root.hidden)return;eg(yt),tg(yt,!1);const t=xa;if(xa=null,t&&typeof t.focus=="function")try{t.focus()}catch{}}function $v(t,e,n){const{el:r,materialIcon:i,resolveMediaUrl:s}=n,o=Zm(t.name),l=t.public_path||Mo(t.path),a=l?s(l):"";if(!o||!a)return;const c=Dv(r,i);xa=e||null,eg(c),o==="image"?(c.img.hidden=!1,c.img.referrerPolicy="no-referrer",c.img.alt=t.name||"",c.img.src=a):o==="video"?(c.video.hidden=!1,c.video.referrerPolicy="no-referrer",c.video.src=a):(c.frame.hidden=!1,c.frame.title=t.name||"HTML preview",c.frame.src=a),c.caption.textContent=t.name||"",c.caption.hidden=!t.name,tg(c,!0),c.closeBtn.focus()}async function qd(t,e){const{state:n,render:r,captureError:i,clearError:s}=e;if(t){s();try{await navigator.clipboard.writeText(t),n.status=`Copied ${t}`}catch(o){i(o),n.status=t}r()}}async function Ti(t,e){const{api:n,state:r,render:i,captureError:s,clearError:o}=e;o(),r.mediaPath=t||bt,r.mediaLoading=!0,r.mediaBusy=!1,r.status=`Loading ${r.mediaPath}…`,i();try{const l=await n.listMedia(r.mediaPath);r.mediaItems=l.items||[],r.mediaPath=l.path||r.mediaPath,r.mediaLoading=!1;const a=r.mediaItems.filter(u=>u.type==="dir").length,c=r.mediaItems.filter(u=>u.type==="file").length;r.status=`${a} folders · ${c} files`}catch(l){r.mediaItems=[],r.mediaLoading=!1,s(l)}i()}async function Bv(t){const{api:e,state:n,render:r,captureError:i,clearError:s}=t,o=window.prompt("New folder name (letters, numbers, .-_)");if(o==null)return;const l=Ov(o);if(!l){n.error="Invalid folder name",n.status="",r();return}const a=`${n.mediaPath||bt}/${l}`;s(),n.mediaBusy=!0,n.status=`Creating ${l}…`,r();try{await e.createMediaFolder({path:a,message:`studio: mkdir ${a}`}),n.mediaBusy=!1,n.status=`Created ${Mo(a)||a}`,await Ti(n.mediaPath,t)}catch(c){n.mediaBusy=!1,i(c),r()}}async function _v(t,e){const{api:n,state:r,render:i,captureError:s,clearError:o}=e;o();const l=r.mediaPath||bt;let a=0;r.mediaBusy=!0;for(const c of t){const u=Nv(c.name);if(!u){r.error=`Skipped invalid name: ${c.name}`;continue}if(c.size>Ud){r.error=`${u} exceeds ${Qm(Ud)} (GitHub Contents API soft limit in Studio)`;continue}r.status=`Uploading ${u}…`,i();try{const d=await Lv(c),p=`${l}/${u}`,h=await n.uploadMedia({path:p,content_base64:d,message:`studio: upload ${p}`});a+=1,r.status=`Uploaded ${h.public_path||Mo(p)}`}catch(d){s(d),r.mediaBusy=!1,i();return}}r.mediaBusy=!1,a&&(r.status=a===1?r.status:`Uploaded ${a} files`),await Ti(l,e)}const zv="pk_test_c291bmQtc3F1aXJyZWwtNDgzMC5jbGVyay5hY2NvdW50cy5kZXYk",Zt="/studio/",Wd="",ng={forceRedirectUrl:Zt,fallbackRedirectUrl:Zt,signInForceRedirectUrl:Zt,signInFallbackRedirectUrl:Zt,signUpForceRedirectUrl:Zt,signUpFallbackRedirectUrl:Zt};function Fv(t){const e=String(t).replace(/^pk_(test|live)_/,"");if(!e)return"";try{const n="=".repeat((4-e.length%4)%4),r=(e+n).replace(/-/g,"+").replace(/_/g,"/");return atob(r).replace(/\$$/,"").trim()}catch{return""}}function Kd(t,e={}){return new Promise((n,r)=>{const i=document.querySelector(`script[src="${t}"]`);if(i){if(i.dataset.loaded==="1")return n();i.addEventListener("load",()=>n(),{once:!0}),i.addEventListener("error",()=>r(new Error(`Failed to load ${t}`)),{once:!0});return}const s=document.createElement("script");s.src=t,s.async=!0,s.defer=!0,s.crossOrigin="anonymous";for(const[o,l]of Object.entries(e))if(o==="dataset"&&l&&typeof l=="object")for(const[a,c]of Object.entries(l))s.dataset[a]=c;else l!=null&&s.setAttribute(o,l);s.onload=()=>{s.dataset.loaded="1",n()},s.onerror=()=>r(new Error(`Failed to load ${t}`)),document.head.appendChild(s)})}async function Hv(t){if(window.Clerk&&typeof window.Clerk.load=="function"&&window.__internal_ClerkUICtor)return window.Clerk;const e="".replace(/^https?:\/\//,"").replace(/\/$/,"")||Fv(t);if(!e)throw new Error("Cannot resolve Clerk Frontend API host from publishable key");const n=`https://${e}/npm`;await Kd(`${n}/@clerk/ui@1/dist/ui.browser.js`),await Kd(`${n}/@clerk/clerk-js@6/dist/clerk.browser.js`,{dataset:{clerkPublishableKey:t}});for(let r=0;r<80;r++){if(window.Clerk&&typeof window.Clerk.load=="function"&&window.__internal_ClerkUICtor)return window.Clerk;await new Promise(s=>setTimeout(s,25))}throw new Error("Clerk / ClerkUI global missing after script load")}async function jv(){const t=await Hv(zv);return await t.load({clerkUICtor:window.__internal_ClerkUICtor,...ng}),Dg(async()=>t.session?t.session.getToken():null),t}const ot=document.getElementById("app"),m={schema:null,session:null,collection:null,items:[],file:null,sha:null,fields:{},body:"",yamlDoc:null,yamlList:null,yamlUiMode:"structured",bodyMode:"visual",lastEditorMode:"visual",baseline:null,dirty:!1,saving:!1,status:"",error:"",errorCode:"",errorDetail:"",listLoading:!1,fileLoading:!1,previewHtml:"",bodyEditor:null,insertMenuOpen:!1,aiProofHint:"",aiProofBusy:!1,aiProofSelection:null,navOpenGroups:new Set,navMenuOpen:!1,themeMenuOpen:!1,listQueryByCollection:Object.create(null),listSortByCollection:Object.create(null),listPageSizeByCollection:Object.create(null),listPageByCollection:Object.create(null),listTagByCollection:Object.create(null),navCountByCollection:Object.create(null),treeCacheByCollection:Object.create(null),treePrefetchGen:0,frontMatterOpen:null,mediaOpen:!1,mediaPath:"content/media",mediaItems:[],mediaLoading:!1,mediaBusy:!1},Vv={figure:"image",cutIn:"transition_push",youtube:"smart_display",youtubeShort:"mobile_screen_share",video:"videocam",plotly:"analytics",xcite:"format_quote",cite:"bookmark",articleNote:"sticky_note_2",poem:"history_edu"},Sa={Writing:"edit_note",References:"menu_book",Portfolio:"work",Media:"photo_library",Pages:"description","CV Summary":"badge",Presentation:"campaign",Profile:"person"},Uv=[{label:"Default",value:""},{label:"Primary",value:"var(--primary)"},{label:"Secondary",value:"var(--secondary)"},{label:"Tertiary",value:"var(--tertiary)"},{label:"Muted",value:"var(--on-surface-variant)"},{label:"Error",value:"var(--error)"}],qv={Writing:"Articles and Portuguese rascunhos",References:"Source cards and bibliography entries",Portfolio:"Products, projects, and CV jobs",Media:"Upload and browse content/media — cite /media/… in includes",Pages:"Listing page headers and furniture copy","CV Summary":"Public and PDF CV summary variants",Presentation:"Home catch phrase and CV side notes",Profile:"Contacts, education, languages, and skills"};function Ai(t){return String(t||"").split("/").filter(Boolean).join(" | ")}function rg(t){return qv[t]||`Browse ${t} collections`}function ig(t){return"nav-group-"+String(t).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")}function sg(t){const e=og(t.description);if(e)return e;const n=Ai(t.path)||t.name;return t.type==="file"?`Open ${t.label} | ${n}`:`List entries in ${t.label} | ${n}`}function og(t){let e=String(t||"").trim();if(!e)return"";const n=[/\s*The filename uses Key as YYYY-MM-DD-key[^.]*\./gi,/\s*Also the filename stem:[^.]*\./gi,/\s*Also the filename:[^.]*\./gi,/\s*Must match the YYYY-MM-DD in the filename[^.]*\./gi,/\s*;?\s*must match the YYYY-MM-DD in the filename\./gi,/\s*The Updated date is read from Git, never set here\./gi,/\s*ASCII kebab-case\./gi,/\s*\(44 characters total for the key segment is a good ceiling\)\.?/gi,/Metadata-first forms[^.]*\./gi,/TipTap with Liquid blocks[^.]*\./gi,/preview via content-runtime contract\.?/gi,/Paste Liquid \{%\s*include\s*%\} markers[^.]*\./gi,/Do not use rich-text:[^.]*\./gi,/its Editor mode rewrites URLs inside includes\.?/gi,/Markdown source \(code editor\)\.?/gi];for(const r of n)e=e.replace(r,"");return e=e.replace(/\s{2,}/g," ").replace(/\s+\./g,".").trim(),/filename|YYYY-MM-DD-key|content-runtime|autolink|TipTap/i.test(e)?"":e}function Yd(t){return og(t==null?void 0:t.description)}function zn(t){var i,s;const e=String((t==null?void 0:t.message)||t||"Request failed"),n=[];t!=null&&t.status&&n.push(`HTTP ${t.status}`);const r=(i=t==null?void 0:t.data)==null?void 0:i.detail;if(r)n.push(String(r));else if(t!=null&&t.data&&typeof t.data=="object")try{n.push(JSON.stringify(t.data,null,2))}catch{}else t!=null&&t.stack&&!String(t.stack).includes(e)&&n.push(String(t.stack).split(`
|
|
269
269
|
`).slice(0,6).join(`
|
|
270
270
|
`));m.error=e,m.errorCode=String((t==null?void 0:t.code)||((s=t==null?void 0:t.data)==null?void 0:s.error)||""),m.errorDetail=n.join(`
|
|
271
271
|
`).trim(),m.status=""}function zt(){m.error="",m.errorCode="",m.errorDetail=""}function Ol(){var t;return m.mediaOpen?"Media":(t=m.collection)!=null&&t.label?m.collection.label:"Home"}function yc(){m.navMenuOpen=!1}function bc(){var t,e;Ht(),m.collection=null,m.file=null,m.baseline=null,m.items=[],m.yamlDoc=null,m.yamlList=null,m.listLoading=!1,m.fileLoading=!1,m.dirty=!1,m.insertMenuOpen=!1,m.mediaOpen=!1,m.mediaItems=[],m.mediaLoading=!1,m.mediaBusy=!1,yc(),zt(),m.status=((t=m.session)==null?void 0:t.email)||((e=m.session)==null?void 0:e.userId)||"",oe(),dg()}function lg(){return{api:kt,state:m,el:k,materialIcon:Ve,resolveMediaUrl:fg,render:()=>oe(),captureError:zn,clearError:zt,goHome:bc}}async function ag(t){Ht(),m.collection=null,m.file=null,m.baseline=null,m.items=[],m.insertMenuOpen=!1,m.dirty=!1,m.mediaOpen=!0,m.navOpenGroups.add("Media"),yc();const e=Ev(m.schema);await Ti(e,lg())}function Ve(t,e=""){return k("span",{className:"material-symbols-outlined"+(e?` ${e}`:""),text:t,"aria-hidden":"true"})}function To({size:t=40,label:e=""}={}){return k("span",{className:"studio-mark",...e?{role:"img","aria-label":e}:{"aria-hidden":"true"},html:`<svg class="studio-mark-svg" viewBox="0 0 32 32" width="${t}" height="${t}" focusable="false"><polygon class="studio-mark-primary" points="16,1 24,5 13,14 2,17 2,9"/><polygon class="studio-mark-secondary" points="24,5 30,9 30,23 22,28 19,18 13,14"/><polygon class="studio-mark-tertiary" points="2,17 13,14 19,18 22,28 16,31 2,23"/><polygon class="studio-mark-frame" points="16,1 30,9 30,23 16,31 2,23 2,9"/></svg>`})}function Gd(t){const e=t.title||t.name||"Entry",n=Ai(t.path);return n?`Open ${e} | ${n}`:`Open ${e}`}function Wv(){var e;const t=(e=m.collection)==null?void 0:e.name;return t&&m.listQueryByCollection[t]||""}function Kv(){var n;const t=(n=m.collection)==null?void 0:n.name;if(!t)return to;if(m.listSortByCollection[t])return m.listSortByCollection[t];const e=hv(t,to);return m.listSortByCollection[t]=e,e}function Yv(t){var n;const e=(n=m.collection)==null?void 0:n.name;e&&(m.listSortByCollection[e]=t,mv(e,t),Ao())}function Gv(){var n;const t=(n=m.collection)==null?void 0:n.name;if(!t)return ro;if(m.listPageSizeByCollection[t])return m.listPageSizeByCollection[t];const e=gv(t,ro);return m.listPageSizeByCollection[t]=e,e}function Jv(t){var n;const e=(n=m.collection)==null?void 0:n.name;e&&(m.listPageSizeByCollection[e]=t,yv(e,t),Ao())}function Jd(){var e;const t=(e=m.collection)==null?void 0:e.name;return t?Math.max(1,Number(m.listPageByCollection[t])||1):1}function Ll(t){var n;const e=(n=m.collection)==null?void 0:n.name;e&&(m.listPageByCollection[e]=Math.max(1,Number(t)||1))}function Ao(){var e;const t=(e=m.collection)==null?void 0:e.name;t&&(m.listPageByCollection[t]=1)}function Xv(){var e;const t=(e=m.collection)==null?void 0:e.name;return t&&m.listTagByCollection[t]||""}function Xd(t){var n;const e=(n=m.collection)==null?void 0:n.name;e&&(m.listTagByCollection[e]=String(t||""),Ao())}function cg(t,e){t!=null&&t.name&&(m.navCountByCollection[t.name]=Math.max(0,Number(e)||0))}function ug(t,e){if(!(t!=null&&t.name))return;const n=Array.isArray(e)?e:[];m.treeCacheByCollection[t.name]={items:n},cg(t,n.length)}function Zv(t){if(!(t!=null&&t.name))return null;const e=m.treeCacheByCollection[t.name];return e?e.items:null}function Qv(t){if(!t){m.treeCacheByCollection=Object.create(null);return}delete m.treeCacheByCollection[t]}function eM(t=m.schema){return((t==null?void 0:t.collections)||[]).filter(e=>e&&e.type!=="file"&&e.path)}function tM(t){return[...t].sort((e,n)=>{const r=e.group==="Writing"?0:1,i=n.group==="Writing"?0:1;return r!==i?r-i:String(e.label||e.name).localeCompare(String(n.label||n.name))})}function dg(){const t=++m.treePrefetchGen,e=()=>{nM(t)};typeof requestIdleCallback=="function"?requestIdleCallback(e,{timeout:2500}):setTimeout(e,400)}async function nM(t){const e=tM(eM()).filter(n=>!m.treeCacheByCollection[n.name]);for(const n of e){if(t!==m.treePrefetchGen)return;try{const r=await kt.tree(n.path);if(t!==m.treePrefetchGen)return;m.treeCacheByCollection[n.name]||(ug(n,r.items||[]),m.file||oe())}catch{}await new Promise(r=>setTimeout(r,60))}}function fg(t){const e=String(t||"").trim();return e?/^https?:\/\//i.test(e)?e:e.startsWith("/media/")?`${Wd.replace(/\/$/,"")}${e}`:e.startsWith("media/")?`${Wd.replace(/\/$/,"")}/${e}`:(e.startsWith("/"),e):""}function Zd(){return k("span",{className:"ledger-thumb placeholder",title:"No thumbnail","aria-label":"No thumbnail"},[k("span",{className:"material-symbols-outlined",text:"web_asset_off","aria-hidden":"true"})])}function Qd(t){const e=fg(t.thumbnail);if(!e)return Zd();const n=k("img",{className:"ledger-thumb",src:e,alt:"",loading:"lazy",referrerpolicy:"no-referrer"});return n.addEventListener("error",()=>{n.replaceWith(Zd())}),n}function ve(t,e=document){return e.querySelector(t)}function k(t,e={},n=[]){const r=document.createElement(t);for(const[i,s]of Object.entries(e))i==="className"?r.className=s:i==="text"?r.textContent=s:i==="html"?r.innerHTML=s:i==="htmlFor"?r.htmlFor=s:i.startsWith("on")&&typeof s=="function"?r.addEventListener(i.slice(2).toLowerCase(),s):i==="checked"||i==="selected"||i==="disabled"||i==="multiple"||i==="open"?r[i]=!!s:s===!1||s==null||(s===!0?r.setAttribute(i,""):r.setAttribute(i,s));for(const i of[].concat(n))i==null||i===!1||r.append(i.nodeType?i:document.createTextNode(String(i)));return r}const pg="studio-theme",io={light:"light_mode",dark:"dark_mode",system:"routine"};function di(){const t=localStorage.getItem(pg);return t==="light"||t==="dark"||t==="system"?t:"system"}function rM(){const t=di();return t==="dark"?"dark":t==="light"?"light":window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}function iM(t){localStorage.setItem(pg,t),wa(),fi()}function wa(){document.documentElement.setAttribute("data-theme",rM())}function sM(){wa();const t=window.matchMedia("(prefers-color-scheme: dark)");typeof t.addEventListener=="function"&&t.addEventListener("change",()=>{di()==="system"&&wa()})}function fi(){const t=di(),e=document.querySelector("[data-studio-theme-icon]");e&&(e.textContent=io[t]||io.system);for(const i of document.querySelectorAll("[data-theme-choice]")){const o=i.getAttribute("data-theme-choice")===t;i.setAttribute("aria-checked",o?"true":"false"),i.classList.toggle("is-selected",o)}const n=document.querySelector("[data-studio-action='theme-menu']"),r=document.getElementById("studio-theme-menu");n&&r&&(n.setAttribute("aria-expanded",m.themeMenuOpen?"true":"false"),r.hidden=!m.themeMenuOpen)}function oM(){const t=[{id:"light",label:"Light",icon:"light_mode"},{id:"dark",label:"Dark",icon:"dark_mode"},{id:"system",label:"System",icon:"routine"}],e=k("div",{className:"studio-theme-menu-panel",id:"studio-theme-menu",role:"menu","aria-label":"Choose color theme",hidden:!m.themeMenuOpen},t.map(r=>k("button",{className:"studio-theme-choice",type:"button",role:"menuitemradio","data-theme-choice":r.id,"aria-checked":di()===r.id?"true":"false",onClick:i=>{i.stopPropagation(),iM(r.id),m.themeMenuOpen=!1,fi();const s=ve("#preview-frame");s&&bg(s)}},[Ve(r.icon),k("span",{text:r.label})]))),n=k("button",{className:"btn btn-icon",type:"button",title:"Theme","aria-label":"Theme","data-studio-action":"theme-menu","aria-haspopup":"true","aria-expanded":m.themeMenuOpen?"true":"false","aria-controls":"studio-theme-menu",onClick:r=>{r.stopPropagation(),m.themeMenuOpen=!m.themeMenuOpen,fi()}},[k("span",{className:"material-symbols-outlined","data-studio-theme-icon":"true",text:io[di()]||io.system,"aria-hidden":"true"})]);return k("div",{className:"studio-theme-menu"},[n,e])}function lM(){var n,r;const t=m.saving?"Saving…":m.dirty?"Save draft":"Saved",e=m.saving?"progress_activity":m.dirty?"save":"check";return k("div",{className:"studio-toolbar studio-icon-bar"},[k("span",{className:"status-pill"+(m.error?" error":""),text:m.error?"Error":m.status||((n=m.session)==null?void 0:n.email)||((r=m.session)==null?void 0:r.userId)||"",title:m.error||m.errorDetail||m.status||""}),k("span",{className:"spacer"}),oM(),k("button",{className:"btn btn-icon",type:"button",title:"Revert all edits to the last loaded or saved version","aria-label":"Discard edits","data-studio-action":"discard",disabled:!m.file||!m.dirty||!m.baseline,onClick:()=>XM()},[Ve("undo")]),k("button",{className:"btn btn-icon btn-primary",type:"button",title:m.saving?"Saving this draft":m.dirty?"Commit this draft":"No edits to commit yet","aria-label":t,"data-studio-action":"save",disabled:m.saving||!m.file||!m.dirty,onClick:()=>ZM()},[k("span",{className:"material-symbols-outlined"+(m.saving?" studio-icon-spin":""),text:e,"aria-hidden":"true"})])])}function hg(t){var r,i;if(!t||t.dev||!t.user)return"";const e=(r=t.user.primaryEmailAddress)==null?void 0:r.emailAddress;return e||((i=(t.user.emailAddresses||[])[0])==null?void 0:i.emailAddress)||""}function pi(t){if(t&&!t.dev&&t.user){aM(t,m.error||"Studio API session failed while you are signed in.");return}ot.innerHTML="";const e=k("div",{className:"auth-gate"},[k("div",{className:"studio-brand"},[To({size:32,label:"Studio"}),k("strong",{text:"Studio"})]),k("h1",{text:"Sign in to edit"}),k("p",{text:"Studio is for site admins only. Anyone may register; access is granted after review."}),k("div",{id:"clerk-sign-in"})]);ot.append(e),t&&!t.dev?t.mountSignIn(ve("#clerk-sign-in"),{...ng}):ve("#clerk-sign-in").append(k("p",{className:"status-pill",text:"No VITE_CLERK_PUBLISHABLE_KEY — using API bypass if enabled."}),k("button",{className:"btn btn-primary",text:"Continue",onClick:()=>ls(t)}))}function aM(t,e){ot.innerHTML="";const n=k("div",{className:"auth-gate"},[k("div",{className:"studio-brand"},[To({size:32,label:"Studio"}),k("strong",{text:"Studio"})]),k("h1",{text:"Studio API unavailable"}),k("p",{className:"status-pill error",text:e}),k("p",{text:"You are signed in with Clerk, but /api/studio/session did not succeed. Local jekyll serve has no Pages Functions — use a Pages preview, wrangler pages dev, or STUDIO_DEV_BYPASS against a running Function."}),k("button",{className:"btn",type:"button",text:"Sign out",onClick:async()=>{if(t&&!t.dev&&t.signOut){await t.signOut({redirectUrl:Zt});return}pi(t)}})]);ot.append(n)}function cM(t,e){const n=e||hg(t)||"the address you used to register";ot.innerHTML="";const r=k("p",{className:"pending-copy"});r.append(document.createTextNode("Thank you for your registration. Your profile is being transferred to the site administration to be reviewed as a potential contributor. You will be contacted via "));const i=document.createElement("strong");i.textContent=n,r.append(i),r.append(document.createTextNode("."));const s=k("div",{className:"auth-gate auth-gate--pending"},[k("div",{className:"studio-brand"},[To({size:32,label:"Studio"}),k("strong",{text:"Studio"})]),k("h1",{text:"Registration received"}),r,k("p",{className:"pending-signoff",text:"Have a nice one! ✍️"}),k("button",{className:"btn",type:"button",text:"Sign out",onClick:async()=>{if(t&&!t.dev&&t.signOut){await t.signOut({redirectUrl:Zt});return}pi(t)}})]);ot.append(s)}const uM=["Writing","References","Portfolio","Pages","CV Summary","Presentation","Profile"];function mg(t){const e=new Map;for(const r of t.collections)e.has(r.group)||e.set(r.group,[]),e.get(r.group).push(r);const n=new Map;for(const r of uM)e.has(r)&&n.set(r,e.get(r));for(const[r,i]of e)n.has(r)||n.set(r,i);return n}function ef(){const t="Media",e=m.navOpenGroups.has(t),n=k("div",{className:"studio-nav-group-items",id:ig(t),role:"region","aria-label":t});e||(n.hidden=!0),n.append(k("button",{className:"nav-item",type:"button",text:"Library",title:"Browse and upload under content/media","aria-current":m.mediaOpen?"page":null,onClick:()=>ag()}));const r=k("button",{className:"studio-nav-group-toggle",type:"button",title:rg(t),"aria-expanded":e?"true":"false","aria-controls":n.id,onClick:()=>{m.navOpenGroups.has(t)?m.navOpenGroups.delete(t):m.navOpenGroups.add(t),oe()}},[k("span",{className:"material-symbols-outlined",text:e?"expand_more":"chevron_right","aria-hidden":"true"}),k("span",{className:"nav-group-label",text:t})]);return k("div",{className:"studio-nav-group"},[r,n])}function dM(){if(!m.error||!m.file&&!m.mediaOpen)return null;const t=[];if(m.errorCode==="conflict"&&m.file){const e=m.file;t.push(k("button",{className:"btn",type:"button",text:"Reload from GitHub",title:"Replace this screen with the file currently on GitHub",onClick:()=>xc(e)}))}return t.push(k("button",{className:"btn",type:"button",text:"Dismiss",onClick:()=>{zt(),oe()}})),k("div",{className:"studio-error-banner",role:"alert"},[k("p",{className:"studio-error-message",text:m.error}),k("div",{className:"studio-error-actions"},t)])}function oe(){var a;ot.innerHTML="";const t=mg(m.schema),e=!!m.navMenuOpen,n=k("button",{className:"studio-brand studio-brand-home",type:"button",title:"Studio home","aria-current":!m.collection&&!m.mediaOpen?"page":null,onClick:()=>bc()},[To({size:40}),k("span",{className:"studio-brand-copy"},[k("span",{className:"studio-brand-name",text:"Studio"})])]),r=k("button",{className:"studio-nav-menu-toggle",type:"button",title:e?"Close collections menu":"Open collections menu","aria-label":e?`Close menu (${Ol()})`:`Open menu (${Ol()})`,"aria-expanded":e?"true":"false","aria-controls":"studio-nav-panel",onClick:()=>{m.navMenuOpen=!m.navMenuOpen,oe()}},[k("span",{className:"studio-nav-menu-label sr-only",text:Ol()}),k("span",{className:"material-symbols-outlined",text:e?"close":"menu","aria-hidden":"true"})]),i=k("div",{className:"studio-nav-panel",id:"studio-nav-panel"});for(const[c,u]of t){const d=m.navOpenGroups.has(c),p=k("div",{className:"studio-nav-group-items",id:ig(c),role:"region","aria-label":c});d||(p.hidden=!0);for(const g of u){const b=m.navCountByCollection[g.name],x=[k("span",{className:"nav-item-label",text:g.label})];b!=null&&x.push(k("span",{className:"nav-item-count",text:String(b)})),p.append(k("button",{className:"nav-item",type:"button",title:sg(g),"aria-current":((a=m.collection)==null?void 0:a.name)===g.name?"page":null,onClick:()=>xg(g)},x))}const h=k("button",{className:"studio-nav-group-toggle",type:"button",title:rg(c),"aria-expanded":d?"true":"false","aria-controls":p.id,onClick:()=>{m.navOpenGroups.has(c)?m.navOpenGroups.delete(c):m.navOpenGroups.add(c),oe()}},[k("span",{className:"material-symbols-outlined",text:d?"expand_more":"chevron_right","aria-hidden":"true"}),k("span",{className:"nav-group-label",text:c})]);i.append(k("div",{className:"studio-nav-group"},[h,p])),(c==="Portfolio"||c==="References"&&!t.has("Portfolio"))&&i.append(ef())}!t.has("Portfolio")&&!t.has("References")&&i.append(ef());const s=k("nav",{className:"studio-nav"+(e?" is-open":""),"aria-label":"Collections"},[k("div",{className:"studio-nav-bar"},[n,r]),i]),o=lM(),l=k("div",{className:"studio-main"},[o,dM(),fM(),k("div",{className:"studio-body"+(m.file?"":" list-only"),id:"studio-body"})]);ot.append(k("div",{className:"studio-shell"},[s,l])),Nt(),fi(),window.__studioMenuDismissBound||(window.__studioMenuDismissBound=!0,document.addEventListener("click",()=>{m.themeMenuOpen&&(m.themeMenuOpen=!1,fi())}))}function fM(){var e,n;const t=[k("span",{className:"studio-crumb",text:"Studio"})];if(m.mediaOpen&&!m.collection)t.push(k("span",{className:"studio-crumb-sep","aria-hidden":"true",text:"/"}),k("span",{className:"studio-crumb is-current",text:"Media"}));else if(m.collection){const r=m.collection.group||"Content",i=m.collection.label||m.collection.name;if(t.push(k("span",{className:"studio-crumb-sep","aria-hidden":"true",text:"/"}),k("span",{className:"studio-crumb",text:r}),k("span",{className:"studio-crumb-sep","aria-hidden":"true",text:"/"}),k("span",{className:"studio-crumb"+(m.file?"":" is-current"),text:i})),m.file){const s=((e=m.fields)==null?void 0:e.title)||((n=m.fields)==null?void 0:n.key)||String(m.file).split("/").pop()||"Entry";t.push(k("span",{className:"studio-crumb-sep","aria-hidden":"true",text:"/"}),k("span",{className:"studio-crumb is-current",text:s}))}}else t.push(k("span",{className:"studio-crumb-sep","aria-hidden":"true",text:"/"}),k("span",{className:"studio-crumb is-current",text:"Map"}));return k("nav",{className:"studio-breadcrumb","aria-label":"Location"},t)}function Fe(){m.dirty=!0,va(),DM()}function kc(){var t;return!m.file||fr()||m.aiProofBusy?!1:!!String(((t=m.fields)==null?void 0:t.language)||"").trim()}function Ca(){const t=m.aiProofBusy,e=kc()&&!t;for(const n of["correct","refine"]){const r=document.querySelector(`[data-studio-action='${n}']`);if(!r)continue;r.disabled=!e;const i=r.querySelector(".editor-ai-proof-label");i&&(t?i.textContent="Working…":i.textContent=n==="refine"?"Refine":"Correct")}}function Zr(){m.insertMenuOpen=!1;const t=ve("#insert-menu");t&&(t.hidden=!0);for(const e of document.querySelectorAll(".editor-insert-btn[aria-haspopup='menu']"))e.setAttribute("aria-expanded","false")}function ss(t){m.aiProofHint=t;const e=ve("#ai-proof-hint");e&&(e.textContent=t,e.hidden=!t),clearTimeout(m._aiProofHintTimer),t&&(m._aiProofHintTimer=setTimeout(()=>{m.aiProofHint="";const n=ve("#ai-proof-hint");n&&(n.textContent="",n.hidden=!0)},3200))}function gg(){var t;if(m.bodyMode==="source"){const e=ve("#body-source");if(!e)return null;const n=e.selectionStart,r=e.selectionEnd;if(!Number.isInteger(n)||!Number.isInteger(r)||n===r)return null;cn();const i=m.body||"";return{kind:"source",start:n,end:r,text:i.slice(n,r)}}if(m.bodyMode==="visual"&&((t=m.bodyEditor)!=null&&t.editor)){const e=m.bodyEditor.editor,{from:n,to:r,empty:i}=e.state.selection;if(i||n===r)return null;const s=e.state.doc.textBetween(n,r,`
|
data/studio/index.html
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
rel="stylesheet"
|
|
19
19
|
href="https://cdn.jsdelivr.net/gh/lipis/flag-icons@7.2.3/css/flag-icons.min.css"
|
|
20
20
|
/>
|
|
21
|
-
<script type="module" crossorigin src="/studio/assets/index-
|
|
21
|
+
<script type="module" crossorigin src="/studio/assets/index-CaMlZpH1.js"></script>
|
|
22
22
|
<link rel="stylesheet" crossorigin href="/studio/assets/index-B2os0c1O.css">
|
|
23
23
|
</head>
|
|
24
24
|
<body>
|
data/studio-app/vite.config.js
CHANGED
|
@@ -1,10 +1,77 @@
|
|
|
1
|
-
import { defineConfig } from "vite";
|
|
1
|
+
import { defineConfig, loadEnv } from "vite";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import fs from "node:fs";
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
/** Decode Frontend API host from a Clerk publishable key (`pk_test_` / `pk_live_`). */
|
|
6
|
+
function frontendApiHostFromKey(key) {
|
|
7
|
+
const raw = String(key || "").replace(/^pk_(test|live)_/, "");
|
|
8
|
+
if (!raw) return "";
|
|
9
|
+
try {
|
|
10
|
+
const pad = "=".repeat((4 - (raw.length % 4)) % 4);
|
|
11
|
+
const b64 = (raw + pad).replace(/-/g, "+").replace(/_/g, "/");
|
|
12
|
+
return Buffer.from(b64, "base64").toString("utf8").replace(/\$$/, "").trim();
|
|
13
|
+
} catch {
|
|
14
|
+
return "";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function rejectExampleClerkHost(mode) {
|
|
19
|
+
return {
|
|
20
|
+
name: "reject-example-clerk-host",
|
|
21
|
+
configResolved() {
|
|
22
|
+
const env = loadEnv(mode, process.cwd(), "");
|
|
23
|
+
const key = env.VITE_CLERK_PUBLISHABLE_KEY || process.env.VITE_CLERK_PUBLISHABLE_KEY || "";
|
|
24
|
+
const host = frontendApiHostFromKey(key);
|
|
25
|
+
if (!key) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
"Studio production build requires VITE_CLERK_PUBLISHABLE_KEY (see studio-app/.env.local).",
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
if (!host || host === "clerk.example.com" || host.endsWith(".example.com")) {
|
|
31
|
+
throw new Error(
|
|
32
|
+
`Refusing to bake placeholder Clerk host "${host || "(empty)"}" into studio/. ` +
|
|
33
|
+
"Set VITE_CLERK_PUBLISHABLE_KEY to the real instance publishable key.",
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
writeBundle(_options, bundle) {
|
|
38
|
+
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
39
|
+
if (!fileName.endsWith(".js") || typeof chunk.code !== "string") continue;
|
|
40
|
+
if (
|
|
41
|
+
chunk.code.includes("clerk.example.com") ||
|
|
42
|
+
chunk.code.includes("pk_test_Y2xlcmsuZXhhbXBsZS5jb20k")
|
|
43
|
+
) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
`Studio bundle ${fileName} embeds clerk.example.com — rebuild with the real VITE_CLERK_PUBLISHABLE_KEY.`,
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
closeBundle() {
|
|
51
|
+
// emptyOutDir is false so schema.yml survives; drop stale hashed assets.
|
|
52
|
+
const studioDir = path.resolve(__dirname, "../studio");
|
|
53
|
+
const htmlPath = path.join(studioDir, "index.html");
|
|
54
|
+
if (!fs.existsSync(htmlPath)) return;
|
|
55
|
+
const html = fs.readFileSync(htmlPath, "utf8");
|
|
56
|
+
const keep = new Set(
|
|
57
|
+
[...html.matchAll(/\/studio\/assets\/([^"']+)/g)].map((m) => m[1]),
|
|
58
|
+
);
|
|
59
|
+
const assetsDir = path.join(studioDir, "assets");
|
|
60
|
+
if (!fs.existsSync(assetsDir)) return;
|
|
61
|
+
for (const name of fs.readdirSync(assetsDir)) {
|
|
62
|
+
if (!/^index-.*\.(js|css)$/.test(name)) continue;
|
|
63
|
+
if (keep.has(name)) continue;
|
|
64
|
+
fs.unlinkSync(path.join(assetsDir, name));
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export default defineConfig(({ mode }) => ({
|
|
5
71
|
root: ".",
|
|
6
72
|
base: "/studio/",
|
|
7
73
|
publicDir: false,
|
|
74
|
+
plugins: [rejectExampleClerkHost(mode)],
|
|
8
75
|
build: {
|
|
9
76
|
outDir: path.resolve(__dirname, "../studio"),
|
|
10
77
|
emptyOutDir: false,
|
|
@@ -22,4 +89,4 @@ export default defineConfig({
|
|
|
22
89
|
},
|
|
23
90
|
},
|
|
24
91
|
},
|
|
25
|
-
});
|
|
92
|
+
}));
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pandorga
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.3.
|
|
4
|
+
version: 1.3.11
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- The Pandorga contributors
|
|
@@ -450,7 +450,7 @@ files:
|
|
|
450
450
|
- studio-app/src/styles/studio.css
|
|
451
451
|
- studio-app/vite.config.js
|
|
452
452
|
- studio/assets/index-B2os0c1O.css
|
|
453
|
-
- studio/assets/index-
|
|
453
|
+
- studio/assets/index-CaMlZpH1.js
|
|
454
454
|
- studio/index.html
|
|
455
455
|
- studio/schema.yml
|
|
456
456
|
- templates/articles/README.md
|