Unfurl card in link previews

This commit is contained in:
Alex Gleason
2023-05-06 19:58:41 -05:00
parent 2fff0ed879
commit b6ce22cfaf
3 changed files with 87 additions and 26 deletions

View File

@@ -6,16 +6,6 @@ linkify.registerCustomProtocol('wss');
const url = (path: string) => new URL(path, LOCAL_DOMAIN).toString();
/** Get pubkey from decoded bech32 entity, or undefined if not applicable. */
function getDecodedPubkey(decoded: nip19.DecodeResult): string | undefined {
switch (decoded.type) {
case 'npub':
return decoded.data;
case 'nprofile':
return decoded.data.pubkey;
}
}
const linkifyOpts: linkify.Opts = {
render: {
hashtag: ({ content }) => {
@@ -46,16 +36,8 @@ type Link = ReturnType<typeof linkify.find>[0];
interface ParsedNoteContent {
html: string;
links: Link[];
}
/** Ensures the URL can be parsed. Why linkifyjs doesn't already guarantee this, idk... */
function isValidLink(link: Link): boolean {
try {
new URL(link.href);
return true;
} catch (_e) {
return false;
}
/** First non-media URL - eligible for a preview card. */
firstUrl: string | undefined;
}
/** Convert Nostr content to Mastodon API HTML. Also return parsed data. */
@@ -63,10 +45,12 @@ function parseNoteContent(content: string): ParsedNoteContent {
// Parsing twice is ineffecient, but I don't know how to do only once.
const html = linkifyStr(content, linkifyOpts);
const links = linkify.find(content).filter(isValidLink);
const firstUrl = links.find(isNonMediaLink)?.href;
return {
html,
links,
firstUrl,
};
}
@@ -77,9 +61,7 @@ interface MediaLink {
function getMediaLinks(links: Link[]): MediaLink[] {
return links.reduce<MediaLink[]>((acc, link) => {
const { pathname } = new URL(link.href);
const mimeType = mime.getType(pathname);
const mimeType = getUrlMimeType(link.href);
if (!mimeType) return acc;
const [baseType, _subType] = mimeType.split('/');
@@ -95,4 +77,39 @@ function getMediaLinks(links: Link[]): MediaLink[] {
}, []);
}
function isNonMediaLink({ href }: Link): boolean {
return /^https?:\/\//.test(href) && !getUrlMimeType(href);
}
/** Ensures the URL can be parsed. Why linkifyjs doesn't already guarantee this, idk... */
function isValidLink(link: Link): boolean {
try {
new URL(link.href);
return true;
} catch (_e) {
console.error(`Invalid link: ${link.href}`);
return false;
}
}
/** `npm:mime` treats `.com` as a file extension, so parse the full URL to get its path first. */
function getUrlMimeType(url: string): string | undefined {
try {
const { pathname } = new URL(url);
return mime.getType(pathname) || undefined;
} catch (_e) {
return undefined;
}
}
/** Get pubkey from decoded bech32 entity, or undefined if not applicable. */
function getDecodedPubkey(decoded: nip19.DecodeResult): string | undefined {
switch (decoded.type) {
case 'npub':
return decoded.data;
case 'nprofile':
return decoded.data.pubkey;
}
}
export { getMediaLinks, type MediaLink, parseNoteContent };