Skip to content

Extraer imágenes para compartir en redes sociales y etiquetas Open Graph

La API HTMLRewriter de Bun se puede usar para extraer eficientemente imágenes para compartir en redes sociales y metadatos Open Graph de contenido HTML. Esto es particularmente útil para construir vistas previas de enlaces, tarjetas de redes sociales o web scrapers. Podemos usar HTMLRewriter para coincidir selectores CSS con elementos HTML, texto y atributos que queremos procesar.

ts
interface SocialMetadata {
  title?: string;
  description?: string;
  image?: string;
  url?: string;
  siteName?: string;
  type?: string;
}

async function extractSocialMetadata(url: string): Promise<SocialMetadata> {
  const metadata: SocialMetadata = {};
  const response = await fetch(url);

  const rewriter = new HTMLRewriter()
    // Extraer etiquetas meta Open Graph
    .on('meta[property^="og:"]', {
      element(el) {
        const property = el.getAttribute("property");
        const content = el.getAttribute("content");
        if (property && content) {
          // Convertir "og:image" a "image" etc.
          const key = property.replace("og:", "") as keyof SocialMetadata;
          metadata[key] = content;
        }
      },
    })
    // Extraer etiquetas meta Twitter Card como fallback
    .on('meta[name^="twitter:"]', {
      element(el) {
        const name = el.getAttribute("name");
        const content = el.getAttribute("content");
        if (name && content) {
          const key = name.replace("twitter:", "") as keyof SocialMetadata;
          // Solo usar datos de Twitter Card si no tenemos datos OG
          if (!metadata[key]) {
            metadata[key] = content;
          }
        }
      },
    })
    // Fallback a etiquetas meta regulares
    .on('meta[name="description"]', {
      element(el) {
        const content = el.getAttribute("content");
        if (content && !metadata.description) {
          metadata.description = content;
        }
      },
    })
    // Fallback a etiqueta title
    .on("title", {
      text(text) {
        if (!metadata.title) {
          metadata.title = text.text;
        }
      },
    });

  // Procesar la respuesta
  await rewriter.transform(response).blob();

  // Convertir URLs de imágenes relativas a absolutas
  if (metadata.image && !metadata.image.startsWith("http")) {
    try {
      metadata.image = new URL(metadata.image, url).href;
    } catch {
      // Mantener la URL original si falla el análisis
    }
  }

  return metadata;
}
ts
// Ejemplo de uso
const metadata = await extractSocialMetadata("https://bun.com");
console.log(metadata);
// {
//   title: "Bun — Un runtime de JavaScript rápido todo en uno",
//   description: "Empaqueta, transpila, instala y ejecuta proyectos de JavaScript y TypeScript — todo en Bun. Bun es un runtime y kit de herramientas de JavaScript rápido todo en uno diseñado para la velocidad, completo con un empaquetador, ejecutor de pruebas y administrador de paquetes compatible con Node.js.",
//   image: "https://bun.com/share.jpg",
//   type: "website",
//   ...
// }

Bun por www.bunjs.com.cn editar