Changeset 7cf8144 in Klonkt for src/routes/posts.js
- Timestamp:
- 08/18/2026 06:47:58 PM (3 weeks ago)
- Branches:
- main
- Children:
- 9da8027
- Parents:
- 2d2fd8c
- git-author:
- Bart <bart@…> (08/18/2026 05:28:31 AM)
- git-committer:
- Bart <bart@…> (08/18/2026 06:47:58 PM)
- File:
-
- 1 edited
-
src/routes/posts.js (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/routes/posts.js
r2d2fd8c r7cf8144 232 232 233 233 if (append) { 234 return renderPage(req, res, 'partials/home-append', { posts, hasMore, nextOffset: offset + FEED_PAGE, moreBase }); 234 return renderPage(req, res, 'partials/home-append', { 235 posts, hasMore, nextOffset: offset + FEED_PAGE, moreBase, 236 readerItems: readerItems(site, posts, req), 237 }); 235 238 } 236 239 … … 243 246 pinnedPosts, 244 247 posts, 248 readerItems: readerItems(site, [...pinnedPosts, ...posts], req), 245 249 hasMore, nextOffset: offset + FEED_PAGE, moreBase, 246 250 movedTo, … … 249 253 socialDescr: site.description || site.tagline || '', 250 254 bodyClass: 'on-home', 255 // mod/read.js: alleen nog de tik-op-een-bericht in de leesweergave. 256 pageJs: 'read', 251 257 }); 252 });253 254 // ==================== LEES (meeslepende tijdlijn) ====================255 //256 // Eén bericht vult het scherm, de chrome schuift weg, en je scrollt voorbij de257 // rand naar het vorige of volgende. Naar bartoverkamp.nl, waar prev/next258 // schildwachten boven en onder het artikel staan en het overscrollen zelf de259 // navigatie is.260 //261 // De buren komen uit postNeighbors(), dezelfde die de gewone postpagina al262 // gebruikt -- dus "vorige" en "volgende" betekenen hier precies hetzelfde als263 // daar, ook voor gepinde berichten.264 //265 // ?partial=1 levert alleen het artikel, want dat is wat de schildwacht inruilt.266 router.get('/read/:slug?', (req, res, next) => {267 const site = res.locals.site;268 if (!site) return next();269 270 // Zonder slug: het nieuwste bericht, zodat /read een ingang is en niet een271 // fout. Gepind eerst, net als op de voorpagina.272 const post = req.params.slug273 ? db.prepare(`SELECT p.*, u.username as author_username FROM posts p JOIN users u ON p.author_id = u.id274 WHERE p.site_id = ? AND p.slug = ?`).get(site.id, req.params.slug)275 : db.prepare(`SELECT p.*, u.username as author_username FROM posts p JOIN users u ON p.author_id = u.id276 WHERE p.site_id = ? AND p.status = 'published'277 ORDER BY (p.pinned = 0) ASC, p.pinned ASC, p.published_at DESC LIMIT 1`).get(site.id);278 if (!post) return next();279 280 // Het besluit en het lijf komen uit één plek (PostAccessService). Een dichte281 // poort levert hier GEEN tekst op: die wordt niet eens gerenderd.282 const _u = req.query.u ? verifyBlob(String(req.query.u)) : null;283 const unlockedSlug = (_u && _u.purpose === 'unlocked' && _u.siteId === site.id) ? String(_u.post) : null;284 const entry = postEntry(post, { user: req.session?.user || null, site, unlockedSlug },285 { renderBody: (p) => renderPostBodyHtml(site, p, req) });286 287 if (entry.access === 'forbidden') return next();288 289 const { newerPost, olderPost } = postNeighbors(site, post);290 const model = {291 post, entry, newerPost, olderPost,292 pageTitle: post.title || site.title,293 // on-read zet de chrome weg; de mini-topnav blijft (chrome.ejs, _headerless).294 bodyClass: 'on-read on-special',295 pageJs: 'read',296 };297 // ALLEEN de leesmodule krijgt één artikel; ?fragment=1 is haar eigen teken.298 //299 // Hier stond `?partial=1 || hx-request`, en dat waren twee dingen door elkaar.300 // Op deze site betekent ?partial=1 al iets anders -- "de pagina zonder de301 // schil", voor htmx -- dus een gebooste link naar /read kreeg één kaal302 // artikel in #pcms-main geschoven: geen stroom, geen on-read, geen script.303 // Onzichtbaar zolang je /read alleen intikt; zichtbaar zodra er een link naar304 // toe bestaat (de Lezen-knop in de view-switcher).305 //306 // Alles wat GEEN fragment vraagt gaat naar pages/read, en renderPage bepaalt307 // daar zelf of de schil eromheen moet -- net als bij elke andere pagina.308 if (req.query.fragment === '1') {309 return renderPage(req, res, 'partials/read-article', model);310 }311 recordPageview(site.id, req);312 return renderPage(req, res, 'pages/read', model);313 258 }); 314 259 … … 748 693 // Renders a post's display HTML: baked content + the dynamic audio/embed layer. 749 694 // Extracted so the paid unlock (slice 4) serves the exact same body as the page. 695 // Dezelfde berichten, klaar voor de leesweergave. 696 // 697 // Tijdlijn en Grid tonen kaartjes; Lezen toont het hele stuk. Het is dus geen 698 // andere PAGINA maar een andere vorm van dezelfde rijen -- vandaar dat de feed 699 // ze alledrie meestuurt en CSS kiest, precies zoals timeline/grid dat al deden. 700 // 701 // Het lijf loopt door PostAccessService: een gesloten poort levert hier GEEN 702 // tekst op, want wat niet gerenderd wordt kan ook niet lekken. 703 function readerItems(site, rows, req) { 704 const viewer = { user: req.session?.user || null, site, unlockedSlug: null }; 705 return rows.map((post) => ({ 706 post, 707 entry: postEntry(post, viewer, { renderBody: (p) => renderPostBodyHtml(site, p, req) }), 708 })); 709 } 710 750 711 export function renderPostBodyHtml(site, post, req) { 751 712 let html = (post.content_rendered != null && post.content_rendered !== '')
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)