npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@hyperfov/link-previews

v1.0.0-beta

Published

Add a link preview to any hyperlink.

Downloads

8

Readme

Link Preview Web Component

This is the frontend portion of the Hyperfov Link Preview library. It provides a function linkPreview that allows you to add a link preview web component to any a tag:

<html>
  <body>
    <!-- page markup here with some a tags: -->
    <a id="myLink" href="https://example.com">A cool link</a>
    <!-- Insert the link preview script at the end of the body -->
    <script src="https://unpkg.com/@hyperfov/link-previews@latest/dist/index.js"></script>
    <script>
      // now we can call `linkPreview` to add a preview
      linkPreview("#myLink", {
        worker: "https://link-to-worker.workers.dev",
      });
    </script>
  </body>
</html>

Install

Make sure you've set up the worker and have it's url.

Install via NPM

npm i @hyperfov/link-previews
import { linkPreview } from "@hyperfov/link-previews";

Install via a CDN

<script src="https://unpkg.com/@hyperfov/link-previews@latest/dist/index.js"></script>

Initialize

Add the script to the end of your site's body.

Create link previews by passing through a selector, element, or list of elements and configuration props to the global linkPreview constructor:

linkPreview("#myLink", {
  worker: "https://link-to-worker.workers.dev",
});

You can also customize the previews' styling. For example:

<style>
  link-preview {
    --lp-border: 1px dashed rebeccapurple;
    --lp-title-color: rebeccapurple;
  }
</style>

For more on styling and custom templates, see custom previews.

Props

You can configure the preview element by passing through props in the constructor:

linkPreview("#myLink", {
  // props get passed through here
});

Valid props:

worker

The URL of the deployed worker. See the worker's docs for deployment information.

template

The selector of the template element used to render the preview. See custom previews for more on templates. If nothing is passed, a default template is used.

fetch

Should the worker be called to get information for this link? Defaults to true. You may want to set this to false if you're pregenerating a page and don't want to make calls to the worker at runtime.

fetchOnHover

Should the link preview content be fetched when the user hovers on the link? Defaults to true. When set to false, the preview content is fetched immediately when the preview component is initialized.

content

The data passed through to the template's slots. This object can include props such as title, description, href, and image:

linkPreview(elt, {
  content: {
    href: "https://example.com/",
    description: "Some interesting description",
    title: "Example link",
  },
});

Note that passing through data in content will override any data that's returned by the worker.

Any of the keys in content can also be specified on the element with attributes prefixed with lp-:

<a
  href="https://example.com/"
  lp-description="Some interesting description"
  lp-title="Example link"
  >example</a
>

tippy

Props that are passed through to tippy.js, the library used for the preview popups. These can allow you to modify the positioning of the preview and provide options such as an offset, delay, and animation:

linkPreview(elt, {
  tippy: {
    placement: "bottom-start",
    animation: "scale",
    offset: [0, 10],
    delay: 200,
  },
});

Find the full list of props on the tippy docs.

All of the props in tippy can also be specified on the element with attributes prefixed with tippy-data-:

<a
  href="https://example.com/"
  data-tippy-placement="bottom-start"
  data-tippy-animation="scale"
  data-tippy-offset="[0, 10]"
  data-tippy-delay="200"
  >example</a
>

Custom previews

Styling

You can style the basic template with CSS variables set in the link-preview selector:

link-preview {
  --lp-title-color: red;
  --lp-link-color: blue;
}

Variables are in the form --lp-[element]-[css property]. Here's all the variables the template accepts:

| Variable | Default value | | ------------------------------ | --------------------------------------- | | --lp-border | none | | --lp-padding | 0 | | --lp-background | white | | --lp-box-shadow | 0px 5px 15px rgba(101, 101, 110, 0.3) | | --lp-border-radius | 6px | | --lp-max-width | 225px | | --lp-font-family | inherit | | --lp-font-weight | normal | | --lp-link-padding | 0 10px | | --lp-link-color | grey | | --lp-link-border | none | | --lp-link-font-size | 12px | | --lp-link-font-family | inherit | | --lp-link-font-weight | normal | | --lp-title-padding | 0 10px 3px 10px | | --lp-title-color | inherit | | --lp-title-border | none | | --lp-title-font-size | 16px | | --lp-title-font-family | inherit | | --lp-title-font-weight | bold | | --lp-description-padding | 0 10px 3px 10px | | --lp-description-color | inherit | | --lp-description-border | none | | --lp-description-font-size | 16px | | --lp-description-font-family | inherit | | --lp-description-font-weight | normal | | --lp-image-border | none | | --lp-image-border-radius | 3px 3px 0 0 | | --lp-image-object-fit | cover | | --lp-image-object-position | center center | | --lp-image-max-height | 150px |

Custom templates

For instances where the css variables aren't enough, the link preview is completely customizable through an html template with slots. The template that's used by default can be found at src/templates/basic.js.

Add a custom template to your page (the template element is invisible, so this can be anywhere in the document):

<template id="link-preview-template">
  <style>
    .wrapper {
      padding: 20px;
      background-color: lightsalmon;
    }
  </style>
  <div class="wrapper">
    <slot name="lp-title">my title</slot>
    <div><slot name="lp-description">my description</slot></div>
    <div><slot name="lp-href">my url</slot></div>
  </div>
</template>

The styling and markup is totally up to you, though you must ensure styles are either inline or included in a style tag in the template. The link preview component will look for a slots lp-title, lp-description, lp-url, lp-favicon, and lp-image to insert content. Data that doesn't have corresponding slot in the template won't be displayed, so for example if you don't specify an lp-image slot, no image will be inserted.

Once you've created a template, pass its id as an option when instantiating your link previews:

linkPreview("#myLink", {
  worker: "https://link-to-worker.workers.dev",
  template: "#link-preview-template",
});