From 26a16ba8182966dce51cd29033426ec47d108036 Mon Sep 17 00:00:00 2001 From: Caley Woods Date: Wed, 3 Apr 2024 12:28:49 -0500 Subject: [PATCH 1/3] Add the `html_block` rule to the markdown renderer The goal for all links within the guides content is to evaluate them to see whether or not they leave the ".gov" domain and if they do, we want to make sure that the class list of the link has `usa-link--external` applied so that the link gets the external link icon shown when it renders on the page. Most of that work is handled by the `link_open` rendering rule which scans all of the markdown links and then another portion is handled by `html_inline` for intances where the HTML is placed inside the markdown document. The research for issue #348 discovered that when an HTML page is included using the 11ty `include` syntax that neither `link_open` nor `html_inline` parse links within the included HTML file. This commit adds a third renderer rule which scans all chunks of HTML to see if it includes any links that leave the ".gov" domain and then attempts to make sure the `usa-link--external` class is applied. --- .eleventy.js | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/.eleventy.js b/.eleventy.js index 1a7f36f..e920653 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -170,6 +170,52 @@ module.exports = function (config) { return openDefaultRender(tokens, idx, options, env, self) + `${prefixIcon}`; }; + const defaultHtmlBlockRender = markdownLibrary.renderer.rules.html_block || + function(tokens, idx, options, env, self) { + return self.renderToken(tokens, idx, options); + }; + + markdownLibrary.renderer.rules.html_block = (tokens, idx, options, env, self) => { + const token = tokens[idx]; + let content = token.content; + // Capture the class portion of the element if it exists so it can be interacted with later + // https://regexr.com/7udrd + const hrefRE = /|href=\"([^"]*)\"/g; + const htmlIncludesLinks = content.includes('http') && hrefRE.test(token.content); + + if (htmlIncludesLinks) { + const matches = content.match(hrefRE); + + matches.forEach(anchorElement => { + if (!anchorElement.includes('.gov')) { + if (!anchorElement.includes('class=')) { + if (!anchorElement.includes('usa-link--external')) { + // Since no class is present, we can safely just append our classes after the href property + const newUrl = anchorElement + ' class="usa-link usa-link--external"'; + content = content.replace(anchorElement, newUrl); + tokens[idx].content = content; + } + } else { + // Handle URLs with classes already present + const classRE = /class="([^"]*)"/; + const [classString, oldClassList] = anchorElement.match(classRE); + const newClassList = oldClassList + ' usa-link usa-link--external'; + + // If someone uses the class property but doesn't actually put any classes in it, the class list will be empty + if (classString === 'class=""') { + content = content.replace(classString, 'class="usa-link usa-link--external"'); + } else { + content = content.replace(oldClassList, newClassList); + } + tokens[idx].content = content; + } + } + }); + } + + return defaultHtmlBlockRender(tokens, idx, options, env, self); + } + // Also need to add icon links to any html style links const inlineHTMLDefaultRender = markdownLibrary.renderer.rules.html_inline || function(tokens, idx, options, env, self) { From 911cb3e4268903b412bc7d68945c19ce2bc0f428 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 13:50:28 +0000 Subject: [PATCH 2/3] Bump esbuild-sass-plugin from 3.0.0 to 3.2.0 Bumps [esbuild-sass-plugin](https://github.com/glromeo/esbuild-sass-plugin) from 3.0.0 to 3.2.0. - [Release notes](https://github.com/glromeo/esbuild-sass-plugin/releases) - [Commits](https://github.com/glromeo/esbuild-sass-plugin/compare/v3.0.0...v3.2.0) --- updated-dependencies: - dependency-name: esbuild-sass-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 83 ++++++++++++++++++++++++++++++++--------------- package.json | 2 +- 2 files changed, 58 insertions(+), 27 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5ac8e85..b300ff2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@uswds/uswds": "3.8.0", "autoprefixer": "^10.4.19", "esbuild": "^0.20.2", - "esbuild-sass-plugin": "^3.0.0", + "esbuild-sass-plugin": "^3.2.0", "luxon": "^2.3.1", "markdown-it-footnote": "^3.0.3", "netlify-cms": "^2.10.192" @@ -723,7 +723,8 @@ "node_modules/@bufbuild/protobuf": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-1.8.0.tgz", - "integrity": "sha512-qR9FwI8QKIveDnUYutvfzbC21UZJJryYrLuZGjeZ/VGz+vXelUkK+xgkOHsvPEdYEdxtgUUq4313N8QtOehJ1Q==" + "integrity": "sha512-qR9FwI8QKIveDnUYutvfzbC21UZJJryYrLuZGjeZ/VGz+vXelUkK+xgkOHsvPEdYEdxtgUUq4313N8QtOehJ1Q==", + "peer": true }, "node_modules/@colors/colors": { "version": "1.5.0", @@ -2631,7 +2632,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -3306,7 +3306,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, "engines": { "node": ">=8" } @@ -3397,7 +3396,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -3484,7 +3482,8 @@ "node_modules/buffer-builder": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/buffer-builder/-/buffer-builder-0.2.0.tgz", - "integrity": "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==" + "integrity": "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==", + "peer": true }, "node_modules/buffer-crc32": { "version": "0.2.13", @@ -4005,7 +4004,6 @@ "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, "funding": [ { "type": "individual", @@ -5385,15 +5383,16 @@ } }, "node_modules/esbuild-sass-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/esbuild-sass-plugin/-/esbuild-sass-plugin-3.0.0.tgz", - "integrity": "sha512-bwIzYBdI7mK0HghblwqGEYX44Hknvj6EBKXEI8e0hC+Xui5L8oUXFeJ4/PDldxYD++wIPuA6Lr4EAnNCtbv//A==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/esbuild-sass-plugin/-/esbuild-sass-plugin-3.2.0.tgz", + "integrity": "sha512-a+e7rYx4sDHgtKWN2n6/7lH5fgfvJaT6AMHmFhBKZy2ZTSN91X5q12l+DNVYJ8cWViEjJNWEd7k7UVcCg/2S/Q==", "dependencies": { - "resolve": "^1.22.6", - "sass-embedded": "^1.70.0" + "resolve": "^1.22.8", + "sass": "^1.71.1" }, "peerDependencies": { - "esbuild": "^0.20.0" + "esbuild": "^0.20.1", + "sass-embedded": "^1.71.1" } }, "node_modules/escalade": { @@ -6215,7 +6214,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -6474,7 +6472,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -6676,7 +6673,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -7662,7 +7658,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -7757,7 +7752,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -7775,7 +7769,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -7827,7 +7820,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "engines": { "node": ">=0.12.0" } @@ -10875,7 +10867,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -11762,7 +11753,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "engines": { "node": ">=8.6" }, @@ -13340,7 +13330,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -13908,10 +13897,27 @@ "truncate-utf8-bytes": "^1.0.0" } }, + "node_modules/sass": { + "version": "1.75.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.75.0.tgz", + "integrity": "sha512-ShMYi3WkrDWxExyxSZPst4/okE9ts46xZmJDSawJQrnte7M1V9fScVB+uNXOVKRBt0PggHOwoZcn8mYX4trnBw==", + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/sass-embedded": { "version": "1.74.1", "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.74.1.tgz", "integrity": "sha512-VnrsLUfLVuLNq8Zrz6oaYmJ+hK5saaOhuwRC58yAcXYM+CRbS+6us3ab2+PE2a94H2V+cPU4XFvqibfz3C/XSw==", + "peer": true, "dependencies": { "@bufbuild/protobuf": "^1.0.0", "buffer-builder": "^0.2.0", @@ -13954,6 +13960,7 @@ "os": [ "android" ], + "peer": true, "bin": { "sass": "dart-sass/sass" }, @@ -13972,6 +13979,7 @@ "os": [ "android" ], + "peer": true, "bin": { "sass": "dart-sass/sass" }, @@ -13990,6 +13998,7 @@ "os": [ "android" ], + "peer": true, "bin": { "sass": "dart-sass/sass" }, @@ -14008,6 +14017,7 @@ "os": [ "android" ], + "peer": true, "bin": { "sass": "dart-sass/sass" }, @@ -14026,6 +14036,7 @@ "os": [ "darwin" ], + "peer": true, "bin": { "sass": "dart-sass/sass" }, @@ -14044,6 +14055,7 @@ "os": [ "darwin" ], + "peer": true, "bin": { "sass": "dart-sass/sass" }, @@ -14062,6 +14074,7 @@ "os": [ "linux" ], + "peer": true, "bin": { "sass": "dart-sass/sass" }, @@ -14080,6 +14093,7 @@ "os": [ "linux" ], + "peer": true, "bin": { "sass": "dart-sass/sass" }, @@ -14098,6 +14112,7 @@ "os": [ "linux" ], + "peer": true, "bin": { "sass": "dart-sass/sass" }, @@ -14116,6 +14131,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=14.0.0" } @@ -14131,6 +14147,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=14.0.0" } @@ -14146,6 +14163,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=14.0.0" } @@ -14161,6 +14179,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=14.0.0" } @@ -14176,6 +14195,7 @@ "os": [ "linux" ], + "peer": true, "bin": { "sass": "dart-sass/sass" }, @@ -14194,6 +14214,7 @@ "os": [ "win32" ], + "peer": true, "bin": { "sass": "dart-sass/sass.bat" }, @@ -14212,6 +14233,7 @@ "os": [ "win32" ], + "peer": true, "bin": { "sass": "dart-sass/sass.bat" }, @@ -14230,6 +14252,7 @@ "os": [ "win32" ], + "peer": true, "bin": { "sass": "dart-sass/sass.bat" }, @@ -14241,6 +14264,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "peer": true, "engines": { "node": ">=8" } @@ -14248,12 +14272,14 @@ "node_modules/sass-embedded/node_modules/immutable": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz", - "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==" + "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==", + "peer": true }, "node_modules/sass-embedded/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "peer": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -14264,6 +14290,11 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/sass/node_modules/immutable": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz", + "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==" + }, "node_modules/sax-wasm": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/sax-wasm/-/sax-wasm-2.2.3.tgz", @@ -15404,7 +15435,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -16116,7 +16146,8 @@ "node_modules/varint": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==" + "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", + "peer": true }, "node_modules/vary": { "version": "1.1.2", diff --git a/package.json b/package.json index cf1f181..cf17b5e 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "@uswds/uswds": "3.8.0", "autoprefixer": "^10.4.19", "esbuild": "^0.20.2", - "esbuild-sass-plugin": "^3.0.0", + "esbuild-sass-plugin": "^3.2.0", "luxon": "^2.3.1", "markdown-it-footnote": "^3.0.3", "netlify-cms": "^2.10.192" From 15b27736defad356309d74448538f7f43c0db7ac Mon Sep 17 00:00:00 2001 From: Caley Woods Date: Tue, 16 Apr 2024 11:19:34 -0500 Subject: [PATCH 3/3] Add 'f' to the email address for 18F --- _includes/footer.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_includes/footer.html b/_includes/footer.html index 9d6c692..3a4dde8 100644 --- a/_includes/footer.html +++ b/_includes/footer.html @@ -5,7 +5,7 @@

This project is maintained by 18F

Learn more about our Linking Policy

-

Have questions or would like to contact us? Email us at 18F@gsa.gov

+

Have questions or would like to contact us? Email us at 18F@gsa.gov