Changeset 84903a1 in Klonkt
- Timestamp:
- 06/26/2026 04:02:03 PM (2 months ago)
- Branches:
- main
- Children:
- d22b55c
- Parents:
- 0fa59c3
- Location:
- src
- Files:
-
- 2 edited
-
routes/posts.js (modified) (1 diff)
-
views/pages/newspaper.ejs (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/routes/posts.js
r0fa59c3 r84903a1 597 597 } 598 598 599 // A federated Klonkt audio post renders as "🎵 … listen on <link>". Embed the remote 600 // Klonkt player (its /embed?post=<slug>). A single-segment path = a Klonkt post slug 601 // (skips Mastodon /@user/123). The origin is whitelisted in the response CSP frame-src. 602 function klonktAudioEmbed(html, url) { 603 if (!html || !url || html.indexOf('🎵') < 0) return null; 604 let u; try { u = new URL(url); } catch { return null; } 605 if (u.protocol !== 'https:' && u.protocol !== 'http:') return null; 606 const slug = u.pathname.replace(/^\/+|\/+$/g, ''); 607 if (!slug || slug.indexOf('/') >= 0) return null; // single segment only 608 const src = u.origin + '/embed?post=' + encodeURIComponent(slug); 609 return { origin: u.origin, html: `<iframe class="tl-embed-frame tl-embed-klonkt" src="${src}" title="Audio" loading="lazy" frameborder="0" allow="autoplay; encrypted-media"></iframe>` }; 610 } 611 599 612 router.get('/newspaper', requireSiteManager, (req, res) => { 600 613 const site = res.locals.site; 601 const timeline = (site ? ActivityPubService.getTimeline(site.slug, 60) : []) 602 .map((p) => ({ ...p, embedHtml: timelineEmbedHtml(p.content) })); 614 const cspOrigins = new Set(); 615 const timeline = (site ? ActivityPubService.getTimeline(site.slug, 60) : []).map((p) => { 616 let embedHtml = timelineEmbedHtml(p.content); 617 if (!embedHtml) { 618 const k = klonktAudioEmbed(p.content, p.url); 619 if (k) { embedHtml = k.html; cspOrigins.add(k.origin); } 620 } 621 return { ...p, embedHtml }; 622 }); 623 // Option A: allow the followed Klonkt sites' player iframes (you follow them) by 624 // extending ONLY this response's CSP frame-src. The global policy stays locked down. 625 if (cspOrigins.size) { 626 const csp = res.getHeader('Content-Security-Policy'); 627 if (csp) { 628 const extra = [...cspOrigins].join(' '); 629 res.setHeader('Content-Security-Policy', String(csp).replace(/frame-src ([^;]*)/i, (m, g) => `frame-src ${g} ${extra}`)); 630 } 631 } 603 632 renderPage(req, res, 'pages/newspaper', { 604 pageTitle: ' Tijdlijn', bodyClass: 'on-special',633 pageTitle: 'Newspaper', bodyClass: 'on-special', 605 634 timeline, 606 635 success: req.query.success || null, error: req.query.error || null, -
src/views/pages/newspaper.ejs
r0fa59c3 r84903a1 106 106 .tl-embed-spotify { aspect-ratio: auto; height: 152px; } 107 107 .tl-embed-sc { aspect-ratio: auto; height: 166px; } 108 .tl-embed-klonkt { aspect-ratio: auto; height: 180px; background: var(--paper, #fff); } 108 109 109 110 .tl-orig { display: inline-block; margin: .7rem 0 0; font-size: .82rem; color: var(--accent, #06c); text-decoration: none; }
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)