CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-link-preview-js

JavaScript module to extract and fetch HTTP link information from blocks of text via OpenGraph and meta tag parsing.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

pre-fetched-content.mddocs/

Pre-fetched Content Processing

Parse pre-fetched HTML content to extract link preview metadata without making additional HTTP requests. Ideal for scenarios where content is already available from other sources or when implementing custom fetching logic.

Capabilities

getPreviewFromContent Function

Processes pre-fetched response objects to extract comprehensive link preview metadata using the same parsing logic as getLinkPreview but without making HTTP requests.

/**
 * Skip HTTP fetching and parse pre-fetched content for link preview metadata
 * @param response - Pre-fetched response object with URL, headers, and HTML data
 * @param options - Configuration options for parsing
 * @returns Promise resolving to preview information object
 * @throws Error if invalid response object or parsing fails
 */
function getPreviewFromContent(
  response: IPreFetchedResource,
  options?: ILinkPreviewOptions
): Promise<ILinkPreviewResponse>;

Basic Usage:

import { getPreviewFromContent } from "link-preview-js";

// Pre-fetched response object
const prefetchedResponse = {
  url: "https://www.example.com",
  headers: {
    "content-type": "text/html; charset=utf-8"
  },
  data: `<!DOCTYPE html>
    <html>
      <head>
        <title>Example Site</title>
        <meta property="og:title" content="Example Site">
        <meta property="og:description" content="This is an example website">
        <meta property="og:image" content="https://example.com/image.jpg">
      </head>
      <body>...</body>
    </html>`
};

const preview = await getPreviewFromContent(prefetchedResponse);
console.log(preview.title);       // "Example Site"
console.log(preview.description); // "This is an example website"

Advanced Usage with Custom Fetching:

import { getPreviewFromContent } from "link-preview-js";
import axios from "axios";

// Custom fetch implementation
async function customPreviewExtraction(url: string) {
  try {
    const response = await axios.get(url, {
      headers: {
        "User-Agent": "CustomBot/1.0",
        "Accept": "text/html,application/xhtml+xml"
      },
      timeout: 10000
    });
    
    const prefetchedResource = {
      url: response.config.url || url,
      headers: response.headers,
      data: response.data,
      status: response.status
    };
    
    return await getPreviewFromContent(prefetchedResource, {
      imagesPropertyType: "og"
    });
  } catch (error) {
    throw new Error(`Custom fetch failed: ${error.message}`);
  }
}

const preview = await customPreviewExtraction("https://example.com");

Integration with Existing HTTP Clients:

import { getPreviewFromContent } from "link-preview-js";
import fetch from "node-fetch";

// Using node-fetch
async function fetchAndParse(url: string) {
  const response = await fetch(url, {
    headers: {
      "User-Agent": "MyApp/1.0"
    }
  });
  
  const headers: Record<string, string> = {};
  response.headers.forEach((value, key) => {
    headers[key] = value;
  });
  
  const prefetchedResource = {
    url: response.url,
    headers,
    data: await response.text(),
    status: response.status
  };
  
  return await getPreviewFromContent(prefetchedResource);
}

Required Response Object Structure

The IPreFetchedResource interface defines the required structure for pre-fetched content:

interface IPreFetchedResource {
  /** HTTP response headers */
  headers: Record<string, string>;
  /** HTTP status code (optional) */
  status?: number;
  /** Property type for image meta tags (optional) */
  imagesPropertyType?: string;
  /** Proxy URL used (optional) */
  proxyUrl?: string;
  /** The URL that was fetched */
  url: string;
  /** The HTML content/response body */
  data: string;
}

Minimum Required Fields:

// Minimal valid response object
const minimalResponse = {
  url: "https://example.com",
  headers: {
    "content-type": "text/html"
  },
  data: "<html><head><title>Example</title></head></html>"
};

Complete Response Object:

// Complete response object with all optional fields
const completeResponse = {
  url: "https://example.com/page",
  headers: {
    "content-type": "text/html; charset=utf-8",
    "server": "nginx/1.18.0",
    "last-modified": "Wed, 21 Oct 2015 07:28:00 GMT"
  },
  status: 200,
  data: `<!DOCTYPE html>
    <html>
      <head>
        <title>Complete Example</title>
        <meta property="og:title" content="Complete Example Page">
        <meta property="og:description" content="A complete example with all metadata">
        <meta property="og:image" content="https://example.com/og-image.jpg">
        <meta property="og:video" content="https://example.com/video.mp4">
        <link rel="icon" href="/favicon.ico">
      </head>
      <body>
        <h1>Page Content</h1>
        <p>This is the main content of the page.</p>
      </body>
    </html>`
};

Content Type Processing

The function processes different content types based on the content-type header:

HTML Content (text/html):

  • Parses DOM using Cheerio
  • Extracts OpenGraph meta tags
  • Falls back to standard HTML meta tags
  • Extracts images, videos, and favicons
  • Supports custom response processing via onResponse callback

Image Content (image/*):

  • Returns media type "image"
  • Includes content type and default favicon
  • No HTML parsing required

Audio Content (audio/*):

  • Returns media type "audio"
  • Includes content type and default favicon

Video Content (video/*):

  • Returns media type "video"
  • Includes content type and default favicon

Application Content (application/*):

  • Returns media type "application"
  • Includes content type and default favicon

Unknown Content Types:

  • Attempts HTML parsing as fallback
  • May extract partial metadata if HTML-like content

Error Handling

The function validates input and throws descriptive errors:

// Invalid response object
try {
  await getPreviewFromContent(null);
} catch (error) {
  // "link-preview-js did not receive a valid response object"
}

// Missing URL
try {
  await getPreviewFromContent({
    headers: {},
    data: "<html></html>"
    // Missing required 'url' field
  });
} catch (error) {
  // "link-preview-js did not receive a valid response object"
}

// Parsing errors
try {
  await getPreviewFromContent({
    url: "https://example.com",
    headers: { "content-type": "text/html" },
    data: "invalid html content"
  });
} catch (error) {
  // "link-preview-js could not fetch link information [parsing error details]"
}

Use Cases

Server-Side Rendering:

// Pre-fetch during server-side rendering
export async function getStaticProps({ params }) {
  const response = await fetch(params.url);
  const prefetchedData = {
    url: response.url,
    headers: Object.fromEntries(response.headers.entries()),
    data: await response.text()
  };
  
  const preview = await getPreviewFromContent(prefetchedData);
  
  return {
    props: { preview },
    revalidate: 3600 // Cache for 1 hour
  };
}

Batch Processing:

// Process multiple URLs efficiently
async function batchProcessUrls(urls: string[]) {
  const responses = await Promise.all(
    urls.map(url => fetch(url).then(r => ({
      url: r.url,
      headers: Object.fromEntries(r.headers.entries()),
      data: r.text()
    })))
  );
  
  return Promise.all(
    responses.map(response => getPreviewFromContent(response))
  );
}

Custom Caching:

// Implement custom caching layer
class PreviewCache {
  private cache = new Map();
  
  async getPreview(url: string) {
    if (this.cache.has(url)) {
      const cached = this.cache.get(url);
      return await getPreviewFromContent(cached);
    }
    
    const response = await fetch(url);
    const prefetchedData = {
      url: response.url,
      headers: Object.fromEntries(response.headers.entries()),
      data: await response.text()
    };
    
    this.cache.set(url, prefetchedData);
    return await getPreviewFromContent(prefetchedData);
  }
}

docs

index.md

link-preview.md

pre-fetched-content.md

security-configuration.md

tile.json