diff --git a/middleware/index.js b/middleware/index.js index 9eed341a14a3..60919f6bdb50 100644 --- a/middleware/index.js +++ b/middleware/index.js @@ -34,6 +34,7 @@ import helpToDocs from './redirects/help-to-docs.js' import languageCodeRedirects from './redirects/language-code-redirects.js' import handleRedirects from './redirects/handle-redirects.js' import findPage from './find-page.js' +import spotContentFlaws from './spot-content-flaws.js' import blockRobots from './block-robots.js' import archivedEnterpriseVersionsAssets from './archived-enterprise-versions-assets.js' import events from './events.js' @@ -173,6 +174,7 @@ export default function (app) { // *** Config and context for rendering *** app.use(asyncMiddleware(instrument(findPage, './find-page'))) // Must come before archived-enterprise-versions, breadcrumbs, featured-links, products, render-page + app.use(asyncMiddleware(instrument(spotContentFlaws, './spot-content-flaws'))) // Must come after findPage app.use(instrument(blockRobots, './block-robots')) // Check for a dropped connection before proceeding diff --git a/middleware/spot-content-flaws.js b/middleware/spot-content-flaws.js new file mode 100644 index 000000000000..d05ce4c1f6b8 --- /dev/null +++ b/middleware/spot-content-flaws.js @@ -0,0 +1,32 @@ +// This middleware, exclusively in 'development' tries to spot flaws in +// the content you're actively viewing. +// The hopeful assumption is that if you're actively viewing this +// page on localhost, you're actively working on its content. + +import path from 'path' + +import kleur from 'kleur' + +export default async function spotContentFlaws(req, res, next) { + const { page } = req.context + if (process.env.NODE_ENV === 'development' && page) { + const trailingSlashRedirects = (page.redirect_from || []).filter( + (uri) => uri.endsWith('/') && uri.startsWith('/') + ) + if (trailingSlashRedirects.length > 0) { + console.warn( + `The page ${kleur.bold(path.relative(process.cwd(), page.fullPath))} has ${ + trailingSlashRedirects.length + } redirect_from entries that have a trailing slash\n ${kleur.yellow( + trailingSlashRedirects.join('\n ') + )}` + ) + console.log( + "If you're actively working on this page, consider", + kleur.bold('deleting all trailing slashes in redirect_from.\n') + ) + } + } + + return next() +} diff --git a/package-lock.json b/package-lock.json index 4c024ca009ca..2e8f3b9a759e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47,6 +47,7 @@ "imurmurhash": "^0.1.4", "js-cookie": "^3.0.1", "js-yaml": "^4.1.0", + "kleur": "4.1.4", "liquidjs": "^9.22.1", "lodash": "^4.17.21", "lodash-es": "^4.17.21", @@ -13371,10 +13372,9 @@ } }, "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "devOptional": true, + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz", + "integrity": "sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==", "engines": { "node": ">=6" } @@ -17831,6 +17831,15 @@ "node": ">= 6" } }, + "node_modules/prompts/node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "devOptional": true, + "engines": { + "node": ">=6" + } + }, "node_modules/prop-types": { "version": "15.7.2", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", @@ -22247,14 +22256,6 @@ "node": ">=8" } }, - "node_modules/uvu/node_modules/kleur": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz", - "integrity": "sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==", - "engines": { - "node": ">=6" - } - }, "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -33493,10 +33494,9 @@ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" }, "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "devOptional": true + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz", + "integrity": "sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==" }, "language-subtag-registry": { "version": "0.3.21", @@ -36869,6 +36869,14 @@ "requires": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" + }, + "dependencies": { + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "devOptional": true + } } }, "prop-types": { @@ -40276,13 +40284,6 @@ "kleur": "^4.0.3", "sade": "^1.7.3", "totalist": "^2.0.0" - }, - "dependencies": { - "kleur": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz", - "integrity": "sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==" - } } }, "v8-compile-cache": { diff --git a/package.json b/package.json index c9c70c070ef8..c1960a4dcfa7 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "imurmurhash": "^0.1.4", "js-cookie": "^3.0.1", "js-yaml": "^4.1.0", + "kleur": "4.1.4", "liquidjs": "^9.22.1", "lodash": "^4.17.21", "lodash-es": "^4.17.21",