link-view
Version:
A Node.js package to generate link previews from URLs
62 lines (53 loc) • 2.21 kB
JavaScript
const cheerio = require('cheerio');
const { fetchWithFallback } = require('./preview');
const generateLinkPreview = async (url) => {
try {
// Validate URL
let validUrl;
try {
validUrl = new URL(url).href;
} catch (e) {
throw new Error('Invalid URL format');
}
// Attempt to fetch the data
const htmlContent = await fetchWithFallback(validUrl);
if (!htmlContent) {
throw new Error('Failed to fetch page content');
}
// Load HTML content with cheerio
const $ = cheerio.load(htmlContent);
// Extract metadata
const getMetaTag = (name) => {
return (
$(`meta[name="${name}"]`).attr('content') ||
$(`meta[property="og:${name}"]`).attr('content') ||
$(`meta[name="twitter:${name}"]`).attr('content')
);
};
const preview = {
url: validUrl,
title: $('meta[name="extracted-title"]').attr('content') ||
getMetaTag('title') ||
$('title').first().text().split('|')[0].trim(),
description: getMetaTag('description') || $('p').first().text(),
image: $('meta[name="product-image"]').attr('content') ||
getMetaTag('image') ||
$('img').first().attr('src'),
favicon: $('link[rel="shortcut icon"]').attr('href') ||
$('link[rel="icon"]').attr('href'),
domain: new URL(validUrl).hostname.replace('www.', ''),
author: getMetaTag('author')
};
// Clean up relative URLs
if (preview.image && !preview.image.startsWith('http')) {
preview.image = new URL(preview.image, validUrl).href;
}
if (preview.favicon && !preview.favicon.startsWith('http')) {
preview.favicon = new URL(preview.favicon, validUrl).href;
}
return preview;
} catch (error) {
throw new Error(`Failed to generate link preview: ${error.message}`);
}
};
module.exports = { generateLinkPreview };