Skip to content
Open
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
9 changes: 9 additions & 0 deletions docs/rules/no-arbitrary-value.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Examples of **correct** code for this rule:
"config": <string>|<object>,
"skipClassAttribute": <boolean>,
"tags": Array<string>,
"whitelist": Array<string>,
}]
...
```
Expand Down Expand Up @@ -72,6 +73,14 @@ Optional, if you are using tagged templates, you should provide the tags in this

Optional, can be used to support custom attributes

### `whitelist` (default: `[]`)

The `whitelist` is empty by default but you can add custom regular expressions to this array to avoid getting warnings or errors while using arbitrary values for certain tailwind classes.

For example, if we want to whitelist 'text-' classes for pixel values only and all 'h-" classes the `whitelist` options should be set to:

- `['text-\\[\\d*px]', 'h-\\[[^\\]]*]']`

## Further Reading

This rule will not fix the issue for you because it cannot guess the correct class candidate.
9 changes: 8 additions & 1 deletion lib/rules/no-arbitrary-value.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ module.exports = {
items: { type: 'string', minLength: 0 },
uniqueItems: true,
},
whitelist: {
type: 'array',
items: { type: 'string', minLength: 0 },
uniqueItems: true,
},
},
},
],
Expand All @@ -65,6 +70,7 @@ module.exports = {
const tags = getOption(context, 'tags');
const twConfig = getOption(context, 'config');
const classRegex = getOption(context, 'classRegex');
const whitelist = getOption(context, 'whitelist');

const mergedConfig = customConfig.resolve(twConfig);

Expand Down Expand Up @@ -133,7 +139,8 @@ module.exports = {
const forbidden = [];
classNames.forEach((cls, idx) => {
const parsed = groupUtil.parseClassname(cls, [], mergedConfig, idx);
if (/\[.*\]/i.test(parsed.body)) {
const whitelistIdx = groupUtil.getGroupIndex(parsed.body, whitelist, mergedConfig.separator);
if (whitelistIdx < 0 && /\[.*\]/i.test(parsed.body)) {
forbidden.push(parsed.name);
}
});
Expand Down
17 changes: 15 additions & 2 deletions tests/lib/rules/no-arbitrary-value.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,14 +163,27 @@ ruleTester.run("no-arbitrary-value", rule, {
code: `<div className={'min-h-[75dvh]'}>Dynamic viewport units</div>`,
errors: generateErrors(["min-h-[75dvh]"]),
},
...(['myTag', 'myTag.subTag', 'myTag(SomeComponent)'].map(tag => ({
{
code: `
<nav
className={classnames("text-[12px] text-[#ffffff] h-[50px] w-[100px] bg-[red] bg-[#ffff00] m-[5px] min-h-[30px] py-[8px] border-[2px]")}
/>`,
errors: generateErrors("p-[3px]"),
options: [
{
whitelist: ["text-\\[\\d*px]", "bg-\\[[a-zA-Z]+]", "h-\\[[^\\]]*]"],
},
],
errors: generateErrors("text-[#ffffff] w-[100px] bg-[#ffff00] m-[5px] min-h-[30px] py-[8px] border-[2px]"),
},
...["myTag", "myTag.subTag", "myTag(SomeComponent)"].map((tag) => ({
code: `${tag}\`w-[100px]\``,
errors: generateErrors("w-[100px]"),
options: [
{
tags: ["myTag"],
},
],
}))),
})),
],
});