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

ilicon

v1.0.1

Published

A small package for fetching site favicons & nicely displaying them inline.

Downloads

3

Readme

iLicon

A small package for fetching site favicons & nicely displaying them inline.

Quick Demo

An embedded github gist, containing some anchor tags:

iLicon no call demo

After calling iLicon with 0 config on the same page:

iLicon call demo

Table of Contents

Features

Automatically fetches favicons for links and displays them inline. With plenty of configuration options and some potential future features.

Installation

iLicon installation should hopefully be pretty straight forward, but if you run into any issues let me know.

Node

For usage in bundlers, note that iLicon is currently client side only, more info below.

# npm
npm install ilicon

# yarn
yarn add ilicon

# pnpm
pnpm add ilicon

CDN

<script src="unpkg/jsdelivr link once published"></script>

Usage

The automatic, no-config version of iLicon is pretty simple, just import it and call it with no arguments. This will:

  • Find all links on the page
  • Insert a small favicon of the link in the href before the text of each anchor tag
import { iLicon } from 'ilicon';

...

// Somewhere browser-side:
iLicon({
  // Options
});

Options

NOTE: All options are optional!

| Option | Type | Default | Description | | -------------------- | ------------------------------------ | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | root | HTMLElement | document.body | The element to start traversal from. By default iLicon will search the whole document, but if that's not needed you can set the starting element, from which iLicon will search from, including all descendants. | | skipIDs | string[] | undefined | An array of strings representing element IDs to skip checking links for. Skipping an element will also skip all descending elements, so this will likely dramatically improve performance. | | skipClasses | string[] | undefined | Similar to the above skipIDs this is an array of strings representing element classes to skip checking links for. Skipping an element will also skip all descending elements, so this will likely dramatically improve performance. | | injectiLiconStyles | boolean | true | If true will call a funtion injecting a <style> tag with about ~10 lines into the page's <head> if it doesn't already exist. This will not create multiple style tags if called more than once. See default styles & classes below. | | wrapperClass | string | ilicon_wrapper | Class applied to the wrapping <a> tag, used for basic alignment. | | imgClass | string | ilicon_img | Class applied to the generated <img> tag, used for sizing & basic alignment. | | setIcons | { domain: string, icon: string }[] | undefined | An array of objects containing the domain name (ex: google.com) and the specified icon to use for that domain (ex: /some_icon.png or .ico or base64) instead of using duckduckgo's supplied favicon. | | position | 'start' \| 'end' | 'start' | Decides whether the favicon is inserted before or after the link text. | | transformer | Function | defaultTransformer | The transformer function, expanded below is what every found anchor element is passed to. This is what takes the anchor tag on the page and spits out the version with a favicon. | | target | string[] | undefined | Experimental. Instead of the default behavior giving iLicon a list of links via the target parameter will return the duckduckgo favicon links for all given URLs. |

Default Styles

.ilicon_wrapper {
  display: inline-flex;
  align-items: center;
  height: 1cqmax;
}
.ilicon_img {
  width: 100%;
  height: 100%;
  margin: 0 0.25rem;
}

Transformer

This is the current default transformer:

function defaultTransformer(
  element: HTMLElement,
  url: string,
  pos = 'start',
  wrapperClass = 'ilicon_wrapper',
  imgClass = 'ilicon_img'
) {
  const isAnchor = element.nodeName === 'A';
  if (isAnchor) {
    element.classList.add(wrapperClass);
    const img = document.createElement('img');
    img.classList.add(imgClass);
    img.src = url;
    if (pos === 'start') {
      element.insertAdjacentElement('afterbegin', img);
    } else {
      element.insertAdjacentElement('beforeend', img);
    }
  }
}

Breakdown:

  • element is the current anchor tag we're working with
  • url is the url of the favicon to use (favicons are obtained before transforming anchor tags)
  • pos is the position of the favicon relative to the anchor tag's text, either 'start' or 'end' for before or after respectively
  • wrapperClass is the class applied to the wrapping <a> tag, used for basic alignment
  • imgClass is the class applied to the generated <img> tag, used for sizing & basic alignment
  • isAnchor is a boolean representing whether the current element is an anchor tag or not
    • This is just a quick check to make sure we're working with an anchor tag, and later on will be used to work with non-anchor tags

If you want to use your own transformer, you can pass it into iLicon via the transformer option. It will be called with the same arguments as the default transformer, and you can use the default transformer as a reference for how to write your own. Ex:

iLicon({
  transformer: (element, url, pos, wrapperClass, imgClass) => {
    // Do something with the element
  },
});

Contributing

I've not managed an open-source project before, so I'm not sure what the best way to go about this is. But if you have any suggestions or want to contribute, feel free to open an issue or PR and I'll take a look!

Future considerations / Potential features

  • [ ] Tests
    • Currently just been testing in a browser with the dist but some more formal and automated tests would be nice
  • [ ] Add support for links within non anchor tags
  • [ ] Add support for links within anchor tags that don't have an href attribute
  • [ ] Add support for links within anchor tags that have an href attribute but no value?
  • [ ] Fix the cors issue and add an option to 'check' icons before displaying them & fallback to a default icon if they don't exist
  • [ ] Async version that does check for the default bad icon from ddg and will swap to google if it doesn't exist
  • [ ] Mini version that's the same as normal but won't grab all links, instead will just take an element and link and act on that
    • [ ] This would also cover SSR if I have it just return the resulting element
  • [ ] Importable css instead of injected
  • [ ] Support relative links