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

eleventy-plugin-broken-links

v2.2.1

Published

An Eleventy plugin to check for broken external links

Downloads

549

Readme

eleventy-plugin-broken-links

npm License: MIT Codecov

Table of contents


Overview

This is an 11ty plugin to check for broken external links after a build.

Currently it only checks external links, but checking internal links might be added at some point.

Features

  • caching using eleventy-fetch
  • excluding URLs
  • control of level of logging
  • warn or error on broken, redirected or forbidden links
  • exclude certain URLs or wildcards
  • exclude certain input files or globs

Dependencies

Under the hood, the plugin uses:

  • node-html-parser to parse build output and gather links
  • eleventy-fetch to cache results
  • minimatch to handle globbing for excluded input files
  • kleur for log coloring / formatting
  • valid-url to check if it's a valid uri

Usage

1. Install the plugin

NPM:

npm i -D eleventy-plugin-broken-links

Yarn:

yarn add -D eleventy-plugin-broken-links

2. Add plugin to .eleventy.js config

const brokenLinksPlugin = require("eleventy-plugin-broken-links");

module.exports = (eleventyConfig) => {
  eleventyConfig.addPlugin(brokenLinksPlugin);
  // ... the rest of your config
};

3. Add .cache to .gitignore

See this privacy notice in the eleventy-fetch docs about why we should ignore the .cache directory. Unless you really know what you're doing, it's probably a good idea.

.cache/
# ... the rest of your `.gitignore`

(4. Set options)

There are currently 7 possible keys to the optional options object passed with eleventyConfig.addPlugin():

| Option | Default | Accepted values | Description | | ---------------------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------ | | forbidden| "warn" | "warn", "error" | Whether to warn or throw an error | | broken | "warn" | "warn", "error" | (same as above) | | redirect | "warn" | "warn", "error" | (same as above) | | cacheDuration | "1d" | any value accepted by eleventy-fetch | Set the duration of the cache | | loggingLevel | 2 | Integer 0 (silent) to 3 (all) | Set the logging level | | excludeUrls | ['http://localhost*', 'https://localhost*'] | Array of URL strings | Exclude specific URLs or wildcards | | excludeInputs | [] | Array of globs, relative to eleventyConfig.dir.input value | Exclude input files / globs | | callback | null | null or a function with signature (brokenLinks, redirectLinks) => {} | Custom callback after checking links |

Here's an example using all options, with the defaults:

const brokenLinksPlugin = require("eleventy-plugin-broken-links");

module.exports = (eleventyConfig) => {
  // ... the rest of your config
  eleventyConfig.addPlugin(brokenLinksPlugin, {
    forbidden: "warn",
    redirect: "warn",
    broken: "warn",
    cacheDuration: "1d",
    loggingLevel: 2,
    excludeUrls: [],
    excludeInputs: [],
    callback: null,
  });
};

NOTE: If the broken, redirect or forbidden options are set to error, your build will not be successful if there are broken/redirected links!


Options

broken, redirect and forbidden

  • Default: "warn"
  • Accepted: "warn" or "error"

Whether to warn or error if broken, redirect or forbidden links are found. If error, builds will not succeed if any are found.

cacheDuration

  • Default: "1d"
  • Accepted: Anything accepted by eleventy-fetch plugin

Sets the cache duration for checking URL status codes. See the eleventy-fetch plugin docs for more info.

loggingLevel

  • Default: 2
  • Accepted: Integer 0 to 3

| Level | Result | | ----- | ---------------------------------- | | 0 | Silent | | 1 | Only log broken links | | 2 | Only log broken and redirect links | | 3 | All (verbose) |

excludeUrls

  • Default: ['http://localhost*', 'https://localhost*'] (new in 2.0.0)
  • Accepted: Array of URL strings

You can exclude specific URLs by specifying their fully-qualified uri:

excludeUrls: ["https://example.com"];

But you can also use a wildcard (*) to exclude domains or sub-paths. Examples:

"https://example.com"; // excludes only the root URL,
// but sub-paths will be include,
// e.g. 'https://example.com/about'

"https://example.com/about"; // excludes only '/about', but root and other
// pages are included

"https://example.com/about/*"; // excludes any path nested under 'about',
// but includes 'about'

"https://example.com/about*"; // excludes any sub-path that begins
// with `about`, INCLUDING all nested paths

"https://example.com/*"; // excludes all paths, but includes the root

"https://example.com*"; // excludes the root and all paths

Note that the URLs specified need to be fully-qualified, so sub-domains need to be explicitly indicated.

excludeInputs

  • Default: []
  • Accepted: Array of files or globs, relative to dir.input

You can exclude specific input files by providing an array of files or globs.

Please note:

  • All files and globs are relative to the config dir.input value
  • Leading "dot-slash" (./) is optional, and is stripped from the input filenames and excludeInputs values when normalized before processing

To illustrate these points:

// - `dir.input` not set in config (`undefined`)
["index.md"]["./index.md"][ // exclude only ./index.md // identical to above
  // - `dir.input` = "src":
  "index.md"
]; // exclude ./src/index.md

Globbing is handled by minimatch under the hood. Some examples:

// Some globbing examples:
["**/index.md"]["**/*.md"]["notes/**"]["**/./*.md"]["**/+(foo|bar).md"]; // exclude all index.md files recursively // exclude all .md files recursively // exclude all files recursively in 'notes' // exclude all .md files in subdirectories only // exclude all files named "foo.md" or "bar.md"

callback

  • Default: null
  • Accepted: null or a function with signature (brokenLinks, redirectLinks, forbiddenLinks) => {}

Custom callback for handling broken, redirect or forbidden links after checking and logging results (and before throwing an error, if option is set). The three arguments, brokenLinks, redirectLinks and forbiddenLinks are arrays of instances of the ExternalLink class, which has the following methods and properties:

  • url property
  • getHttpStatusCode(), which returns the HTTP status code
  • getPages() which returns an array of Eleventy inputPath filenames
  • getLinkCount(), which returns the number of times the link is used in the site's pages

This allows for integration with third-party services, webhooks, etc. Here's a basic example:

// your project's .eleventy.js:
const thirdPartyService = require("service");
const brokenLinksPlugin = require("eleventy-plugin-broken-links");

module.exports = (eleventyConfig) => {
  eleventyConfig.addPlugin(brokenLinksPlugin, {
    callback: (brokenLinks, redirectLinks) => {
      thirdPartyService.post({
        msg: `Your eleventy build had broken links! Links: ${brokenLinks.map(link => link.url).join(", ")}`,
      });
    },
  });
};

Roadmap / Contributing

I don't have a specific roadmap or timeline for this project, but here is a general idea of what the next steps are. If you would like to contribute, please feel free to file an issue or feature request, or send a PR.

  • [x] cache results (added in v1.1.0)
  • [x] allow control over logging (added in v1.3.0)
  • [x] add option to exclude certain urls (added in v1.4.0)
  • [x] add option to exclude certain input files (added in v1.5.0)
  • [x] add debugging using debug to hook into the DEBUG=Eleventy* workflow (Added in v2.0.0)
  • [ ] check internal links