From b09a512107249a4eb19ef5a37b0bd672266eafdb Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Wed, 1 Mar 2023 01:17:05 +0530 Subject: [PATCH] docs: detect and fix broken links (#16837) * docs: detect and fix broken links * ci: build website before running lint:links * chore: update lint:links script * ci: refactor job * ci: increase memory * ci: fix * chore: use custom script * chore: fix script for windows * chore: fix script for windows * chore: update script * ci: remove unwanted changes * chore: fix script * chore: remove unwanted changes * docs: fix links --- .github/workflows/ci.yml | 6 +++ conf/rule-type-list.json | 4 +- docs/package.json | 7 +++- docs/src/_data/rules.json | 4 +- docs/src/extend/custom-rules-deprecated.md | 2 +- docs/src/extend/custom-rules.md | 4 +- docs/src/use/configure/index.md | 2 +- docs/tools/validate-links.js | 49 ++++++++++++++++++++++ 8 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 docs/tools/validate-links.js diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b630a88f14..5f8b968a550 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,6 +33,12 @@ jobs: run: npm run lint:scss - name: Lint Docs JS Files run: node Makefile lintDocsJS + - name: Build Docs Website + working-directory: docs + run: npm run build + - name: Validate internal links + working-directory: docs + run: npm run lint:links test_on_node: name: Test diff --git a/conf/rule-type-list.json b/conf/rule-type-list.json index 517f8219166..d5823acc898 100644 --- a/conf/rule-type-list.json +++ b/conf/rule-type-list.json @@ -6,12 +6,12 @@ ], "deprecated": { "name": "Deprecated", - "description": "These rules have been deprecated in accordance with the deprecation policy, and replaced by newer rules:", + "description": "These rules have been deprecated in accordance with the deprecation policy, and replaced by newer rules:", "rules": [] }, "removed": { "name": "Removed", - "description": "These rules from older versions of ESLint (before the deprecation policy existed) have been replaced by newer rules:", + "description": "These rules from older versions of ESLint (before the deprecation policy existed) have been replaced by newer rules:", "rules": [ { "removed": "generator-star", "replacedBy": ["generator-star-spacing"] }, { "removed": "global-strict", "replacedBy": ["strict"] }, diff --git a/docs/package.json b/docs/package.json index 6dfed6dfb25..785689e424c 100644 --- a/docs/package.json +++ b/docs/package.json @@ -19,6 +19,7 @@ "start": "npm-run-all build:sass build:postcss --parallel watch:*", "build": "npm-run-all build:sass build:postcss build:eleventy images", "lint:scss": "stylelint \"**/*.{scss,html}\"", + "lint:links": "cross-env NODE_OPTIONS=--max-old-space-size=4096 node tools/validate-links.js", "lint:fix:scss": "npm run lint:scss -- --fix" }, "devDependencies": { @@ -27,15 +28,18 @@ "@11ty/eleventy-navigation": "^0.3.2", "@11ty/eleventy-plugin-rss": "^1.1.1", "@11ty/eleventy-plugin-syntaxhighlight": "^3.1.2", + "@munter/tap-render": "^0.2.0", "@types/markdown-it": "^12.2.3", "algoliasearch": "^4.12.1", "autoprefixer": "^10.4.13", + "cross-env": "^7.0.3", "cssnano": "^5.1.14", "dom-parser": "^0.1.6", "eleventy-plugin-nesting-toc": "^1.3.0", "eleventy-plugin-page-assets": "^0.3.0", "eleventy-plugin-reading-time": "^0.0.1", "github-slugger": "^1.5.0", + "hyperlink": "^5.0.4", "imagemin": "^8.0.1", "imagemin-cli": "^7.0.0", "js-yaml": "^3.14.1", @@ -53,7 +57,8 @@ "stylelint": "^14.13.0", "stylelint-config-html": "^1.1.0", "stylelint-config-standard": "^29.0.0", - "stylelint-config-standard-scss": "^5.0.0" + "stylelint-config-standard-scss": "^5.0.0", + "tap-spot": "^1.1.2" }, "engines": { "node": ">=14.0.0" diff --git a/docs/src/_data/rules.json b/docs/src/_data/rules.json index 5b9d2e21ff3..27280e44935 100644 --- a/docs/src/_data/rules.json +++ b/docs/src/_data/rules.json @@ -1893,7 +1893,7 @@ ], "deprecated": { "name": "Deprecated", - "description": "These rules have been deprecated in accordance with the deprecation policy, and replaced by newer rules:", + "description": "These rules have been deprecated in accordance with the deprecation policy, and replaced by newer rules:", "rules": [ { "name": "callback-return", @@ -2009,7 +2009,7 @@ }, "removed": { "name": "Removed", - "description": "These rules from older versions of ESLint (before the deprecation policy existed) have been replaced by newer rules:", + "description": "These rules from older versions of ESLint (before the deprecation policy existed) have been replaced by newer rules:", "rules": [ { "removed": "generator-star", diff --git a/docs/src/extend/custom-rules-deprecated.md b/docs/src/extend/custom-rules-deprecated.md index 0742233bbab..49faa4f13c7 100644 --- a/docs/src/extend/custom-rules-deprecated.md +++ b/docs/src/extend/custom-rules-deprecated.md @@ -37,7 +37,7 @@ module.exports.schema = []; // no options ## Rule Basics -`schema` (array) specifies the [options](#options-schemas) so ESLint can prevent invalid [rule configurations](../use/configure/rules#configuring-rules) +`schema` (array) specifies the [options](#options-schemas) so ESLint can prevent invalid [rule configurations](../use/configure/rules) `create` (function) returns an object with methods that ESLint calls to "visit" nodes while traversing the abstract syntax tree (AST as defined by [ESTree](https://github.com/estree/estree)) of JavaScript code: diff --git a/docs/src/extend/custom-rules.md b/docs/src/extend/custom-rules.md index 9c57dd1a122..0118757c6a4 100644 --- a/docs/src/extend/custom-rules.md +++ b/docs/src/extend/custom-rules.md @@ -61,7 +61,7 @@ The source file for a rule exports an object with the following properties. **Important:** the `hasSuggestions` property is mandatory for rules that provide suggestions. If this property isn't set to `true`, ESLint will throw an error whenever the rule attempts to produce a suggestion. Omit the `hasSuggestions` property if the rule does not provide suggestions. -* `schema` (array) specifies the [options](#options-schemas) so ESLint can prevent invalid [rule configurations](../use/configure/rules#configuring-rules) +* `schema` (array) specifies the [options](#options-schemas) so ESLint can prevent invalid [rule configurations](../use/configure/rules) * `deprecated` (boolean) indicates whether the rule has been deprecated. You may omit the `deprecated` property if the rule has not been deprecated. @@ -110,7 +110,7 @@ The `context` object contains additional functionality that is helpful for rules * `parserOptions` - the parser options configured for this run (more details [here](../use/configure/language-options#specifying-parser-options)). * `id` - the rule ID. -* `options` - an array of the [configured options](../use/configure/rules#configuring-rules) for this rule. This array does not include the rule severity. For more information, see [here](#contextoptions). +* `options` - an array of the [configured options](../use/configure/rules) for this rule. This array does not include the rule severity. For more information, see [here](#contextoptions). * `settings` - the [shared settings](../use/configure/configuration-files#adding-shared-settings) from configuration. * `parserPath` - the name of the `parser` from configuration. * `parserServices` - an object containing parser-provided services for rules. The default parser does not provide any services. However, if a rule is intended to be used with a custom parser, it could use `parserServices` to access anything provided by that parser. (For example, a TypeScript parser could provide the ability to get the computed type of a given node.) diff --git a/docs/src/use/configure/index.md b/docs/src/use/configure/index.md index 44f84aa4291..e228383c944 100644 --- a/docs/src/use/configure/index.md +++ b/docs/src/use/configure/index.md @@ -42,7 +42,7 @@ All of these options give you fine-grained control over how ESLint treats your c [**Configure Rules**](rules) -* [Configuring Rules](./rules#configuring-rules) +* [Configuring Rules](./rules) * [Disabling Rules](./rules#disabling-rules) [**Configure Plugins**](plugins) diff --git a/docs/tools/validate-links.js b/docs/tools/validate-links.js new file mode 100644 index 00000000000..5c1ca43578d --- /dev/null +++ b/docs/tools/validate-links.js @@ -0,0 +1,49 @@ +const path = require("path"); +const TapRender = require("@munter/tap-render"); +const spot = require("tap-spot"); +const hyperlink = require("hyperlink"); + +const tapRenderInstance = new TapRender(); + +tapRenderInstance.pipe(spot()).pipe(process.stdout); + +const skipPatterns = [ + "https://", + "fragment-redirect", + "migrating-to", + "/blog", + "/play", + "/team", + "/donate", + "/docs/latest", + `src="null"`, +]; + +const skipFilter = (report) => + Object.values(report).some((value) => + skipPatterns.some((pattern) => String(value).includes(pattern)) + ); + +(async () => { + try { + await hyperlink( + { + inputUrls: ["../_site/index.html"], + root: path.resolve(__dirname, "../_site"), + canonicalRoot: "https://eslint.org/docs/head/", + recursive: true, + internalOnly: true, + pretty: true, + concurrency: 25, + skipFilter, + }, + tapRenderInstance + ); + } catch (err) { + console.log(err.stack); + process.exit(1); + } + const results = tapRenderInstance.close(); + + process.exit(results.fail ? 1 : 0); +})();