Changeset f79a471 in Klonkt
- Timestamp:
- 06/28/2026 04:32:37 PM (2 months ago)
- Branches:
- main
- Children:
- 74c5abc
- Parents:
- 1ff0043
- git-author:
- Robin Genis <roboburr@…> (06/28/2026 04:31:09 PM)
- git-committer:
- Robin Genis <roboburr@…> (06/28/2026 04:32:37 PM)
- Location:
- src
- Files:
-
- 1 added
- 4 edited
-
middleware/render.js (modified) (1 diff)
-
server.js (modified) (2 diffs)
-
services/ThumbnailService.js (added)
-
views/partials/post-card.ejs (modified) (1 diff)
-
views/partials/post-tile.ejs (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/middleware/render.js
r1ff0043 rf79a471 160 160 formatDate, 161 161 formatDateTime, 162 // Rewrite a local /media/<file> cover to its on-demand downscaled thumbnail 163 // (crisp grid/list images). External URLs + already-thumb URLs pass through. 164 thumb: (url, w) => (typeof url === 'string' && url.startsWith('/media/') && !url.startsWith('/media/thumb/')) 165 ? `/media/thumb/${w || 480}/${url.slice(7)}` 166 : url, 162 167 pageTitle: data.pageTitle || (data.site && data.site.title) || 'Klonkt', 163 168 appVersion: APP_VERSION, -
src/server.js
r1ff0043 rf79a471 20 20 import { SqliteSessionStore } from './services/SqliteSessionStore.js'; 21 21 import { ensurePrimarySite } from './services/ensurePrimarySite.js'; 22 import { getThumbnail, THUMB_SIZES } from './services/ThumbnailService.js'; 22 23 import { resolveSite, loadAudioTracks, loadTheme } from './middleware/site.js'; 23 24 import { isViewer } from './middleware/auth.js'; … … 213 214 214 215 app.use('/assets', express.static(path.join(__dirname, 'assets'), { maxAge: isDev ? 0 : '1y' })); 216 217 // On-demand cover thumbnails: /media/thumb/<w>/<path> → a small lanczos-downscaled WebP 218 // (cached on disk), so the browser doesn't jaggily shrink a high-res cover for the grid/ 219 // list. Mounted BEFORE the /media static so it catches the thumb path first. 220 app.get('/media/thumb/:w/*', async (req, res) => { 221 const w = parseInt(req.params.w, 10); 222 const rel = req.params[0] || ''; 223 if (!THUMB_SIZES.has(w)) return res.status(400).end(); 224 let file = null; 225 try { file = await getThumbnail(rel, w); } catch { /* fall through to original */ } 226 if (!file) { 227 // Generation unavailable/failed → serve the original instead of 404'ing. 228 return res.redirect(302, '/media/' + rel.split('/').map(encodeURIComponent).join('/')); 229 } 230 res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin'); 231 res.setHeader('Cache-Control', isDev ? 'no-cache' : 'public, max-age=31536000, immutable'); 232 res.type('webp'); 233 res.sendFile(file); 234 }); 235 215 236 app.use('/media', express.static(process.env.MEDIA_PATH || './storage/media', { 216 237 // Public media (post covers, avatars) must be cross-origin embeddable by other -
src/views/partials/post-card.ejs
r1ff0043 rf79a471 49 49 <% if (_ext) { %>target="_blank" rel="noopener"<% } else { %>hx-get="<%= _href %>?partial=1" hx-target="#pcms-main" hx-swap="innerHTML" hx-push-url="<%= _href %>" hx-indicator="#pcms-loading"<% } %> 50 50 aria-label="<%= post.title || '(zonder titel)' %>" tabindex="-1"> 51 <img src="<%= post.cover_image_url%>" alt="" loading="lazy" decoding="async">51 <img src="<%= thumb(post.cover_image_url, 320) %>" alt="" loading="lazy" decoding="async"> 52 52 <% if (post.nsfw) { %><span class="nsfw-veil"><span class="nsfw-veil-label">🔞 <%= post.content_warning || t('post.nsfw_warning') %></span><span class="nsfw-veil-btn"><%= t('post.nsfw_show') %></span></span><% } %> 53 53 </a> -
src/views/partials/post-tile.ejs
r1ff0043 rf79a471 19 19 <% if (_ext) { %>target="_blank" rel="noopener"<% } else { %>hx-get="<%= _href %>?partial=1" hx-target="#pcms-main" hx-swap="innerHTML" hx-push-url="<%= _href %>" hx-indicator="#pcms-loading"<% } %>> 20 20 21 <% if (_hasCover) { %><img class="grid-tile-img" src="<%= post.cover_image_url%>" alt="" loading="lazy" decoding="async"><% } %>21 <% if (_hasCover) { %><img class="grid-tile-img" src="<%= thumb(post.cover_image_url, 480) %>" alt="" loading="lazy" decoding="async"><% } %> 22 22 23 23 <% if (_typeLabel) { %>
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)