OverviewFilesCommitsIssuesDocsReleasesPeers

holepunchto-deps / @holepunchto / keet-link-preview / utils.js

92 lines · javascript ref:
import { userAgent } from 'fast-meta-tags'
import timeoutSignal from 'timeout-abort-signal'

async function getFileBuffer(src, opt = {}) {
  const t = timeoutSignal(opt.signal, opt.timeout)
  try {
    const res = await fetch(src, {
      signal: t.signal,
      headers: {
        Accept: '*/*',
        'User-Agent': opt?.userAgent || userAgent,
      },
    })
    if (!res.ok) return null

    const type = res.headers.get('Content-Type')
    const name = toFilename(src, type)
    const arrayBuffer = await res.arrayBuffer()
    const buffer = new Uint8Array(arrayBuffer)
    return { src, type, name, buffer }
  } catch {
    return null
  } finally {
    t.destroy()
  }
}

function toFilename(url, type) {
  switch (type) {
    case 'image/png':
      return 'preview.png'
    case 'image/jpg':
    case 'image/jpeg':
      return 'preview.jpeg'
    case 'image/gif':
      return 'preview.gif'
  }

  return decodeURIComponent(url?.split('/').pop())
}

export async function getFile(src, opt) {
  if (!src) return null
  return opt?.noBuffer
    ? { src, name: toFilename(src, null), buffer: null }
    : await getFileBuffer(src, opt)
}

export function getDomain(url) {
  try {
    return new URL(url).hostname
  } catch (error) {
    return null
  }
}

export function matchDomain(u1, u2) {
  try {
    const h1 = new URL(u1).hostname
    const h2 = new URL(u2).hostname
    return h1 === h2 || h1.endsWith('.' + h2)
  } catch {
    return false
  }
}

export function htmlToText(html) {
  if (!html) return null

  const decoded = html
    .replace(/ /gi, ' ')
    .replace(/&/gi, '&')
    .replace(/&lt;/gi, '<')
    .replace(/&gt;/gi, '>')
    .replace(/&quot;/gi, '"')
    .replace(/&#39;/g, "'")
    .replace(/&apos;/gi, "'")
    .replace(/&copy;/gi, '©')
    .replace(/&reg;/gi, '®')
    .replace(/&hellip;/gi, '…')
    .replace(/&mdash;/gi, '—')
    .replace(/&ndash;/gi, '–')
    .replace(/<[^>]*?(?:\[[^\]]*\][^>]*?)*>/gs, '')

  return decoded
    .normalize('NFKC')
    .replace(/\[\d+\]/g, '')
    .replace(/\[[a-z]\]/gi, '')
    .replace(/&[a-z]+;|&#\d+;/gi, '')
    .replace(/\s+/g, ' ')
    .trim()
}