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

astro-helmet

v1.0.3

Published

A document head manager for astro.

Downloads

243

Readme

astro-helmet

astro-helmet is a utility for managing the document head of Astro projects. It provides an Astro component Helmet which accepts an object of head items and renders them in the document head.

Features

  • Render head items in the document head, specified in object(s).
  • Merge head items from multiple sources.
  • Control the order of head items.
  • Include default charset and viewport meta tags.
  • Order head items with default or specified priority.
  • Meta tag deduplication.
  • Flexible API for adding head items and tag attributes.

Installation

Install astro-helmet using npm:

npm i astro-helmet

Usage

In your Layout component, import astro-helmet and pass an object of headItems to the Helmet component.

---
import Helmet from 'astro-helmet'

const headItems = {
  title: 'My Site Title',
  base: [{ href: 'https://example.com' }],
  meta: [
    { name: 'description', content: 'My site description' },
    { property: 'og:type', content: 'website' }
  ],
  link: [{ rel: 'stylesheet', href: 'styles.css' }],
  style: [{ innerHTML: 'body { color: red; }' }],
  script: [{ innerHTML: 'console.log("Hello, world!")' }],
  noscript: [{ innerHTML: 'Please enable JavaScript' }]
}
---

<!doctype html>
<html lang="en">
  <Helmet {headItems} />
  <body> ... </body>
</html>

Any attribute can be added to a head item. Simply provide the attribute as a key-value pair in the object.

'innerHTML', 'priority', 'tagName' are reserved keys and cannot not be used as attributes.

To add content to a tag, use the innerHTML key. This will render the content inside the tag.

To control the order of head items, use the priority key.

const headItems: HeadItems = {
  // priority 1 will move the script to just below the <title>
  script: [{ src: '/scripts/importantScript.js', priority: 1 }]
}

See applyPriority() in the Options section for more information on controlling the order of head items.

You can also pass an array of headItems to the Helmet component:

---
import Helmet from 'astro-helmet'
import type { HeadItems } from 'astro-helmet'

interface Props {
  headItems: HeadItems
}

const layoutHeadItems: HeadItems = {
  link: [
    { rel: 'icon', type: 'image/svg+xml', href: '/favicon.svg' },
    { rel: 'sitemap', href: '/sitemap-index.xml' }
  ],
  meta: [{ property: 'og:type', content: 'website' }]
}

const { headItems: pageHeadItems } = Astro.props
---

<!doctype html>
<html lang="en">
  <Helmet headItems={[layoutHeadItems, pageHeadItems]} />
  <body> ... </body>
</html>

Then in your page components (or elsewhere), you can define additional head items:

---
import type { HeadItems } from 'astro-helmet'

const headItems: HeadItems = {
  title: 'My Site Title',
  meta: [{ name: 'description', content: 'My site description' }],
  link: [{ rel: 'canonical', href: 'https://example.com' }]
}
---

<Layout {headItems}>
  <main>content</main>
</Layout>

Deduplication

When provided with an array of headItems, astro-helmet will merge the items together.

headItems.meta are deduplicated by name, property and http-equiv. Meta items later in the array replace earlier items.

title and base items are also deduplicated, with the last item in the array taking precedence.

Props

The Helmet component takes two props:

interface Props {
  headItems: HeadItems | HeadItems[]
  options?: {
    omitHeadTags?: boolean
    applyPriority?: (tag: Tag) => Required<Tag>
  }
}

Options

omitHeadTags

By default, astro-helmet will render the opening and closing tags around the head items. If you want it to render only the head items, set omitHeadTags to true.

---
import Helmet from 'astro-helmet'

const headItems = { title: 'My Site Title' }
const options = { omitHeadTags: true }
---

<!doctype html>
<html lang="en">
  <head>
    <Helmet {headItems} {options} />
  </head>
  <body> ... </body>
</html>

applyPriority()

The applyPriority option allows you to customize the priority of head items. It takes a function that accepts a Tag object and returns a Tag object with the priority applied.

By default, items are ordered as follows:

| priority | item | | -------- | --------------------------------------------- | | -4 | <meta charset=""> | | -3 | <meta name="viewport"> | | -2 | <base href=""> | | -1 | <meta http-equiv=""> | | 0 | <title> | | 10 | <link rel="preconnect" /> | | 20 | <script src="" async></script> | | 30 | <style> where innerHTML.includes('@import') | | 40 | <script> | | 50 | <link rel="stylesheet" /> | | 60 | <link rel="preload" /> | | 70 | <script src="" defer></script> | | 80 | <link rel="prefetch" /> | | 90 | remaining <link> | | 100 | remaining <meta> | | 110 | anything else |

This is the default implementation of applyPriority():

function applyPriority(tag: Tag): Required<Tag> {
  if (typeof tag.priority === 'number') return tag as Required<Tag>
  let priority: number
  switch (tag.tagName) {
    case 'title':
      priority = 0
      break

    case 'base':
      priority = -2
      break

    case 'meta':
      if (tag.charset) priority = -4
      else if (tag.name === 'viewport') priority = -3
      else if (tag['http-equiv']) priority = -1
      else priority = 100
      break

    case 'link':
      if (tag.rel === 'preconnect') priority = 10
      else if (tag.rel === 'preload') priority = 60
      else if (tag.rel === 'prefetch') priority = 80
      else if (tag.rel === 'stylesheet') priority = 50
      else priority = 90
      break

    case 'style':
      priority = tag.innerHTML.includes('@import') ? 30 : 51
      break

    case 'script':
      if (tag.async) priority = 20
      else if (tag.defer) priority = 70
      else priority = 40
      break

    default:
      priority = 110
  }
  return { ...tag, priority }
}

Provide a custom applyPriority() function to reorder head items as needed.

Defaults

Default charset and viewport meta tags are included by default.

const DEFAULT_CHARSET = { charset: 'UTF-8' }
const DEFAULT_VIEWPORT = {
  name: 'viewport',
  content: 'width=device-width, initial-scale=1'
}

These can be overridden by providing your own meta items.

Contributing

Contributions are welcome! Please open an issue or submit a pull request with your improvements.

License

This project is licensed under the ISC License.