Changeset 8b65e67 in Klonkt
- Timestamp:
- 08/18/2026 06:47:58 PM (3 weeks ago)
- Branches:
- main
- Children:
- f5cf299
- Parents:
- b1b7652
- git-author:
- Bart <bart@…> (08/17/2026 07:37:17 PM)
- git-committer:
- Bart <bart@…> (08/18/2026 06:47:58 PM)
- Files:
-
- 1 added
- 2 edited
-
src/services/PostAccessService.js (modified) (1 diff)
-
src/views/partials/post-body.ejs (added)
-
test/post-access.test.js (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/services/PostAccessService.js
rb1b7652 r8b65e67 69 69 export function canReadBody(post, viewer) { return postAccess(post, viewer) === 'full'; } 70 70 71 export default { postAccess, canReadBody, paidTeaser }; 71 /** 72 * Eén bericht, klaar voor de tijdlijn. 73 * 74 * DE HELE REDEN DAT DIT EEN FUNCTIE IS: het lijf wordt alleen GERENDERD als het 75 * ook getoond mag worden. Een sjabloon dat zelf `<% if (access === 'full') %>` 76 * doet krijgt de volledige tekst tóch mee in het model, en dan is het één 77 * vergeten conditie -- of één `?partial=1` die net iets anders samenstelt -- 78 * tussen een betaalmuur en de tekst erachter. Hier komt hij niet eens mee. 79 * 80 * `renderBody` wordt ingespoten (posts.js levert renderPostBodyHtml), zodat 81 * deze module niets van routes of sjablonen hoeft te weten. 82 */ 83 export function postEntry(post, viewer, { renderBody } = {}) { 84 const access = postAccess(post, viewer); 85 const full = access === 'full'; 86 return { 87 slug: post && post.slug, 88 title: (post && post.title) || '', 89 access, 90 // Alleen bij een gesloten poort een teaser, en nooit allebei: de teaser is 91 // de vervanging van het lijf, niet een voorproefje ernaast. 92 teaser: full || access === 'forbidden' ? null : paidTeaser(post), 93 content_html: full && typeof renderBody === 'function' ? renderBody(post) : null, 94 }; 95 } 96 97 export default { postAccess, canReadBody, paidTeaser, postEntry }; -
test/post-access.test.js
rb1b7652 r8b65e67 96 96 assert.equal(paidTeaser(post({ excerpt: 'zelf geschreven' })), 'zelf geschreven'); 97 97 }); 98 99 // ── Wat de tijdlijn krijgt ──────────────────────────────────────────────── 100 // De tijdlijn toont hele berichten, dus een gesloten bericht moet zijn plek 101 // houden ZONDER dat de tekst meereist. Dat is geen sjabloonkwestie: wat niet 102 // gerenderd wordt, kan ook niet per ongeluk getoond worden. 103 104 const { postEntry } = await import('../src/services/PostAccessService.js'); 105 const renderBody = (p) => `<div>GEHEIM: ${p.content}</div>`; 106 107 test('een open bericht krijgt zijn lijf', () => { 108 const e = postEntry(post(), { user: VREEMDE, site: SITE }, { renderBody }); 109 assert.equal(e.access, 'full'); 110 assert.match(e.content_html, /GEHEIM/); 111 assert.equal(e.teaser, null, 'geen teaser NAAST het lijf'); 112 }); 113 114 test('een betaald bericht reist zonder tekst', () => { 115 const e = postEntry(post({ paid: 1 }), { user: VREEMDE, site: SITE }, { renderBody }); 116 assert.equal(e.access, 'paid'); 117 assert.equal(e.content_html, null, 'het lijf wordt niet eens gerenderd'); 118 assert.match(e.teaser, /eerste alinea/); 119 assert.ok(!JSON.stringify(e).includes('tweede alinea'), 'en niets erachter lekt mee'); 120 }); 121 122 test('een fan-bericht ook niet', () => { 123 const e = postEntry(post({ fan_only: 1 }), { user: VREEMDE, site: SITE }, { renderBody }); 124 assert.equal(e.access, 'fan'); 125 assert.equal(e.content_html, null); 126 }); 127 128 test('een concept levert helemaal niets op', () => { 129 const e = postEntry(post({ status: 'draft' }), { user: VREEMDE, site: SITE }, { renderBody }); 130 assert.equal(e.access, 'forbidden'); 131 assert.equal(e.content_html, null); 132 assert.equal(e.teaser, null, 'ook geen teaser: over een concept valt niets te zeggen'); 133 }); 134 135 test('zonder renderer nog steeds geen lijf, en geen fout', () => { 136 const e = postEntry(post(), { user: VREEMDE, site: SITE }); 137 assert.equal(e.access, 'full'); 138 assert.equal(e.content_html, null); 139 });
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)