2.2.1 • Published 11 days ago

eleventy-plugin-broken-links v2.2.1

Weekly downloads
-
License
MIT
Repository
github
Last release
11 days ago

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():

OptionDefaultAccepted valuesDescription
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-fetchSet the duration of the cache
loggingLevel2Integer 0 (silent) to 3 (all)Set the logging level
excludeUrls['http://localhost*', 'https://localhost*']Array of URL stringsExclude specific URLs or wildcards
excludeInputs[]Array of globs, relative to eleventyConfig.dir.input valueExclude input files / globs
callbacknullnull 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
LevelResult
0Silent
1Only log broken links
2Only log broken and redirect links
3All (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.

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

11 days ago

2.2.0

11 days ago

2.1.0

20 days ago

1.5.5

2 years ago

1.6.3

2 years ago

1.5.4

2 years ago

1.6.2

2 years ago

1.6.1

2 years ago

1.5.2

2 years ago

1.6.0

2 years ago

1.5.1

2 years ago

1.5.0

2 years ago

2.0.3

2 years ago

2.0.2

2 years ago

2.0.1

2 years ago

2.0.0

2 years ago

1.5.7

2 years ago

1.5.6

2 years ago

1.4.2

2 years ago

1.4.1

2 years ago

1.4.0

2 years ago

1.3.3

2 years ago

1.3.2

2 years ago

1.3.1

2 years ago

1.3.0

2 years ago

1.2.1

2 years ago

1.2.0

2 years ago

1.1.1

2 years ago

1.1.0

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago