commit 926822686bfc15ab52741649302c87a09e20fd92
parent 0f6413dbbdc8cf156e9cd95c60161a0f36320214
Author: dwhisman <dwhisman@mozilla.com>
Date: Wed, 19 Nov 2025 20:50:27 +0000
Bug 1988865 - Part 5: Allow black and white keywords for border colors r=frontend-codestyle-reviewers,hjones
Differential Revision: https://phabricator.services.mozilla.com/D271146
Diffstat:
3 files changed, 177 insertions(+), 2 deletions(-)
diff --git a/docs/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-border-color-tokens.rst b/docs/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-border-color-tokens.rst
@@ -88,6 +88,24 @@ The rule also allows these values non-token values:
.. code-block:: css
+ .current-border-color {
+ border-color: currentColor;
+ }
+
+.. code-block:: css
+
+ .white-border-color {
+ border-color: white;
+ }
+
+.. code-block:: css
+
+ .black-border-color {
+ border-color: black;
+ }
+
+.. code-block:: css
+
.inherited-border-color{
border-colors: inherit;
}
@@ -104,9 +122,86 @@ The rule also allows these values non-token values:
border-color: initial;
}
-
.. code-block:: css
.current-border-color {
border-color: currentColor;
}
+
+Autofix functionality
+---------------------
+
+This rule can automatically fix some violations by replacing hex color values with
+appropriate color names. Examples of autofixable violations:
+
+.. code-block:: css
+
+ /* Before */
+ .a {
+ border-color: #fff;
+ }
+
+ /* After autofix */
+ .a {
+ border-color: white;
+ }
+
+.. code-block:: css
+
+ /* Before */
+ .a {
+ border-color: #ffffff;
+ }
+
+ /* After autofix */
+ .a {
+ border-color: white;
+ }
+
+.. code-block:: css
+
+ /* Before */
+ .a {
+ border-color: #FFF;
+ }
+
+ /* After autofix */
+ .a {
+ border-color: white;
+ }
+
+.. code-block:: css
+
+ /* Before */
+ .a {
+ border-color: #FFFFFF;
+ }
+
+ /* After autofix */
+ .a {
+ border-color: white;
+ }
+
+.. code-block:: css
+
+ /* Before */
+ .a {
+ border-color: #000;
+ }
+
+ /* After autofix */
+ .a {
+ border-color: black;
+ }
+
+.. code-block:: css
+
+ /* Before */
+ .a {
+ border-color: #000000;
+ }
+
+ /* After autofix */
+ .a {
+ border-color: black;
+ }
diff --git a/tools/lint/stylelint/stylelint-plugin-mozilla/rules/use-border-color-tokens.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/rules/use-border-color-tokens.mjs
@@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import stylelint from "stylelint";
+import valueParser from "postcss-value-parser";
import {
namespace,
createTokenNamesArray,
@@ -25,7 +26,7 @@ const messages = ruleMessages(ruleName, {
const meta = {
url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-border-color-tokens.html",
- fixable: false,
+ fixable: true,
};
// Gather an array of the ready css `['var(--token-name)']`
@@ -37,6 +38,8 @@ const tokenCSS = createTokenNamesArray(INCLUDE_CATEGORIES);
const ALLOW_LIST = createAllowList([
"transparent",
"currentColor",
+ "white",
+ "black",
"auto",
"normal",
"none",
@@ -74,6 +77,13 @@ const CSS_PROPERTIES = [
...SHORTHAND_CSS_PROPERTIES,
];
+const VIOLATION_AUTOFIX_MAP = {
+ "#fff": "white",
+ "#ffffff": "white",
+ "#000": "black",
+ "#000000": "black",
+};
+
const ruleFunction = primaryOption => {
return (root, result) => {
const validOptions = validateOptions(result, ruleName, {
@@ -113,6 +123,23 @@ const ruleFunction = primaryOption => {
node: declarations,
result,
ruleName,
+ fix: () => {
+ const val = valueParser(declarations.value);
+ let hasFixes = false;
+ val.walk(node => {
+ if (node.type == "word") {
+ const token =
+ VIOLATION_AUTOFIX_MAP[node.value.trim().toLowerCase()];
+ if (token) {
+ hasFixes = true;
+ node.value = token;
+ }
+ }
+ });
+ if (hasFixes) {
+ declarations.value = val.toString();
+ }
+ },
});
});
};
diff --git a/tools/lint/stylelint/stylelint-plugin-mozilla/tests/use-border-color-tokens.tests.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/tests/use-border-color-tokens.tests.mjs
@@ -81,6 +81,14 @@ testRule({
description: "Using currentColor is valid.",
},
{
+ code: ".a { border-color: white; }",
+ description: "Using white is valid.",
+ },
+ {
+ code: ".a { border-color: black; }",
+ description: "Using black is valid.",
+ },
+ {
code: ".a { border: none; }",
description: "Using none is valid.",
},
@@ -243,3 +251,48 @@ testRule({
},
],
});
+
+testRule({
+ plugins: [plugin],
+ ruleName,
+ config: true,
+ fix: true,
+ reject: [
+ {
+ code: ".a { border-color: #fff; }",
+ fixed: ".a { border-color: white; }",
+ message: messages.rejected("#fff"),
+ description: "#fff should be fixed to white",
+ },
+ {
+ code: ".a { border: 1px solid #ffffff; }",
+ fixed: ".a { border: 1px solid white; }",
+ message: messages.rejected("1px solid #ffffff"),
+ description: "#ffffff should be fixed to white",
+ },
+ {
+ code: ".a { outline-color: #FFF; }",
+ fixed: ".a { outline-color: white; }",
+ message: messages.rejected("#FFF"),
+ description: "#FFF should be fixed to white",
+ },
+ {
+ code: ".a { border-left-color: #FFFFFF; }",
+ fixed: ".a { border-left-color: white; }",
+ message: messages.rejected("#FFFFFF"),
+ description: "#FFFFFF should be fixed to white",
+ },
+ {
+ code: ".a { outline: 1px solid #000; }",
+ fixed: ".a { outline: 1px solid black; }",
+ message: messages.rejected("1px solid #000"),
+ description: "#000 should be fixed to black",
+ },
+ {
+ code: ".a { border-block-end-color: #000000; }",
+ fixed: ".a { border-block-end-color: black; }",
+ message: messages.rejected("#000000"),
+ description: "#000000 should be fixed to black",
+ },
+ ],
+});