From c0f8f7acd5aaed22cdd3be66b2e36d6e302835ba Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 8 May 2024 23:04:41 +0100 Subject: [PATCH 1/4] feat(#45): make dead link report visibility configurable --- index.d.ts | 3 ++ index.js | 5 +++- src/dead-links.js | 29 ++++++++++++------- .../eleventy.config.js | 3 ++ 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/index.d.ts b/index.d.ts index 80d428e..5456c17 100644 --- a/index.d.ts +++ b/index.d.ts @@ -49,6 +49,9 @@ type EleventyPluginInterlinkOptions = { // slug that you are using. This defaults to a function that returns [UNABLE TO LOCATE EMBED]. unableToLocateEmbedFn?: ErrorRenderFn, + // deadLinkReport is the desired output format of the dead link report, by default its set to 'console' + deadLinkReport?: 'console' | 'json' | 'none', + // resolvingFns is a list of resolving functions. These are invoked by a wikilink containing a `:` character // prefixed by the fn name. The page in this case is the linking page. resolvingFns?: Map Promise>, diff --git a/index.js b/index.js index 8aaf045..6e6bdbd 100644 --- a/index.js +++ b/index.js @@ -18,6 +18,7 @@ module.exports = function (eleventyConfig, options = {}) { layoutKey: 'embedLayout', layoutTemplateLangKey: 'embedLayoutLanguage', resolvingFns: new Map(), + deadLinkReport: 'console', }, options); // TODO: deprecate usage of unableToLocateEmbedFn in preference of using resolving fn @@ -48,7 +49,9 @@ module.exports = function (eleventyConfig, options = {}) { // anything. // TODO: 1.1.0 have this contain more details such as which file(s) are linking (#23) // TODO: 1.1.0 have this clear the interlinker cache so that next time 11ty builds its starting from fresh data! (#24) - eleventyConfig.on('eleventy.after', () => interlinker.deadLinks.report()); + eleventyConfig.on('eleventy.after', () => { + if (opts.deadLinkReport !== 'none') interlinker.deadLinks.report(opts.deadLinkReport) + }); // Teach Markdown-It how to display MediaWiki Links. eleventyConfig.amendLibrary('md', (md) => { diff --git a/src/dead-links.js b/src/dead-links.js index 34e4ebe..d3c36c5 100644 --- a/src/dead-links.js +++ b/src/dead-links.js @@ -25,17 +25,26 @@ module.exports = class DeadLinks { this.gravestones.set(link, names); } - report() { - for (const [link, files] of this.gravestones.entries()) { - console.warn( - chalk.blue('[@photogabble/wikilinks]'), - chalk.yellow('WARNING'), - `${(link.includes('href') ? 'Link' : 'Wikilink')} (${link}) found pointing to to non-existent page in:` - ); - - for (const file of files) { - console.warn(`\t- ${file}`); + /** + * @param {'console'|'json'} format + */ + report(format) { + if (format === 'console') { + for (const [link, files] of this.gravestones.entries()) { + console.warn( + chalk.blue('[@photogabble/wikilinks]'), + chalk.yellow('WARNING'), + `${(link.includes('href') ? 'Link' : 'Wikilink')} (${link}) found pointing to to non-existent page in:` + ); + + for (const file of files) { + console.warn(`\t- ${file}`); + } } + return; } + + const json = JSON.stringify(this.gravestones); + const n =1; } } diff --git a/tests/fixtures/sample-with-hash-in-title/eleventy.config.js b/tests/fixtures/sample-with-hash-in-title/eleventy.config.js index 9b10b5c..fd8d97b 100644 --- a/tests/fixtures/sample-with-hash-in-title/eleventy.config.js +++ b/tests/fixtures/sample-with-hash-in-title/eleventy.config.js @@ -1,6 +1,9 @@ module.exports = function (eleventyConfig) { eleventyConfig.addPlugin( require('../../../index.js'), + { + deadLinkReport: 'none' + } ); return { From 5f68271e8fcff34df3c608d653ac145c7f196f62 Mon Sep 17 00:00:00 2001 From: Simon Date: Thu, 9 May 2024 08:42:00 +0100 Subject: [PATCH 2/4] feat: write .dead-links.json if configured to do so --- src/dead-links.js | 15 ++++++++++++--- tests/eleventy.test.js | 14 +++++++++++++- .../eleventy.config.js | 1 + 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/dead-links.js b/src/dead-links.js index d3c36c5..0d099b5 100644 --- a/src/dead-links.js +++ b/src/dead-links.js @@ -1,6 +1,8 @@ +const path = require('node:path'); const chalk = require("chalk"); -module.exports = class DeadLinks { +const fs = require('node:fs'); +module.exports = class DeadLinks { constructor() { this.gravestones = new Map; this.fileSrc = 'unknown'; @@ -44,7 +46,14 @@ module.exports = class DeadLinks { return; } - const json = JSON.stringify(this.gravestones); - const n =1; + let obj = {}; + for (const [link, files] of this.gravestones.entries()) { + obj[link] = files; + } + + fs.writeFileSync( + path.join(process.env.ELEVENTY_ROOT, '.dead-links.json'), + JSON.stringify(obj) + ); } } diff --git a/tests/eleventy.test.js b/tests/eleventy.test.js index 89798db..547246f 100644 --- a/tests/eleventy.test.js +++ b/tests/eleventy.test.js @@ -1,13 +1,21 @@ const Eleventy = require("@11ty/eleventy"); const {normalize, consoleMockMessages, findResultByUrl, fixturePath} = require('./helpers'); -const test = require("ava"); +const fs = require('node:fs'); const sinon = require("sinon"); +const test = require("ava"); // NOTE: Tests using sinon to mock console.warn need to be run with // `test.serial` so that they don't run at the same time as one another to // avoid the "Attempted to wrap warn which is already wrapped" error. // @see https://stackoverflow.com/a/37900956/1225977 +test.afterEach(() => { + const deadLinksPathname = fixturePath('website-with-custom-resolving-fn/.dead-links.json'); + if (fs.existsSync(deadLinksPathname)) { + fs.rmSync(deadLinksPathname); + } +}) + test("Sample small Website (wikilinks and regular links)", async t => { let elev = new Eleventy(fixturePath('sample-small-website'), fixturePath('sample-small-website/_site'), { configPath: fixturePath('sample-small-website/eleventy.config.js'), @@ -217,10 +225,14 @@ test("Custom resolving functions are invoked", async t => { configPath: fixturePath('website-with-custom-resolving-fn/eleventy.config.js'), }); + t.false(fs.existsSync(fixturePath('website-with-custom-resolving-fn/.dead-links.json'))); + let results = await elev.toJSON(); t.is( normalize(findResultByUrl(results, '/').content), `

These wikilinks use custom resolving functions:

` ); + + t.true(fs.existsSync(fixturePath('website-with-custom-resolving-fn/.dead-links.json'))); }); diff --git a/tests/fixtures/website-with-custom-resolving-fn/eleventy.config.js b/tests/fixtures/website-with-custom-resolving-fn/eleventy.config.js index bef6a17..06f226f 100644 --- a/tests/fixtures/website-with-custom-resolving-fn/eleventy.config.js +++ b/tests/fixtures/website-with-custom-resolving-fn/eleventy.config.js @@ -6,6 +6,7 @@ module.exports = function (eleventyConfig) { ['howdy', (link, page) => `Hello ${link.name}!`], ['issue', (link, page) => `#${link.name}`], ]), + deadLinkReport: 'json', } ); From 92fcf728f6d5124f6685acdb86ce2a231d90dce5 Mon Sep 17 00:00:00 2001 From: Simon Date: Thu, 9 May 2024 08:47:33 +0100 Subject: [PATCH 3/4] doc(#45): document dead link report functionality --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index d770d4c..e037569 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,9 @@ type EleventyPluginInterlinkOptions = { // isn't set then the default 11ty slugify filter is used. slugifyFn?: SlugifyFn, + // deadLinkReport is the desired output format of the dead link report, by default its set to 'console' + deadLinkReport?: 'console' | 'json' | 'none', + // resolvingFns contains functions used for resolving a wikilinks output. // see the Custom Resolving Functions section below resolvingFns?: Map Promise> @@ -195,6 +198,12 @@ You can then display this information in any way you would like, I use the below {% endif %} ``` +### Dead link Report + +The default behaviour of this plugin is to report to the console every broken Wikilink and internal link. This behaviour is configurable via the `deadLinkReport` config option. This option accepts three values: `none`, `console` and `json` with `console` being the default. + +Setting the value to `none` will disable the dead link report while setting it to `json` will silence console output instead writing to `.dead-links.json` within the project root folder. + ### Page lookup logic This plugin will attempt to identify the page being linked using the following steps in order: From f234d335b9aad0565da6825bd4116f4650c4d4de Mon Sep 17 00:00:00 2001 From: Simon Date: Thu, 9 May 2024 08:53:04 +0100 Subject: [PATCH 4/4] doc(#45): update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69c5fa1..614a082 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Make dead link report configurable (#49) - Remove internal dependency upon slugify (#48) - Add support for custom rendering functions (#47) - Add support for referencing files by path (#44)