aboutsummaryrefslogtreecommitdiffstats
path: root/src/features
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-09-15 22:47:26 -0700
committerAdam Soltys <[email protected]>2026-09-15 22:47:26 -0700
commit398bb77165e3ff454f1401b3c114a976aae5216c (patch)
treef362de76df685538e352b998a0839c64faf4448c /src/features
parent3d706acd1edccb5c4eb0f781b52b3d302bdafa2b (diff)
downloadcoinosv3-398bb77165e3ff454f1401b3c114a976aae5216c.tar.gz
coinosv3-398bb77165e3ff454f1401b3c114a976aae5216c.zip
A bare @npub in a message resolves to the person's name.
Vector writes a mention as @npub1… with no nostr: prefix; ours only resolved the prefixed form, so the raw key sat in the bubble. Bare npubs and nprofiles, with or without the @, now render as @name and open the profile, like the prefixed ones. Keys inside URLs are left alone. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01JuwQqNWtDJcxPWtEm9134z
Diffstat (limited to 'src/features')
-rw-r--r--src/features/messages.js12
1 files changed, 8 insertions, 4 deletions
diff --git a/src/features/messages.js b/src/features/messages.js
index 0a87e15..3c48a17 100644
--- a/src/features/messages.js
+++ b/src/features/messages.js
@@ -3766,7 +3766,10 @@ export function messagesFeature(ctx) {
// nip05 (a word character sits before those), and never inside a URL
// (the URL token starts earlier and swallows it).
const MENTION = '(?<![\\w.@/])@[A-Za-z0-9_]{2,32}(?![\\w@])';
- const NOTE_SPLIT = new RegExp('(' + MD_LINK + '|https?:\\/\\/[^\\s]+|nostr:(?:npub|nprofile|note|nevent|naddr)1[a-z0-9]+|' + MENTION + ')', 'gi');
+ // A bare npub/nprofile — with or without an @ in front, no nostr: prefix —
+ // is how Vector (and people) write a mention; it resolves to the name too.
+ const BARE_KEY = '(?<![\\w/])@?(?:npub|nprofile)1[a-z0-9]{20,}(?![\\w])';
+ const NOTE_SPLIT = new RegExp('(' + MD_LINK + '|https?:\\/\\/[^\\s]+|nostr:(?:npub|nprofile|note|nevent|naddr)1[a-z0-9]+|' + BARE_KEY + '|' + MENTION + ')', 'gi');
const MD_PARTS = new RegExp('^(!?)\\[([^\\]\\n]{0,300})\\]\\(\\s*<?(https?:\\/\\/[^\\s>)]+)>?[^)\\n]{0,300}\\)$', 'i');
// A YouTube link is a video, so show the video. All three shapes it comes
@@ -4135,10 +4138,11 @@ export function messagesFeature(ctx) {
} else if (/^https?:\/\//i.test(part)) {
const pack = PACK_LINK_RE.exec(part);
out.push(pack ? packLinkNode(part, pack[1]) : urlNode(part));
- } else if (/^nostr:(npub|nprofile)1/i.test(part)) {
- const ref = parseNostrRef(part.slice(6));
+ } else if (/^(nostr:|@?)(npub|nprofile)1/i.test(part)) {
+ const bare = part.replace(/^(nostr:|@)/i, '');
+ const ref = parseNostrRef(bare);
if (ref && ref.type === 'pubkey') out.push(h('a', { href: '#', onClick: (e) => { e.preventDefault(); openProfile(ref.pk); } }, '@' + displayName(ref.pk)));
- else out.push(h('span', { class: 'faint' }, part.slice(6, 18) + '…'));
+ else out.push(h('span', { class: 'faint' }, bare.slice(0, 12) + '…'));
} else if (/^nostr:(note|nevent)1/i.test(part)) {
const ref = parseNostrRef(part.slice(6));
if (ref && ref.type === 'event') {