diff --git a/public/cat/wag.gif b/public/cat/wag.gif new file mode 100644 index 0000000..d063241 Binary files /dev/null and b/public/cat/wag.gif differ diff --git a/public/cat/wag.webp b/public/cat/wag.webp new file mode 100644 index 0000000..2bb35f7 Binary files /dev/null and b/public/cat/wag.webp differ diff --git a/public/heart/wink.webp b/public/heart/wink.webp new file mode 100644 index 0000000..67ce4a0 Binary files /dev/null and b/public/heart/wink.webp differ diff --git a/vite.config.js b/vite.config.js index 42c4f6f..3fe7587 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,17 +1,21 @@ // fills in index.html from whatever is in public/ -// anything rendered from gen/ gets one tile with webp + gif links, older hand-made files get a tile each -import{readdirSync as rd,readFileSync as rf,existsSync as ex}from'fs' +// one tile per name: shows the .webp (or the .gif if that's all there is) and links every format +// tile images get ?v= so browsers drop old copies when a file changes, links stay clean for hotlinking +import{readdirSync as rd,readFileSync as rf}from'fs' +import{createHash}from'crypto' +const hidden=['cat/tail.gif'] // same drawing as cat/wag.gif, kept so old links still work const walk=d=>rd(d,{withFileTypes:true}).flatMap(e=>e.isDirectory()?walk(`${d}/${e.name}`):`${d}/${e.name}`) -const dims=f=>{const b=rf(f);return f.endsWith('.gif')?[b.readUInt16LE(6),b.readUInt16LE(8)]:[b.readUIntLE(24,3)+1,b.readUIntLE(27,3)+1]} +const dims=(b,x)=>x=='gif'?[b.readUInt16LE(6),b.readUInt16LE(8)]:[b.readUIntLE(24,3)+1,b.readUIntLE(27,3)+1] const gallery=()=>{ - const seen=new Set - return walk('public').filter(f=>/\.(webp|gif)$/.test(f)).sort().map(f=>{ - const id=f.slice(7).replace(/\.\w+$/,''),g=ex(`gen/${id}.js`) - if(g&&seen.has(id))return'' - seen.add(id) - const src=g?`/${id}.webp`:f.slice(6),[w,h]=dims('public'+src) - const links=(g?['webp','gif']:[f.split('.').pop()]).map(x=>`${x}`).join(' ') - return`
${id.replace('/',' ')}
${links}
` - }).filter(Boolean).join('\n') + const g={} + for(const f of walk('public').filter(f=>/\.(webp|gif)$/.test(f)).sort()){ + const p=f.slice(7),x=p.split('.').pop() + if(!hidden.includes(p))(g[p.slice(0,-x.length-1)]??={})[x]=f + } + return Object.entries(g).map(([id,fm])=>{ + const x=fm.webp?'webp':'gif',b=rf(fm[x]),[w,h]=dims(b,x),v=createHash('md5').update(b).digest('hex').slice(0,8) + const links=['webp','gif'].filter(k=>fm[k]).map(k=>`${k}`).join(' ') + return`
${id.replace('/',' ')}
${links}
` + }).join('\n') } export default{plugins:[{name:'gallery',transformIndexHtml:h=>h.replace('',gallery())}]}