- Timestamp:
- 07/01/2026 10:20:25 PM (2 months ago)
- Branches:
- main
- Children:
- e499b71
- Parents:
- 2abd3d2
- File:
-
- 1 edited
-
src/services/ActivityPubService.js (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/services/ActivityPubService.js
r2abd3d2 rfc229f5 1402 1402 // Turn #hashtags in reply text into Mastodon-style hashtag links (clickable + federated). 1403 1403 function linkHashtags(base, html) { 1404 return String(html || '').replace(/(^|[\s>])#([\p{L}\p{M}\p{N}_]+)/gu, (m, pre, tag) => 1404 // Prefix: start / whitespace / '>' / opening bracket — "(#tag" is a tag too. NO quote 1405 // chars in this class: a quote precedes attribute values (alt="#…"), which must not match. 1406 return String(html || '').replace(/(^|[\s>([{])#([\p{L}\p{M}\p{N}_]+)/gu, (m, pre, tag) => 1405 1407 `${pre}<a href="${base}/tag/${encodeURIComponent(tag.toLowerCase())}" class="mention hashtag" rel="tag">#${tag}</a>`); 1406 1408 } … … 1413 1415 for (let i = 0; i < parts.length; i++) { 1414 1416 if (/^<a\b/i.test(parts[i])) continue; // already a link → leave as-is 1415 parts[i] = parts[i].replace(/(^|[\s> ])(https?:\/\/[^\s<]+?)([.,;:!?)\]»]*)(?=$|[\s<])/g,1417 parts[i] = parts[i].replace(/(^|[\s>([{])(https?:\/\/[^\s<]+?)([.,;:!?)\]»]*)(?=$|[\s<])/g, 1416 1418 (m, pre, url, trail) => `${pre}<a href="${url.replace(/"/g, '%22')}" rel="nofollow noopener" target="_blank">${url}</a>${trail}`); 1417 1419 } … … 1485 1487 const inboxes = []; 1486 1488 const handles = new Set(); 1487 const re = /(^|[\s>])@([\p{L}\p{M}\p{N}_.-]+@[\p{L}\p{M}\p{N}.-]+)/gu; 1489 // Prefix also allows opening brackets — "(@user@host + me)" is a mention too (real-world 1490 // miss: a bracketed mention federated as plain text and its target was never notified). 1491 const re = /(^|[\s>([{])@([\p{L}\p{M}\p{N}_.-]+@[\p{L}\p{M}\p{N}.-]+)/gu; 1488 1492 let m; 1489 1493 while ((m = re.exec(html || ''))) handles.add(m[2]); … … 1498 1502 const profileUrl = actorInfo(actor, actorUri).url || actorUri; // human profile page → the link href 1499 1503 const esc = h.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); 1500 out = out.replace(new RegExp('(^|[\\s> ])@' + esc + '(?![\\p{L}\\p{M}\\p{N}_.-])', 'gu'),1504 out = out.replace(new RegExp('(^|[\\s>([{])@' + esc + '(?![\\p{L}\\p{M}\\p{N}_.-])', 'gu'), 1501 1505 (full, pre) => `${pre}<a href="${profileUrl}" class="u-url mention" data-actor="${actorUri}">@${h}</a>`); 1502 1506 }
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)