source: Klonkt/src/views/partials/note-body.ejs@ 54b027a

main
Last change on this file since 54b027a was 54b027a, checked in by Robin <roboburr@…>, 4 weeks ago

Een vreemde note mag de Krant niet meenemen

Robin meldde dat /news op beta niet meer werkte. Oorzaak:

_m.filter is not a function note-body.ejs:20

Drie posts van europeanpirates.eu dragen media_json = "[]": een JSON-STRING met
daarin [], niet een array. De try/catch eromheen vangt KAPOTTE json, maar niet
geldige json van het VERKEERDE TYPE. JSON.parse('"[]"') geeft netjes de string
"[]" terug, en een string heeft geen .filter.

Gevolg: één vreemde note nam de hele pagina mee. Niet de post werd overgeslagen,
de Krant lag plat. Wat er van een andere server binnenkomt is niet van ons, dus de
vorm moet op het punt van gebruik afgedwongen worden en niet aangenomen.

Zelfde wacht gezet in guardian.js, waar dezelfde parse stond. Dat is nog
vervelender: het guardian-paneel is precies het scherm dat het moet doen op het
moment dat er iets aan de hand is.

Changed files:
src/views/partials/note-body.ejs

  • Array.isArray-controle na de parse

src/routes/guardian.js

  • dezelfde controle rond media_json in het wardpaneel

New file:
test/note-body-media-shape.test.js

  • een string, een object, een getal en kapotte json slopen de pagina niet
  • en een normale lijst wordt nog steeds getoond, want een fix die alle media wegpoetst is geen fix

remarks: tegenproef gedaan. Zonder de fix vallen de string, het object en het getal
om; kapotte json en de normale lijst blijven groen. De test meet dus het gat en niet
zichzelf. Suite 937 in UTC en Europe/Amsterdam.

Onderweg twee keer mijn eigen testopzet moeten repareren (ontbrekende emojiHtml- en
thumb-helper); dat was de test, niet de code.

Nog te doen: de drie rijen op beta zelf opruimen, en uitzoeken welk pad ooit dubbel
gestringificeerd heeft. In de huidige code staat die dubbele stringify niet meer.

-robo
Co-Authored-By: Claude Opus 4.8 <noreply@…>

  • Property mode set to 100644
File size: 3.5 KB
Line 
1<%
2 /* The body of a post, rendered the same way wherever a post shows up: de
3 Krant, Berichten and the Guardian PWA. Takes `nb` with the column names an
4 ap_timeline row uses (content, emoji_json, media_json, quote_json,
5 embed_json, nsfw, cw); ap_mentions and ap_interactions carry the same names
6 so a mention or a reply can be handed straight to it.
7
8 Krant-only trimmings (the boost byline, polls, the audio player iframe, the
9 action bar) stay in tl-item: they are about the feed, not about the post. */
10 // De catch vangt KAPOTTE json; hij vangt niet geldige json van het verkeerde
11 // TYPE. Drie posts van een remote server droegen media_json = "[]", dus een
12 // string met daarin [], en JSON.parse geeft dan netjes een string terug. Een
13 // string heeft geen .filter, en daarmee lag de hele Krant plat: één vreemde
14 // note nam de pagina mee. Wat er binnenkomt is niet van ons, dus de vorm moet
15 // hier afgedwongen worden en niet aangenomen.
16 var _m = []; try { _m = JSON.parse(nb.media_json || '[]'); } catch (e) { _m = []; }
17 if (!Array.isArray(_m)) _m = [];
18 var _imgs = _m.filter(function (m) { return m && m.url && (!m.type || /^image\//.test(m.type)); });
19 var _vids = _m.filter(function (m) { return m && m.url && m.type && /^video\//.test(m.type); });
20 var _auds = _m.filter(function (m) { return m && m.url && m.type && /^audio\//.test(m.type); });
21 var _hasVisual = _imgs.length || _vids.length || _auds.length;
22 var _nsfwVisual = !!nb.nsfw && _hasVisual;
23 var _nsfwText = !!nb.nsfw && !_hasVisual;
24 // One card for both: a fediverse quote and an external link preview look
25 // identical; only where they came from differs. An embed carries a title and
26 // a thumbnail, never an iframe.
27 var _quote = noteQuote(nb.quote_json);
28 if (!_quote) {
29 var _emb = noteQuote(nb.embed_json);
30 // The title comes from a third-party oEmbed provider, so it is escaped
31 // here: the quote card renders `content` as HTML (fine for AP content,
32 // which we sanitise on the way in, but not for this).
33 if (_emb) _quote = { url: _emb.url, author: _emb.author || (_emb.provider ? { name: _emb.provider } : null),
34 content: _emb.title ? ('<p>' + emojiName(_emb.title, null) + '</p>') : '', media: _emb.media || [] };
35 }
36 var _noAudio = !!nb.suppressAudio; // the Klonkt player iframe already covers these tracks
37%>
38<% if (_nsfwText) { %>
39 <div class="tl-content nsfw-media"><span class="nsfw-veil"><%- include('../partials/nsfw-veil', { cw: nb.cw }) %></span><%- emojiHtml(nb.content, nb.emoji_json) %></div>
40<% } else { %>
41 <div class="tl-content"><%- emojiHtml(nb.content, nb.emoji_json) %></div>
42<% } %>
43<% if (_quote) { %><%- include('../partials/quote-card', { q: _quote }) %><% } %>
44<% if (_nsfwVisual) { %><div class="nsfw-media"><% } %>
45<% if (_imgs.length) { %>
46 <div class="tl-media">
47 <% _imgs.forEach(function (m) { %>
48 <a class="tl-media-img" href="<%= m.url %>" target="_blank" rel="noopener"><img src="<%= thumb(m.url, 1280) %>" alt="" loading="lazy" decoding="async"></a>
49 <% }); %>
50 </div>
51<% } %>
52<% _vids.forEach(function (m) { %><video class="tl-media-video" src="<%= m.url %>" poster="<%= thumb(m.url, 1280) %>" controls preload="metadata" playsinline></video><% }); %>
53<% if (!_noAudio) { _auds.forEach(function (m) { %><audio class="tl-media-audio" src="<%= m.url %>" controls preload="none"></audio><% }); } %>
54<% if (_nsfwVisual) { %><div class="nsfw-veil"><%- include('../partials/nsfw-veil', { cw: nb.cw }) %></div></div><% } %>
Note: See TracBrowser for help on using the repository browser.