Merge pull request #528 from v0l/fix-nostr-npub-broken-links

don't render nostr:npub as a link
This commit is contained in:
Kieran 2023-04-20 21:49:46 +01:00 committed by GitHub
commit 8f504cfef9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 60 additions and 3 deletions

View File

@ -7,7 +7,7 @@ import * as unist from "unist";
import { HexKey, NostrPrefix } from "@snort/nostr";
import { MentionRegex, InvoiceRegex, HashtagRegex } from "Const";
import { eventLink, hexToBech32, splitByUrl, unwrap } from "Util";
import { eventLink, hexToBech32, splitByUrl, unwrap, validateNostrLink } from "Util";
import Invoice from "Element/Invoice";
import Hashtag from "Element/Hashtag";
import Mention from "Element/Mention";
@ -36,7 +36,21 @@ export default function Text({ content, tags, creator, disableMedia, depth }: Te
.map(f => {
if (typeof f === "string") {
return splitByUrl(f).map(a => {
if (a.match(/^(?:https?|(?:web\+)?nostr|magnet):/i)) {
const validateLink = () => {
const normalizedStr = a.toLowerCase();
if (normalizedStr.startsWith("web+nostr:") || normalizedStr.startsWith("nostr:")) {
return validateNostrLink(normalizedStr);
}
return (
normalizedStr.startsWith("http:") ||
normalizedStr.startsWith("https:") ||
normalizedStr.startsWith("magnet:")
);
};
if (validateLink()) {
if (disableMedia ?? false) {
return (
<a href={a} onClick={e => e.stopPropagation()} target="_blank" rel="noreferrer" className="ext">

View File

@ -1,4 +1,4 @@
import { splitByUrl, magnetURIDecode, getRelayName } from "./Util";
import { splitByUrl, magnetURIDecode, getRelayName, validateNostrLink } from "./Util";
describe("splitByUrl", () => {
it("should split a string by URLs", () => {
@ -90,3 +90,24 @@ describe("getRelayName", () => {
expect(output).toEqual("relay.example2.com?broadcast=true");
});
});
describe("validateNostrLink", () => {
it("should return true for valid nostr links", () => {
[
"nostr:npub10elfcs4fr0l0r8af98jlmgdh9c8tcxjvz9qkw038js35mp4dma8qzvjptg",
"web+nostr:npub10elfcs4fr0l0r8af98jlmgdh9c8tcxjvz9qkw038js35mp4dma8qzvjptg",
"nostr:note15449edq4qa5wzgqvh8td0q0dp6hwtes4pknsrm7eygeenhlj99xsq94wu9",
"nostr:nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p",
"nostr:nevent1qqs226juks2sw68pyqxtn4khs8ksath9uc2smfcpalvjyvuemlezjngrd87dq",
"nostr:naddr1qqzkjurnw4ksz9thwden5te0wfjkccte9ehx7um5wghx7un8qgs2d90kkcq3nk2jry62dyf50k0h36rhpdtd594my40w9pkal876jxgrqsqqqa28pccpzu",
].forEach(link => {
expect(validateNostrLink(link)).toBe(true);
});
});
it("should return false for invalid nostr links", () => {
["nostr:npub", "web+nostr:npub", "nostr:nevent1xxx"].forEach(link => {
expect(validateNostrLink(link)).toBe(false);
});
});
});

View File

@ -491,6 +491,24 @@ export interface NostrLink {
encode(): string;
}
export function validateNostrLink(link: string): boolean {
try {
const parsedLink = parseNostrLink(link);
if (!parsedLink) {
return false;
}
if (parsedLink.type === NostrPrefix.PublicKey || parsedLink.type === NostrPrefix.Note) {
return parsedLink.id.length === 64;
}
return true;
} catch {
return false;
}
}
export function parseNostrLink(link: string): NostrLink | undefined {
const entity = link.startsWith("web+nostr:") || link.startsWith("nostr:") ? link.split(":")[1] : link;

View File

@ -0,0 +1,4 @@
// @ts-expect-error - we have a folder called util so TS gets confused
import { TextEncoder, TextDecoder } from "util";
Object.assign(global, { TextDecoder, TextEncoder });