Changeset ea3e722 in Klonkt
- Timestamp:
- 08/09/2026 08:34:57 AM (4 weeks ago)
- Branches:
- main
- Children:
- 5ae4d61
- Parents:
- d60c498
- Files:
-
- 4 edited
-
src/services/ActivityPubService.js (modified) (3 diffs)
-
src/services/ap-core.js (modified) (1 diff)
-
src/services/music/index.js (modified) (3 diffs)
-
test/music-uitgave.test.js (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/services/ActivityPubService.js
rd60c498 rea3e722 29 29 import Blocklist from './BlocklistService.js'; 30 30 import * as Guardianship from './guardianship/index.js'; 31 import { PUBLIC, AP_CONTEXT, safeUrl, actorId, noteId, guessMediaType, normalizeTags, tagParts } from './ap-core.js';31 import { PUBLIC, AP_CONTEXT, safeUrl, actorId, noteId, guessMediaType, normalizeTags, tagParts, hashtagTags, buildHashtagList } from './ap-core.js'; 32 32 // Doorgeven wat hier altijd vandaan kwam, zodat elke bestaande aanroep blijft werken. 33 33 export { AP_CONTEXT, actorId, noteId, guessMediaType }; … … 2960 2960 2961 2961 // Extract the AP Hashtag tag objects from already-linked reply content. 2962 function hashtagTags(base, content) {2963 const tags = [], seen = new Set();2964 const re = /class="[^"]*\bhashtag\b[^"]*"[^>]*>#([\p{L}\p{M}\p{N}_]+)</giu;2965 let m;2966 while ((m = re.exec(content || ''))) {2967 const k = m[1].toLowerCase();2968 if (seen.has(k)) continue; seen.add(k);2969 tags.push({ type: 'Hashtag', href: `${base}/tag/${encodeURIComponent(k)}`, name: '#' + m[1] });2970 }2971 return tags;2972 }2973 2962 2974 2963 // Normalise a post's tags field (array, JSON-string, or comma-string) to an array. … … 2980 2969 // Merge a post's tags field + the #hashtags linked inline in its body into one deduped 2981 2970 // Hashtag tag list (with hrefs to our /tag page). 2982 function buildHashtagList(base, tagsField, content) { 2983 const out = [], seen = new Set(); 2984 for (const t of normalizeTags(tagsField)) { 2985 const p = tagParts(t); if (!p || seen.has(p.slug)) continue; seen.add(p.slug); 2986 out.push({ type: 'Hashtag', href: `${base}/tag/${encodeURIComponent(p.slug)}`, name: '#' + p.label }); 2987 } 2988 for (const h of hashtagTags(base, content)) { 2989 const k = h.name.slice(1).toLowerCase(); if (seen.has(k)) continue; seen.add(k); 2990 out.push(h); 2991 } 2992 return out; 2993 } 2971 // hashtagTags en buildHashtagList staan sinds shaer-38y in ap-core: music/ 2972 // heeft dezelfde lijst nodig en mag hier niet uit importeren. 2994 2973 2995 2974 // Extract Mention tag objects from already-linked content (class="u-url mention"). -
src/services/ap-core.js
rd60c498 rea3e722 124 124 return { label, slug }; 125 125 } 126 127 /** 128 * De #hashtags die in het LIJF van een post gelinkt staan, zoals ze GESCHREVEN 129 * zijn. De slug in de href is kleingeschreven -- dat is een adres -- maar de 130 * naam niet: #DoenweNiet blijft #DoenweNiet. 131 */ 132 export function hashtagTags(base, content) { 133 const tags = [], seen = new Set(); 134 const re = /class="[^"]*\bhashtag\b[^"]*"[^>]*>#([\p{L}\p{M}\p{N}_]+)</giu; 135 let m; 136 while ((m = re.exec(content || ''))) { 137 const k = m[1].toLowerCase(); 138 if (seen.has(k)) continue; seen.add(k); 139 tags.push({ type: 'Hashtag', href: `${base}/tag/${encodeURIComponent(k)}`, name: '#' + m[1] }); 140 } 141 return tags; 142 } 143 144 /** 145 * Het tagveld van een post en de #hashtags uit het lijf, samen en ontdubbeld. 146 * 147 * HET LIJF GAAT VOOR (Robin, 9-8): staat een tag allebei, dan wint de vorm 148 * zoals hij GESCHREVEN is. Het tagveld gaat door tagParts, en die maakt van 149 * "Doen we Niet" het CamelCase #DoenWeNiet -- nodig, want een hashtag mag geen 150 * spaties bevatten. Maar als iemand in zijn tekst #DoenweNiet heeft getypt is 151 * dat geen benadering meer maar de tag zelf, en dan hoort die te staan zoals 152 * hij er staat. Eerder won het veld, en verdween de geschreven vorm. 153 */ 154 export function buildHashtagList(base, tagsField, content) { 155 const out = [], seen = new Set(); 156 for (const h of hashtagTags(base, content)) { 157 const k = h.name.slice(1).toLowerCase(); if (seen.has(k)) continue; seen.add(k); 158 out.push(h); 159 } 160 for (const t of normalizeTags(tagsField)) { 161 const p = tagParts(t); if (!p || seen.has(p.slug)) continue; seen.add(p.slug); 162 out.push({ type: 'Hashtag', href: `${base}/tag/${encodeURIComponent(p.slug)}`, name: '#' + p.label }); 163 } 164 return out; 165 } -
src/services/music/index.js
rd60c498 rea3e722 14 14 15 15 import db from '../../config/database.js'; 16 import { AP_CONTEXT, PUBLIC, actorId, noteId, safeUrl, guessMediaType, normalizeTags, tagParts} from '../ap-core.js';16 import { AP_CONTEXT, PUBLIC, actorId, noteId, safeUrl, guessMediaType, buildHashtagList } from '../ap-core.js'; 17 17 import { afleidenUitInsluitingen, ingeslotenPlaylists } from '../../assets/js/shared/post-music-type.js'; 18 18 … … 377 377 } 378 378 379 const tags = hashtagsVanPost(base, post.tags); 379 // Dezelfde lijst als de Note: het tagveld EN de hashtags uit het lijf, waarbij 380 // de geschreven vorm voorgaat. Een eigen lijst hier zou de tags uit de tekst 381 // missen en de rest anders spellen dan dezelfde post elders doet. 382 const tags = buildHashtagList(base, post.tags, post.content); 380 383 if (tags.length) obj.tag = tags; 381 384 … … 386 389 obj.context = noteId(base, post.id); 387 390 return obj; 388 }389 390 /**391 * De tags van een post als AS2 Hashtags -- zelfde vorm als buildHashtagList.392 *393 * Met normalizeTags en niet met een eigen split: het veld staat als JSON-array394 * in de database, en op komma's splitsen leverde live `#["Doen we Niet"` op.395 * Dat is het soort fout dat niet omvalt maar onzin uitlevert.396 */397 function hashtagsVanPost(base, tagsField) {398 const uit = [], gezien = new Set();399 for (const t of normalizeTags(tagsField)) {400 const p = tagParts(t);401 if (!p || gezien.has(p.slug)) continue;402 gezien.add(p.slug);403 uit.push({ type: 'Hashtag', href: `${base}/tag/${encodeURIComponent(p.slug)}`, name: '#' + p.label });404 }405 return uit;406 391 } 407 392 -
test/music-uitgave.test.js
rd60c498 rea3e722 74 74 assert.equal(col.image.type, 'Image'); 75 75 assert.equal(col.image.url, `${BASE}/media/hoes.jpg`); 76 // Het tagveld is JSON in de database , en een tag van twee woorden wordt77 // CamelCase -- zelfde regel als elders, want het is nu dezelfde parser.76 // Het tagveld is JSON in de database. Een tag van twee woorden wordt 77 // CamelCase, want een hashtag mag geen spaties bevatten. 78 78 assert.deepEqual(col.tag.map((t) => t.name), ['#lofi', '#ZolderTapes']); 79 79 assert.equal(col.tag[1].href, `${BASE}/tag/zoldertapes`); … … 196 196 assert.equal(M.buildPostTrackCollection(BASE, site, p).content, 'Opgenomen in de schuur.'); 197 197 }); 198 199 test('een hashtag uit het LIJF staat zoals hij geschreven is', () => { 200 // Robins punt (9-8): #DoenweNiet in de tekst hoort #DoenweNiet te blijven. 201 // Eerder won de vorm uit het tagveld -- tagParts maakt daar #DoenWeNiet van -- 202 // en verdween de geschreven vorm als duplicaat. 203 const p = maakPost({ 204 id: 'p-schrijf', slug: 'zoals-geschreven', titel: 'Zoals geschreven', 205 content: '<p>Zie <a class="hashtag" href="/tag/doenweniet">#DoenweNiet</a></p>[[track:t-een]]', 206 tags: '["Doen we Niet","lofi"]', 207 }); 208 const col = M.buildPostTrackCollection(BASE, site, p); 209 const namen = col.tag.map((t) => t.name); 210 assert.ok(namen.includes('#DoenweNiet'), 'de geschreven vorm wint'); 211 assert.ok(!namen.includes('#DoenWeNiet'), 'en de genormaliseerde staat er niet naast'); 212 assert.ok(namen.includes('#lofi'), 'tags die alleen in het veld staan blijven'); 213 assert.equal(col.tag[0].href, `${BASE}/tag/doenweniet`, 'de slug blijft wel klein: dat is een adres'); 214 });
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)