tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 1b2a87b490abfb80d921ee2f8289bf7f142e391d
parent 7330b35e77a4f57d5a23e948a139716a94104a25
Author: Jon Oliver <jooliver@mozilla.com>
Date:   Thu, 11 Dec 2025 21:01:08 +0000

Bug 1994263: consolidate use-border-radius-tokens stylelint rule with use-design-tokens rule r=mstriemer,frontend-codestyle-reviewers,Standard8,mtigley

- converts use-border-radius-tokens rule to be configured via use-design-tokens rule
- updates tests and documentation for border-radius portion of use-design-tokens rule

Differential Revision: https://phabricator.services.mozilla.com/D274066

Diffstat:
M.stylelintrc.js | 3---
Mbrowser/components/aboutlogins/content/components/confirmation-dialog.css | 2+-
Mbrowser/components/aboutlogins/content/components/generic-dialog.css | 2+-
Mbrowser/components/aboutlogins/content/components/remove-logins-dialog.css | 2+-
Mbrowser/themes/shared/migration/migration-wizard.css | 2+-
Ddocs/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-border-radius-tokens.rst | 99-------------------------------------------------------------------------------
Adocs/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-design-tokens/border-radius.rst | 190+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mstylelint-rollouts.config.js | 70++++++++--------------------------------------------------------------
Mtools/lint/stylelint/stylelint-plugin-mozilla/config.mjs | 40++++++++++++++++++++++++++++++++++++++++
Mtools/lint/stylelint/stylelint-plugin-mozilla/rules/index.mjs | 2--
Dtools/lint/stylelint/stylelint-plugin-mozilla/rules/use-border-radius-tokens.mjs | 131-------------------------------------------------------------------------------
Dtools/lint/stylelint/stylelint-plugin-mozilla/tests/use-border-radius-tokens.tests.mjs | 215-------------------------------------------------------------------------------
Atools/lint/stylelint/stylelint-plugin-mozilla/tests/use-design-tokens.border-radius.tests.mjs | 277+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13 files changed, 519 insertions(+), 516 deletions(-)

diff --git a/.stylelintrc.js b/.stylelintrc.js @@ -275,7 +275,6 @@ module.exports = { "csstools/use-logical": null, "stylelint-plugin-mozilla/no-base-design-tokens": true, "stylelint-plugin-mozilla/use-design-tokens": true, - "stylelint-plugin-mozilla/use-border-radius-tokens": true, "stylelint-plugin-mozilla/use-space-tokens": true, "stylelint-plugin-mozilla/no-non-semantic-token-usage": true, "stylelint-plugin-mozilla/use-size-tokens": true, @@ -427,7 +426,6 @@ module.exports = { ], rules: { "stylelint-plugin-mozilla/use-design-tokens": null, - "stylelint-plugin-mozilla/use-border-radius-tokens": null, "stylelint-plugin-mozilla/use-space-tokens": null, "stylelint-plugin-mozilla/no-non-semantic-token-usage": null, "stylelint-plugin-mozilla/use-size-tokens": null, @@ -441,7 +439,6 @@ module.exports = { ], rules: { "stylelint-plugin-mozilla/use-design-tokens": true, - "stylelint-plugin-mozilla/use-border-radius-tokens": true, "stylelint-plugin-mozilla/use-space-tokens": true, "stylelint-plugin-mozilla/no-non-semantic-token-usage": true, "stylelint-plugin-mozilla/use-size-tokens": true, diff --git a/browser/components/aboutlogins/content/components/confirmation-dialog.css b/browser/components/aboutlogins/content/components/confirmation-dialog.css @@ -25,7 +25,7 @@ color: var(--text-color); box-shadow: var(--logins-dialog-shadow); border: var(--logins-dialog-border); - /* stylelint-disable-next-line stylelint-plugin-mozilla/use-border-radius-tokens */ + /* stylelint-disable-next-line stylelint-plugin-mozilla/use-design-tokens */ border-radius: var(--logins-dialog-border-radius); /* show a border in high contrast mode */ diff --git a/browser/components/aboutlogins/content/components/generic-dialog.css b/browser/components/aboutlogins/content/components/generic-dialog.css @@ -28,7 +28,7 @@ color: var(--text-color); box-shadow: var(--logins-dialog-shadow); border: var(--logins-dialog-border); - /* stylelint-disable-next-line stylelint-plugin-mozilla/use-border-radius-tokens */ + /* stylelint-disable-next-line stylelint-plugin-mozilla/use-design-tokens */ border-radius: var(--logins-dialog-border-radius); /* show a border in high contrast mode */ outline: 1px solid transparent; diff --git a/browser/components/aboutlogins/content/components/remove-logins-dialog.css b/browser/components/aboutlogins/content/components/remove-logins-dialog.css @@ -25,7 +25,7 @@ color: var(--text-color); box-shadow: var(--logins-dialog-shadow); border: var(--logins-dialog-border); - /* stylelint-disable-next-line stylelint-plugin-mozilla/use-border-radius-tokens */ + /* stylelint-disable-next-line stylelint-plugin-mozilla/use-design-tokens */ border-radius: var(--logins-dialog-border-radius); /* show a border in high contrast mode */ outline: 1px solid transparent; diff --git a/browser/themes/shared/migration/migration-wizard.css b/browser/themes/shared/migration/migration-wizard.css @@ -272,7 +272,7 @@ summary { */ .progress-icon-parent { /* stylelint rule disabled to support workaround for Bug 1671784 */ - /* stylelint-disable-next-line stylelint-plugin-mozilla/use-border-radius-tokens */ + /* stylelint-disable-next-line stylelint-plugin-mozilla/use-design-tokens */ border-radius: 0.01px; overflow: hidden; display: flex; diff --git a/docs/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-border-radius-tokens.rst b/docs/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-border-radius-tokens.rst @@ -1,99 +0,0 @@ -======================== -use-border-radius-tokens -======================== - -This rule checks that CSS declarations use border-radius design token variables -instead of hardcoded values. This ensures consistent border-radius usage across -the application and makes it easier to maintain design system consistency. - -Examples of incorrect code for this rule: ------------------------------------------ - -.. code-block:: css - - .custom-button { - border-radius: 0.5rem; - } - -.. code-block:: css - - .card { - border-radius: 8px; - } - -.. code-block:: css - - .avatar { - border-radius: 50%; - } - -Examples of correct token usage for this rule: ----------------------------------------------- - -.. code-block:: css - - .custom-button { - border-radius: var(--border-radius-small); - } - -.. code-block:: css - - .custom-button { - border-radius: var(--border-radius-medium); - } - -.. code-block:: css - - .custom-button { - border-radius: var(--border-radius-circle); - } - -.. code-block:: css - - .custom-button { - border-radius: var(--border-radius-large); - } - -.. code-block:: css - - /* Local CSS variables that reference valid border-radius tokens are allowed */ - :root { - --custom-border-radius: var(--border-radius-small); - } - - .custom-button { - border-radius: var(--custom-border-radius); - } - -.. code-block:: css - - .custom-button { - border-radius: var(--custom-border-radius, --border-radius-small); - } - - -The rule also allows these values non-token values: - -.. code-block:: css - - .no-radius { - border-radius: 0; - } - -.. code-block:: css - - .inherited-radius { - border-radius: inherit; - } - -.. code-block:: css - - .unset-radius { - border-radius: unset; - } - -.. code-block:: css - - .initial-radius { - border-radius: initial; - } diff --git a/docs/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-design-tokens/border-radius.rst b/docs/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-design-tokens/border-radius.rst @@ -0,0 +1,190 @@ +============= +border-radius +============= + +The ``use-design-tokens`` rule checks that CSS ``border-radius`` declarations use +design token variables instead of hardcoded values. This ensures consistent +border-radius usage across the application and makes it easier to maintain design +system consistency. + +Examples of incorrect code for this rule: +----------------------------------------- + +.. code-block:: css + + .custom-button { + border-radius: 0.5rem; + } + +.. code-block:: css + + .card { + border-radius: 8px; + } + +.. code-block:: css + + .avatar { + border-radius: 50%; + } + +Examples of correct token usage for this rule: +---------------------------------------------- + +.. code-block:: css + + .custom-button { + border-radius: var(--border-radius-small); + } + +.. code-block:: css + + .custom-button { + border-radius: var(--border-radius-medium); + } + +.. code-block:: css + + .custom-button { + border-radius: var(--border-radius-circle); + } + +.. code-block:: css + + .custom-button { + border-radius: var(--border-radius-large); + } + +.. code-block:: css + + /* Local CSS variables that reference valid border-radius tokens are allowed */ + :root { + --custom-border-radius: var(--border-radius-small); + } + + .custom-button { + border-radius: var(--custom-border-radius); + } + +.. code-block:: css + + .custom-button { + border-radius: var(--custom-border-radius, --border-radius-small); + } + + +The rule also allows these values non-token values: + +.. code-block:: css + + .no-radius { + border-radius: 0; + } + +.. code-block:: css + + .inherited-radius { + border-radius: inherit; + } + +.. code-block:: css + + .unset-radius { + border-radius: unset; + } + +.. code-block:: css + + .initial-radius { + border-radius: initial; + } + +Autofix functionality +--------------------- + +This rule can automatically fix some violations by replacing raw values with +appropriate design tokens. Examples of autofixable violations: + +.. code-block:: css + + /* Before */ + .a { + border-radius: 50%; + } + + /* After autofix */ + .a { + border-radius: var(--border-radius-circle); + } + +.. code-block:: css + + /* Before */ + .a { + border-radius: 100%; + } + + /* After autofix */ + .a { + border-radius: var(--border-radius-circle); + } + +.. code-block:: css + + /* Before */ + .a { + border-radius: 1000px; + } + + /* After autofix */ + .a { + border-radius: var(--border-radius-circle); + } + +.. code-block:: css + + /* Before */ + .a { + border-radius: 4px; + } + + /* After autofix */ + .a { + border-radius: var(--border-radius-small); + } + +.. code-block:: css + + /* Before */ + .a { + border-radius: 8px; + } + + /* After autofix */ + .a { + border-radius: var(--border-radius-medium); + } + +.. code-block:: css + + /* Before */ + .a { + border-radius: 16px; + } + + /* After autofix */ + .a { + border-radius: var(--border-radius-large); + } + +.. code-block:: css + + /* Before */ + .a { + border-radius: 4px 8px; + } + + /* After autofix */ + .a { + border-radius: var(--border-radius-small) var(--border-radius-medium); + } diff --git a/stylelint-rollouts.config.js b/stylelint-rollouts.config.js @@ -616,68 +616,6 @@ module.exports = [ ], }, { - name: "rollout-use-border-radius-tokens", - rules: { - "stylelint-plugin-mozilla/use-border-radius-tokens": null, - }, - files: [ - "browser/base/content/sanitizeDialog.css", - "browser/components/asrouter/content-src/components/ASRouterAdmin/ASRouterAdmin.scss", - "browser/components/asrouter/content-src/styles/_feature-callout.scss", - "browser/components/contextualidentity/content/usercontext.css", - "browser/components/genai/content/link-preview-card.css", - "browser/components/preferences/dialogs/clearSiteData.css", - "browser/components/profiles/content/profile-card.css", - "browser/components/profiles/content/profiles-theme-card.css", - "browser/components/protections/content/protections.css", - "browser/components/screenshots/overlay/overlay.css", - "browser/components/screenshots/screenshots-buttons.css", - "browser/components/search/test/browser/telemetry/serp.css", - "browser/components/textrecognition/textrecognition.css", - "browser/components/urlbar/tests/browser/dynamicResult0.css", - "browser/components/urlbar/tests/browser/dynamicResult1.css", - "browser/extensions/formautofill/content/manageDialog.css", - "browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/TopicSelection/_TopicSelection.scss", - "browser/themes/linux/browser.css", - "browser/themes/shared/addons/unified-extensions.css", - "browser/themes/shared/customizableui/customizeMode.css", - "browser/themes/shared/customizableui/panelUI-shared.css", - "browser/themes/shared/identity-block/identity-block.css", - "browser/themes/shared/notification-icons.css", - "browser/themes/shared/search/searchbar.css", - "browser/themes/shared/sidebar.css", - "browser/themes/shared/tabbrowser/content-area.css", - "browser/themes/shared/tabbrowser/ctrlTab.css", - "browser/themes/shared/tabbrowser/tabs.css", - "browser/themes/shared/toolbarbuttons.css", - "browser/themes/shared/urlbar-dynamic-results.css", - "browser/themes/shared/urlbar-searchbar.css", - "browser/themes/shared/urlbarView.css", - "browser/themes/windows/downloads/allDownloadsView.css", - "security/manager/pki/resources/content/clientauthask.css", - "toolkit/components/aboutinference/content/aboutInference.css", - "toolkit/components/certviewer/content/components/certificate-section.css", - "toolkit/components/normandy/content/about-studies/about-studies.css", - "toolkit/components/printing/content/printPagination.css", - "toolkit/components/satchel/megalist/content/components/login-line/login-line.css", - "toolkit/content/aboutTelemetry.css", - "toolkit/content/aboutwebrtc/aboutWebrtc.css", - "toolkit/content/widgets/infobar.css", - "toolkit/content/widgets/moz-box-common.css", - "toolkit/content/widgets/moz-visual-picker/moz-visual-picker-item.css", - "toolkit/content/xul.css", - "toolkit/mozapps/extensions/content/aboutaddons.css", - "toolkit/mozapps/extensions/content/shortcuts.css", - "toolkit/themes/mobile/global/aboutMemory.css", - "toolkit/themes/shared/alert.css", - "toolkit/themes/shared/datetimeinputpickers.css", - "toolkit/themes/shared/design-system/storybook/tokens-table.css", - "toolkit/themes/shared/in-content/common-shared.css", - "toolkit/themes/shared/menu.css", - "toolkit/themes/shared/popup.css", - ], - }, - { name: "rollout-no-non-semantic-token-usage", rules: { "stylelint-plugin-mozilla/no-non-semantic-token-usage": null, @@ -766,6 +704,7 @@ module.exports = [ }, files: [ "browser/base/content/aboutDialog.css", + "browser/base/content/sanitizeDialog.css", "browser/components/aboutlogins/content/aboutLogins.css", "browser/components/aboutlogins/content/aboutLoginsImportReport.css", "browser/components/aboutlogins/content/components/confirmation-dialog.css", @@ -785,6 +724,7 @@ module.exports = [ "browser/components/backup/content/password-rules-tooltip.css", "browser/components/backup/content/password-validation-inputs.css", "browser/components/backup/content/turn-on-scheduled-backups.css", + "browser/components/contextualidentity/content/usercontext.css", "browser/components/enterprisepolicies/content/aboutPolicies.css", "browser/components/firefoxview/card-container.css", "browser/components/firefoxview/firefoxview.css", @@ -799,6 +739,7 @@ module.exports = [ "browser/components/genai/content/smart-assist.css", "browser/components/ipprotection/content/ipprotection-content.css", "browser/components/messagepreview/messagepreview.css", + "browser/components/preferences/dialogs/clearSiteData.css", "browser/components/preferences/widgets/nav-notice/nav-notice.css", "browser/components/profiles/content/avatar.css", "browser/components/profiles/content/edit-profile-card.css", @@ -819,6 +760,7 @@ module.exports = [ "browser/components/textrecognition/textrecognition.css", "browser/components/urlbar/tests/browser/dynamicResult0.css", "browser/components/urlbar/tests/browser/dynamicResult1.css", + "browser/extensions/formautofill/content/manageDialog.css", "browser/extensions/formautofill/skin/shared/editAddress.css", "browser/extensions/formautofill/skin/shared/editDialog-shared.css", "browser/extensions/newtab/content-src/components/A11yLinkButton/_A11yLinkButton.scss", @@ -938,6 +880,7 @@ module.exports = [ "devtools/client/aboutdebugging/src/components/sidebar/SidebarRuntimeItem.css", "gfx/layers/layerviewer/tree.css", "netwerk/test/browser/res.css", + "security/manager/pki/resources/content/clientauthask.css", "security/manager/ssl/tests/mochitest/mixedcontent/somestyle.css", "toolkit/components/aboutcheckerboard/content/aboutCheckerboard.css", "toolkit/components/aboutconfig/content/aboutconfig.css", @@ -975,6 +918,8 @@ module.exports = [ "toolkit/content/aboutwebrtc/aboutWebrtc.css", "toolkit/content/tests/widgets/videomask.css", "toolkit/content/widgets/infobar.css", + "toolkit/content/widgets/moz-box-common.css", + "toolkit/content/widgets/moz-box-item/moz-box-item.css", "toolkit/content/widgets/moz-button/moz-button.css", "toolkit/content/widgets/moz-input-common.css", "toolkit/content/widgets/moz-input-text/moz-input-text.css", @@ -983,6 +928,7 @@ module.exports = [ "toolkit/content/widgets/moz-page-nav/moz-page-nav.css", "toolkit/content/widgets/moz-reorderable-list/moz-reorderable-list.css", "toolkit/content/widgets/moz-toggle/moz-toggle.css", + "toolkit/content/widgets/moz-visual-picker/moz-visual-picker-item.css", "toolkit/content/widgets/panel-list/panel-item.css", "toolkit/content/widgets/panel-list/panel-list.css", "toolkit/content/xul.css", diff --git a/tools/lint/stylelint/stylelint-plugin-mozilla/config.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/config.mjs @@ -157,6 +157,18 @@ const BorderWidth = { }; /** @type {PropertyTypeConfig} */ +const BorderRadius = { + allow: ["0"], + tokenTypes: ["border-radius"], + customFixes: { + ...createRawValuesObject(["border-radius"]), + "50%": "var(--border-radius-circle)", + "100%": "var(--border-radius-circle)", + "1000px": "var(--border-radius-circle)", + }, +}; + +/** @type {PropertyTypeConfig} */ const TextColor = { allow: ["currentColor", "white", "black"], tokenTypes: ["text-color"], @@ -278,6 +290,34 @@ export const propertyConfig = { "outline-color": { validTypes: [BorderColor], }, + "border-radius": { + validTypes: [BorderRadius], + shorthand: true, + }, + "border-top-left-radius": { + validTypes: [BorderRadius], + }, + "border-top-right-radius": { + validTypes: [BorderRadius], + }, + "border-bottom-right-radius": { + validTypes: [BorderRadius], + }, + "border-bottom-left-radius": { + validTypes: [BorderRadius], + }, + "border-start-start-radius": { + validTypes: [BorderRadius], + }, + "border-start-end-radius": { + validTypes: [BorderRadius], + }, + "border-end-start-radius": { + validTypes: [BorderRadius], + }, + "border-end-end-radius": { + validTypes: [BorderRadius], + }, color: { validTypes: [TextColor], }, diff --git a/tools/lint/stylelint/stylelint-plugin-mozilla/rules/index.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/rules/index.mjs @@ -6,7 +6,6 @@ import noBaseDesignTokens from "./no-base-design-tokens.mjs"; import noBrowserRefsInToolkit from "./no-browser-refs-in-toolkit.mjs"; -import useBorderRadiusTokens from "./use-border-radius-tokens.mjs"; import useSpaceTokens from "./use-space-tokens.mjs"; import useDesignTokens from "./use-design-tokens.mjs"; import noNonSemanticTokenUsage from "./no-non-semantic-token-usage.mjs"; @@ -15,7 +14,6 @@ import useSizeTokens from "./use-size-tokens.mjs"; export default { "no-base-design-tokens": noBaseDesignTokens, "no-browser-refs-in-toolkit": noBrowserRefsInToolkit, - "use-border-radius-tokens": useBorderRadiusTokens, "use-space-tokens": useSpaceTokens, "use-design-tokens": useDesignTokens, "no-non-semantic-token-usage": noNonSemanticTokenUsage, diff --git a/tools/lint/stylelint/stylelint-plugin-mozilla/rules/use-border-radius-tokens.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/rules/use-border-radius-tokens.mjs @@ -1,131 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * 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, - createRawValuesObject, - isValidTokenUsage, - getLocalCustomProperties, - usesRawFallbackValues, - usesRawShorthandValues, - createAllowList, -} from "../helpers.mjs"; - -const { - utils: { report, ruleMessages, validateOptions }, -} = stylelint; - -const ruleName = namespace("use-border-radius-tokens"); - -const messages = ruleMessages(ruleName, { - rejected: value => - `${value} should be using a border-radius design token. This may be fixable by running the same command again with --fix.`, -}); - -const meta = { - url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/stylelint-plugin-mozilla/rules/use-border-radius-tokens.html", - fixable: true, -}; - -// Gather an array of `['--token-name']` and the ready css `['var(--token-name)']` -const INCLUDE_CATEGORIES = ["border-radius"]; - -const tokenCSS = createTokenNamesArray(INCLUDE_CATEGORIES); - -// Allowed border-color values in CSS -const ALLOW_LIST = createAllowList(["0"]); - -const CSS_PROPERTIES = [ - "border-radius", - "border-top-left-radius", - "border-top-right-radius", - "border-bottom-right-radius", - "border-bottom-left-radius", - "border-start-start-radius", - "border-start-end-radius", - "border-end-start-radius", - "border-end-end-radius", -]; - -// some circular values aren't in our token tree, so we'll append them -const RAW_VALUE_TO_TOKEN_VALUE = { - ...createRawValuesObject(INCLUDE_CATEGORIES), - "50%": "var(--border-radius-circle)", - "100%": "var(--border-radius-circle)", - "1000px": "var(--border-radius-circle)", -}; - -const ruleFunction = primaryOption => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primaryOption, - possible: [true], - }); - - if (!validOptions) { - return; - } - - // Walk declarations once to generate a lookup table of variables. - const cssCustomProperties = getLocalCustomProperties(root); - - // Walk declarations again to detect non-token values. - root.walkDecls(declarations => { - // If the property is not in our list to check, skip it. - if (!CSS_PROPERTIES.includes(declarations.prop)) { - return; - } - - // Otherwise, see if we are using the tokens correctly - if ( - isValidTokenUsage( - declarations.value, - tokenCSS, - cssCustomProperties, - ALLOW_LIST - ) && - !usesRawFallbackValues(declarations.value, RAW_VALUE_TO_TOKEN_VALUE) && - !usesRawShorthandValues( - declarations.value, - tokenCSS, - cssCustomProperties, - ALLOW_LIST - ) - ) { - return; - } - - report({ - message: messages.rejected(declarations.value), - node: declarations, - result, - ruleName, - fix: () => { - const val = valueParser(declarations.value); - let hasFixes = false; - val.walk(node => { - if (node.type == "word") { - const token = RAW_VALUE_TO_TOKEN_VALUE[node.value.trim()]; - if (token) { - hasFixes = true; - node.value = token; - } - } - }); - if (hasFixes) { - declarations.value = val.toString(); - } - }, - }); - }); - }; -}; - -ruleFunction.ruleName = ruleName; -ruleFunction.messages = messages; -ruleFunction.meta = meta; - -export default ruleFunction; diff --git a/tools/lint/stylelint/stylelint-plugin-mozilla/tests/use-border-radius-tokens.tests.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/tests/use-border-radius-tokens.tests.mjs @@ -1,215 +0,0 @@ -/** - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -// Bug 1948378: remove this exception when the eslint import plugin fully -// supports exports in package.json files -// eslint-disable-next-line import/no-unresolved -import { testRule } from "stylelint-test-rule-node"; -import stylelint from "stylelint"; -import useBorderRadiusTokens from "../rules/use-border-radius-tokens.mjs"; - -let plugin = stylelint.createPlugin( - useBorderRadiusTokens.ruleName, - useBorderRadiusTokens -); -let { - ruleName, - rule: { messages }, -} = plugin; - -testRule({ - plugins: [plugin], - ruleName, - config: true, - fix: false, - accept: [ - // allowed token values - { - code: ".a { border-radius: var(--border-radius-small); }", - description: "Using small border-radius token is valid.", - }, - { - code: ".a { border-radius: var(--border-radius-medium); }", - description: "Using medium border-radius token is valid.", - }, - { - code: ".a { border-radius: var(--border-radius-large); }", - description: "Using large border-radius token is valid.", - }, - { - code: ".a { border-radius: var(--border-radius-small) var(--border-radius-medium) var(--border-radius-large) var(--border-radius-circle); }", - description: "Using shorthand with tokens is valid.", - }, - { - code: ".a { border-radius: 0 var(--border-radius-circle); }", - description: "Using shorthand with allowed values and tokens is valid.", - }, - { - code: ".a { border-radius: var(--border-radius-circle); }", - description: "Using circle border-radius token is valid.", - }, - { - code: ":root { --custom-radius: var(--border-radius-circle); }", - description: "Defining a custom variable with a token is valid.", - }, - { - code: ` - :root { --local-radius: var(--border-radius-small); } - .a { border-radius: var(--local-radius); } - `, - description: - "Using a locally declared custom property that resolves to a design token is valid.", - }, - { - code: ".a { border-radius: var(--my-local, var(--border-radius-circle)); }", - description: - "Using a custom property with fallback to design token is valid.", - }, - // allowed primitive/keyword values - { - code: ".a { border-radius: 0; }", - description: "Using 0 is allowed.", - }, - { - code: ".a { border-radius: initial; }", - description: "Using initial is allowed.", - }, - { - code: ".a { border-radius: unset; }", - description: "Using unset is allowed.", - }, - { - code: ".a { border-radius: inherit; }", - description: "Using inherit is allowed.", - }, - ], - reject: [ - { - code: ".a { border-radius: 2px; }", - message: messages.rejected("2px"), - description: "Using a pixel value should use a design token.", - }, - { - code: ".a { border-radius: 1rem; }", - message: messages.rejected("1rem"), - description: "Using a rem value should use a design token.", - }, - { - code: ".a { border-radius: 50%; }", - message: messages.rejected("50%"), - description: "Using a percentage value should use a design token.", - }, - { - code: ".a { border-radius: 2px 4px; }", - message: messages.rejected("2px 4px"), - description: - "Using shorthand with non-token values should use design tokens.", - }, - { - code: ".a { border-radius: 2px var(--border-radius-small); }", - message: messages.rejected("2px var(--border-radius-small)"), - description: - "Using a disallowed value in a shorthand value should use a design token.", - }, - { - code: ".a { border-radius: var(--border-radius-small) 2px; }", - message: messages.rejected("var(--border-radius-small) 2px"), - description: - "Using a disallowed value in a shorthand value should use a design token regardless of order.", - }, - { - code: ".a { border-radius: var(--invalid-radius); }", - message: messages.rejected("var(--invalid-radius)"), - description: "Using a custom variable should use a design token.", - }, - { - code: ".a { border-radius: calc(var(--tab-border-radius) + 4px); }", - message: messages.rejected("calc(var(--tab-border-radius) + 4px)"), - description: - "Using calc() with custom variables should use design tokens.", - }, - { - code: ".a { border-radius: env(-moz-gtk-csd-titlebar-radius); }", - message: messages.rejected("env(-moz-gtk-csd-titlebar-radius)"), - description: "Using env() function should use design tokens.", - }, - ], -}); - -// autofix tests -testRule({ - plugins: [plugin], - ruleName, - config: true, - fix: true, - reject: [ - { - code: ".a { border-radius: 50%; }", - fixed: ".a { border-radius: var(--border-radius-circle); }", - message: messages.rejected("50%"), - description: "Percentage value should be fixed to use design token.", - }, - { - code: ".a { border-radius: 100%; }", - fixed: ".a { border-radius: var(--border-radius-circle); }", - message: messages.rejected("100%"), - description: "100% value should be fixed to use design token.", - }, - { - code: ".a { border-radius: 1000px; }", - fixed: ".a { border-radius: var(--border-radius-circle); }", - message: messages.rejected("1000px"), - description: "1000px value should be fixed to use design token.", - }, - { - code: ".a { border-radius: 9999px; }", - fixed: ".a { border-radius: var(--border-radius-circle); }", - message: messages.rejected("9999px"), - description: "9999px value should be fixed to use design token.", - }, - { - code: ".a { border-radius: 4px; }", - fixed: ".a { border-radius: var(--border-radius-small); }", - message: messages.rejected("4px"), - description: "4px should be fixed to use --border-radius-small token.", - }, - { - code: ".a { border-radius: 8px; }", - fixed: ".a { border-radius: var(--border-radius-medium); }", - message: messages.rejected("8px"), - description: "8px should be fixed to use --border-radius-medium token.", - }, - { - code: ".a { border-radius: 16px; }", - fixed: ".a { border-radius: var(--border-radius-large); }", - message: messages.rejected("16px"), - description: "16px should be fixed to use --border-radius-large token.", - }, - { - code: ".a { border-radius: 4px 8px; }", - fixed: - ".a { border-radius: var(--border-radius-small) var(--border-radius-medium); }", - message: messages.rejected("4px 8px"), - description: "Shorthand values should be fixed to use design tokens.", - }, - { - code: ".a { border-radius: 0 4px 8px; }", - fixed: - ".a { border-radius: 0 var(--border-radius-small) var(--border-radius-medium); }", - message: messages.rejected("0 4px 8px"), - description: - "Mixed shorthand values should be fixed to use design tokens where possible.", - }, - { - code: ".a { border-radius: var(--my-local, 4px); }", - fixed: - ".a { border-radius: var(--my-local, var(--border-radius-small)); }", - message: messages.rejected("var(--my-local, 4px)"), - description: - "custom property with fallback should be fixed to use design token.", - }, - ], -}); diff --git a/tools/lint/stylelint/stylelint-plugin-mozilla/tests/use-design-tokens.border-radius.tests.mjs b/tools/lint/stylelint/stylelint-plugin-mozilla/tests/use-design-tokens.border-radius.tests.mjs @@ -0,0 +1,277 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// Bug 1948378: remove this exception when the eslint import plugin fully +// supports exports in package.json files +// eslint-disable-next-line import/no-unresolved +import { testRule } from "stylelint-test-rule-node"; +import stylelint from "stylelint"; +import useDesignTokens from "../rules/use-design-tokens.mjs"; + +let plugin = stylelint.createPlugin(useDesignTokens.ruleName, useDesignTokens); +let { + ruleName, + rule: { messages }, +} = plugin; + +testRule({ + plugins: [plugin], + ruleName, + config: true, + fix: false, + accept: [ + // allowed token values + { + code: ".a { border-radius: var(--border-radius-small); }", + description: "Using small border-radius token is valid.", + }, + { + code: ".a { border-radius: var(--border-radius-medium); }", + description: "Using medium border-radius token is valid.", + }, + { + code: ".a { border-radius: var(--border-radius-large); }", + description: "Using large border-radius token is valid.", + }, + { + code: ".a { border-radius: var(--border-radius-small) var(--border-radius-medium) var(--border-radius-large) var(--border-radius-circle); }", + description: "Using shorthand with tokens is valid.", + }, + { + code: ".a { border-radius: 0 var(--border-radius-circle); }", + description: "Using shorthand with allowed values and tokens is valid.", + }, + { + code: ".a { border-radius: var(--border-radius-circle); }", + description: "Using circle border-radius token is valid.", + }, + { + code: ":root { --custom-radius: var(--border-radius-circle); }", + description: "Defining a custom variable with a token is valid.", + }, + { + code: ` + :root { --local-radius: var(--border-radius-small); } + .a { border-radius: var(--local-radius); } + `, + description: + "Using a locally declared custom property that resolves to a design token is valid.", + }, + { + code: ".a { border-radius: var(--my-local, var(--border-radius-circle)); }", + description: + "Using a custom property with fallback to design token is valid.", + }, + // allowed primitive/keyword values + { + code: ".a { border-radius: 0; }", + description: "Using 0 is allowed.", + }, + { + code: ".a { border-radius: initial; }", + description: "Using initial is allowed.", + }, + { + code: ".a { border-radius: unset; }", + description: "Using unset is allowed.", + }, + { + code: ".a { border-radius: inherit; }", + description: "Using inherit is allowed.", + }, + ], + reject: [ + { + code: ".a { border-radius: 2px; }", + message: messages.rejected( + "2px", + ["border-radius"], + "var(--border-radius-xsmall)" + ), + description: "Using a pixel value should use a design token.", + }, + { + code: ".a { border-radius: 1rem; }", + message: messages.rejected("1rem", ["border-radius"]), + description: "Using a rem value should use a design token.", + }, + { + code: ".a { border-radius: 50%; }", + message: messages.rejected( + "50%", + ["border-radius"], + "var(--border-radius-circle)" + ), + description: "Using a percentage value should use a design token.", + }, + { + code: ".a { border-radius: 2px 4px; }", + message: messages.rejected( + "2px 4px", + ["border-radius"], + "var(--border-radius-xsmall) var(--border-radius-small)" + ), + description: + "Using shorthand with non-token values should use design tokens.", + }, + { + code: ".a { border-radius: 2px var(--border-radius-small); }", + message: messages.rejected( + "2px var(--border-radius-small)", + ["border-radius"], + "var(--border-radius-xsmall) var(--border-radius-small)" + ), + description: + "Using a disallowed value in a shorthand value should use a design token.", + }, + { + code: ".a { border-radius: var(--border-radius-small) 2px; }", + message: messages.rejected( + "var(--border-radius-small) 2px", + ["border-radius"], + "var(--border-radius-small) var(--border-radius-xsmall)" + ), + description: + "Using a disallowed value in a shorthand value should use a design token regardless of order.", + }, + { + code: ".a { border-radius: var(--invalid-radius); }", + message: messages.rejected("var(--invalid-radius)", ["border-radius"]), + description: "Using a custom variable should use a design token.", + }, + { + code: ".a { border-radius: calc(var(--tab-border-radius) + 4px); }", + message: messages.rejected( + "calc(var(--tab-border-radius) + 4px)", + ["border-radius"], + "calc(var(--tab-border-radius) + var(--border-radius-small))" + ), + description: + "Using calc() with custom variables should use design tokens.", + }, + { + code: ".a { border-radius: env(-moz-gtk-csd-titlebar-radius); }", + message: messages.rejected("env(-moz-gtk-csd-titlebar-radius)", [ + "border-radius", + ]), + description: "Using env() function should use design tokens.", + }, + ], +}); + +testRule({ + plugins: [plugin], + ruleName, + config: true, + fix: true, + reject: [ + { + code: ".a { border-radius: 50%; }", + fixed: ".a { border-radius: var(--border-radius-circle); }", + message: messages.rejected( + "50%", + ["border-radius"], + "var(--border-radius-circle)" + ), + description: "Percentage value should be fixed to use design token.", + }, + { + code: ".a { border-radius: 100%; }", + fixed: ".a { border-radius: var(--border-radius-circle); }", + message: messages.rejected( + "100%", + ["border-radius"], + "var(--border-radius-circle)" + ), + description: "100% value should be fixed to use design token.", + }, + { + code: ".a { border-radius: 1000px; }", + fixed: ".a { border-radius: var(--border-radius-circle); }", + message: messages.rejected( + "1000px", + ["border-radius"], + "var(--border-radius-circle)" + ), + description: "1000px value should be fixed to use design token.", + }, + { + code: ".a { border-radius: 9999px; }", + fixed: ".a { border-radius: var(--border-radius-circle); }", + message: messages.rejected( + "9999px", + ["border-radius"], + "var(--border-radius-circle)" + ), + description: "9999px value should be fixed to use design token.", + }, + { + code: ".a { border-radius: 4px; }", + fixed: ".a { border-radius: var(--border-radius-small); }", + message: messages.rejected( + "4px", + ["border-radius"], + "var(--border-radius-small)" + ), + description: "4px should be fixed to use --border-radius-small token.", + }, + { + code: ".a { border-radius: 8px; }", + fixed: ".a { border-radius: var(--border-radius-medium); }", + message: messages.rejected( + "8px", + ["border-radius"], + "var(--border-radius-medium)" + ), + description: "8px should be fixed to use --border-radius-medium token.", + }, + { + code: ".a { border-radius: 16px; }", + fixed: ".a { border-radius: var(--border-radius-large); }", + message: messages.rejected( + "16px", + ["border-radius"], + "var(--border-radius-large)" + ), + description: "16px should be fixed to use --border-radius-large token.", + }, + { + code: ".a { border-radius: 4px 8px; }", + fixed: + ".a { border-radius: var(--border-radius-small) var(--border-radius-medium); }", + message: messages.rejected( + "4px 8px", + ["border-radius"], + "var(--border-radius-small) var(--border-radius-medium)" + ), + description: "Shorthand values should be fixed to use design tokens.", + }, + { + code: ".a { border-radius: 0 4px 8px; }", + fixed: + ".a { border-radius: 0 var(--border-radius-small) var(--border-radius-medium); }", + message: messages.rejected( + "0 4px 8px", + ["border-radius"], + "0 var(--border-radius-small) var(--border-radius-medium)" + ), + description: + "Mixed shorthand values should be fixed to use design tokens where possible.", + }, + { + code: ".a { border-radius: var(--my-local, 4px); }", + fixed: + ".a { border-radius: var(--my-local, var(--border-radius-small)); }", + message: messages.rejected( + "var(--my-local, 4px)", + ["border-radius"], + "var(--my-local, var(--border-radius-small))" + ), + description: + "custom property with fallback should be fixed to use design token.", + }, + ], +});