mirror of
https://github.com/aljazceru/ditto.git
synced 2026-01-22 14:54:22 +01:00
Unfurl card in link previews
This commit is contained in:
63
src/note.ts
63
src/note.ts
@@ -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 };
|
||||
|
||||
Reference in New Issue
Block a user