Skip to content
This repository was archived by the owner on Sep 30, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/stale-trainers-heal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/stylelint-polaris': minor
---

Created `polaris/declaration-property-value-disallowed-list` rule to ignore failures in `@font-face` at-rules
3 changes: 2 additions & 1 deletion stylelint-polaris/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ const stylelintPolarisCoverageOptions = {
],
typography: [
{
'declaration-property-value-disallowed-list': {
'polaris/declaration-property-value-disallowed-list': {
'font-weight': [/(\$.*|[0-9]+)/],
},
'declaration-property-unit-disallowed-list': [
Expand Down Expand Up @@ -487,6 +487,7 @@ module.exports = {
'./plugins/at-rule-disallowed-list',
'./plugins/custom-property-allowed-list',
'./plugins/media-query-allowed-list',
'./plugins/declaration-property-value-disallowed-list',
],
rules: {
'polaris/coverage': stylelintPolarisCoverageOptions,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
const stylelint = require('stylelint');

const {
isRegExp,
isString,
validateObjectWithArrayProps,
} = require('../../utils');

const ruleName = 'polaris/declaration-property-value-disallowed-list';

/**
* @typedef {{
* [property: string]: string | RegExp | (string | RegExp)[]
* }} PrimaryOptions
*/

/**
* Wrapper for the Stylelint `declaration-property-value-disallowed-list` rule
* that ignores failures in `@font-face` at-rules.
*/
const {rule} = stylelint.createPlugin(
ruleName,
/** @param {PrimaryOptions} primary */
(primary) => {
return (root, result) => {
const validOptions = stylelint.utils.validateOptions(result, ruleName, {
actual: primary,
possible: [validateObjectWithArrayProps(isString, isRegExp)],
});

if (!validOptions) return;

stylelint.utils.checkAgainstRule(
{
ruleName: 'declaration-property-value-disallowed-list',
ruleSettings: primary,
root,
},
(warning) => {
if (
warning.node.type === 'decl' &&
warning.node.parent.type === 'atrule' &&
warning.node.parent.name === 'font-face'
) {
return;
}

stylelint.utils.report({
ruleName,
result,
node: warning.node,
message: warning.text,
});
},
);
};
},
);

module.exports = {
rule,
ruleName,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const {ruleName} = require('.');

const config = {
'font-weight': [/(\$.*|[0-9]+)/],
};

testRule({
ruleName,
plugins: [__dirname],
config,
customSyntax: 'postcss-scss',
accept: [
{
code: '@font-face { font-weight: 400; }',
description: '@font-face descriptors are ignored',
},
],

reject: [
{
code: '.class { font-weight: 400; }',
description: 'Not using a Polaris custom property',
message:
'Unexpected value "400" for property "font-weight" (declaration-property-value-disallowed-list)',
},
],
});
29 changes: 29 additions & 0 deletions stylelint-polaris/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,34 @@ function isString(value) {
return typeof value === 'string' || value instanceof String;
}

/**
* Check whether the variable is an object and all its properties are one or more values
* that satisfy the specified validator(s):
*
* @example
* ignoreProperties = {
* value1: ["item11", "item12", "item13"],
* value2: "item2",
* };
* validateObjectWithArrayProps(isString)(ignoreProperties);
* //=> true
*
* @typedef {(value: unknown) => boolean} Validator
* @param {...Validator} validators
* @returns {Validator}
*/
function validateObjectWithArrayProps(...validators) {
return (value) => {
if (!isPlainObject(value)) {
return false;
}

return Object.values(value)
.flat()
.every((item) => validators.some((validator) => validator(item)));
};
}

/**
* Returns the arguments expected by Stylelint rules that support functional custom messages
* @param {string} ruleName The category's default message
Expand Down Expand Up @@ -259,6 +287,7 @@ module.exports.isPlainObject = isPlainObject;
module.exports.isRegExp = isRegExp;
module.exports.isScssInterpolation = isScssInterpolation;
module.exports.isString = isString;
module.exports.validateObjectWithArrayProps = validateObjectWithArrayProps;
module.exports.matchesStringOrRegExp = matchesStringOrRegExp;
module.exports.scssInterpolationExpression = scssInterpolationExpression;
module.exports.scssInterpolationRegExp = scssInterpolationRegExp;
Expand Down