@gitlab/eslint-plugin 19.6.1 → 20.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/docs/rules/tailwind.md +38 -0
- package/docs/rules/vue-tailwind.md +45 -0
- package/docs/rules.md +2 -0
- package/lib/configs/base.js +2 -0
- package/lib/configs/typescript.js +1 -0
- package/lib/index.js +5 -3
- package/lib/rules/tailwind.js +30 -0
- package/lib/rules/vue-tailwind.js +32 -0
- package/lib/utils/tailwind-utils.js +35 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
# [20.1.0](https://gitlab.com/gitlab-org/frontend/eslint-plugin/compare/v20.0.0...v20.1.0) (2024-08-28)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* add rules to ensure Tailwind CSS is used properly ([c51533e](https://gitlab.com/gitlab-org/frontend/eslint-plugin/commit/c51533ecfa9f20f76d0b2a3113da7213213658f6))
|
|
7
|
+
|
|
8
|
+
# [20.0.0](https://gitlab.com/gitlab-org/frontend/eslint-plugin/compare/v19.6.1...v20.0.0) (2024-08-13)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* add max-params rule ([110cb10](https://gitlab.com/gitlab-org/frontend/eslint-plugin/commit/110cb1018c8f681251f199a00a8cfda58a32bf05))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### BREAKING CHANGES
|
|
17
|
+
|
|
18
|
+
* The max-params rule is set to error on methods using
|
|
19
|
+
more than 3 parameters.
|
|
20
|
+
|
|
1
21
|
## [19.6.1](https://gitlab.com/gitlab-org/frontend/eslint-plugin/compare/v19.6.0...v19.6.1) (2024-08-06)
|
|
2
22
|
|
|
3
23
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# @gitlab/tailwind
|
|
2
|
+
|
|
3
|
+
This rule lints against string interpolation being used to build CSS utility class
|
|
4
|
+
names as that would prevent Tailwind from parsing those classes and adding them to the bundle.
|
|
5
|
+
|
|
6
|
+
## Rule Details
|
|
7
|
+
|
|
8
|
+
### Examples of **incorrect** code for this rule
|
|
9
|
+
|
|
10
|
+
```js
|
|
11
|
+
// Using interpolation to build a utility in a string literal
|
|
12
|
+
const cssUtilsStringLiteral = 'gl-bg-red-' + variant;
|
|
13
|
+
|
|
14
|
+
// Using interpolation to build a utility in a template literal
|
|
15
|
+
const cssUtilsTemplateLiteral = `gl-border-top gl-bg-red-${color} gl-text-gray-400`;
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Examples of **correct** code for this rule
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
// Utilities declared as a string literal without interpolation
|
|
22
|
+
const cssUtilsStringLiteral = 'gl-bg-red-800';
|
|
23
|
+
|
|
24
|
+
// Utilities declared as a template literal without interpolation
|
|
25
|
+
const cssUtils = `gl-border-top gl-bg-red-800 gl-text-gray-400`;
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Options
|
|
29
|
+
|
|
30
|
+
No options.
|
|
31
|
+
|
|
32
|
+
## Related rules
|
|
33
|
+
|
|
34
|
+
- [vue-tailwind](./vue-tailwind.md)
|
|
35
|
+
|
|
36
|
+
## When Not To Use It
|
|
37
|
+
|
|
38
|
+
If the codebase doesn't leverage Tailwind CSS, keep this rule disabled.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# @gitlab/vue-tailwind
|
|
2
|
+
|
|
3
|
+
This rule enforces the same conventions as [tailwind](./tailwind.md) in Vue templates.
|
|
4
|
+
|
|
5
|
+
## Rule Details
|
|
6
|
+
|
|
7
|
+
### Examples of **incorrect** code for this rule
|
|
8
|
+
|
|
9
|
+
```html
|
|
10
|
+
<!-- Using interpolation to build a utility in a string literal -->
|
|
11
|
+
<template>
|
|
12
|
+
<span :class="'gl-bg-red-' + color"></span>
|
|
13
|
+
</template>
|
|
14
|
+
|
|
15
|
+
<!-- Using interpolation to build a utility in a template literal -->
|
|
16
|
+
<template>
|
|
17
|
+
<span :class="`gl-border-top gl-bg-red-${color} gl-text-gray-400`"></span>
|
|
18
|
+
</template>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Examples of **correct** code for this rule
|
|
22
|
+
|
|
23
|
+
```html
|
|
24
|
+
<!-- Utilities declared as a string literal without interpolation -->
|
|
25
|
+
<template>
|
|
26
|
+
<span class="gl-bg-red-800"></span>
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<!-- Utilities declared as a template literal without interpolation -->
|
|
30
|
+
<template>
|
|
31
|
+
<span :class="`gl-bg-red-800`"></span>
|
|
32
|
+
</template>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Options
|
|
36
|
+
|
|
37
|
+
No options.
|
|
38
|
+
|
|
39
|
+
## Related rules
|
|
40
|
+
|
|
41
|
+
- [tailwind](./tailwind.md)
|
|
42
|
+
|
|
43
|
+
## When Not To Use It
|
|
44
|
+
|
|
45
|
+
If the codebase doesn't leverage Tailwind CSS, keep this rule disabled.
|
package/docs/rules.md
CHANGED
|
@@ -8,6 +8,7 @@ Available rules:
|
|
|
8
8
|
- [no-runtime-template-compiler](./rules/no-runtime-template-compiler.md): Disallow components which rely on a runtime template compiler.
|
|
9
9
|
- [require-i18n-strings](./rules/require-i18n-strings.md): Detect a string which has been hard coded and requires externalization.
|
|
10
10
|
- [require-valid-i18n-helpers](./rules/require-valid-i18n-helpers.md): Enforces valid usage of translation helpers in JavaScript.
|
|
11
|
+
- [tailwind](./rules/tailwind.md): Prevents undesired Tailwind CSS features from being used.
|
|
11
12
|
- [vtu-no-explicit-wrapper-destroy](./rules/vtu-no-explicit-wrapper-destroy.md): Prevents redundant destroy calls and null asignment
|
|
12
13
|
- [vtu-no-wrapper-vm](./rules/vtu-no-wrapper-vm.md): Prevent direct access to `vm` internals for `@vue/test-utils` wrappers.
|
|
13
14
|
- [vue-no-data-toggle](./rules/vue-no-data-toggle.md): Restrict the use of `data-toggle` bootstrap behaviors within Vue templates
|
|
@@ -18,3 +19,4 @@ Available rules:
|
|
|
18
19
|
- [vue-require-required-key](./rules/vue-require-required-key.md): Require the required key to be set
|
|
19
20
|
- [vue-require-valid-i18n-helpers](./rules/vue-require-valid-i18n-helpers.md): Enforces valid usage of translation helpers in Vue templates.
|
|
20
21
|
- [vue-slot-name-casing](./rules/vue-slot-name-casing.md): enforce specific casing for slot naming style in template
|
|
22
|
+
- [vue-tailwind](./rules/vue-tailwind.md): Prevents undesired Tailwind CSS features from being used in Vue templates.
|
package/lib/configs/base.js
CHANGED
package/lib/index.js
CHANGED
|
@@ -7,6 +7,7 @@ module.exports = {
|
|
|
7
7
|
'no-runtime-template-compiler': require('./rules/no-runtime-template-compiler.js'),
|
|
8
8
|
'require-i18n-strings': require('./rules/require-i18n-strings.js'),
|
|
9
9
|
'require-valid-i18n-helpers': require('./rules/require-valid-i18n-helpers.js'),
|
|
10
|
+
tailwind: require('./rules/tailwind.js'),
|
|
10
11
|
'vtu-no-explicit-wrapper-destroy': require('./rules/vtu-no-explicit-wrapper-destroy.js'),
|
|
11
12
|
'vtu-no-wrapper-vm': require('./rules/vtu-no-wrapper-vm.js'),
|
|
12
13
|
'vue-no-data-toggle': require('./rules/vue-no-data-toggle.js'),
|
|
@@ -17,13 +18,14 @@ module.exports = {
|
|
|
17
18
|
'vue-require-required-key': require('./rules/vue-require-required-key.js'),
|
|
18
19
|
'vue-require-valid-i18n-helpers': require('./rules/vue-require-valid-i18n-helpers.js'),
|
|
19
20
|
'vue-slot-name-casing': require('./rules/vue-slot-name-casing.js'),
|
|
21
|
+
'vue-tailwind': require('./rules/vue-tailwind.js'),
|
|
20
22
|
},
|
|
21
23
|
configs: {
|
|
22
|
-
default: require('./configs/default.js'),
|
|
23
|
-
typescript: require('./configs/typescript.js'),
|
|
24
24
|
base: require('./configs/base.js'),
|
|
25
|
-
|
|
25
|
+
default: require('./configs/default.js'),
|
|
26
26
|
i18n: require('./configs/i18n.js'),
|
|
27
27
|
jest: require('./configs/jest.js'),
|
|
28
|
+
typescript: require('./configs/typescript.js'),
|
|
29
|
+
vue: require('./configs/vue.js'),
|
|
28
30
|
},
|
|
29
31
|
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// ------------------------------------------------------------------------------
|
|
2
|
+
// Requirements
|
|
3
|
+
// ------------------------------------------------------------------------------
|
|
4
|
+
const { DOCS_BASE_URL } = require('../constants');
|
|
5
|
+
const { validateInterpolatedUtils } = require('../utils/tailwind-utils');
|
|
6
|
+
|
|
7
|
+
// ------------------------------------------------------------------------------
|
|
8
|
+
// Rule Definition
|
|
9
|
+
// ------------------------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
module.exports = {
|
|
12
|
+
meta: {
|
|
13
|
+
type: 'error',
|
|
14
|
+
docs: {
|
|
15
|
+
description: 'Ensures Tailwind CSS is used according to our internal guidelines.',
|
|
16
|
+
category: 'css',
|
|
17
|
+
url: DOCS_BASE_URL + '/tailwind.md',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
create(context) {
|
|
21
|
+
return {
|
|
22
|
+
BinaryExpression(node) {
|
|
23
|
+
validateInterpolatedUtils(context, node);
|
|
24
|
+
},
|
|
25
|
+
TemplateLiteral(node) {
|
|
26
|
+
validateInterpolatedUtils(context, node);
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
|
|
2
|
+
// ------------------------------------------------------------------------------
|
|
3
|
+
// Requirements
|
|
4
|
+
// ------------------------------------------------------------------------------
|
|
5
|
+
const { DOCS_BASE_URL } = require('../constants');
|
|
6
|
+
const { defineTemplateBodyVisitor } = require('../utils/index');
|
|
7
|
+
const { validateInterpolatedUtils } = require('../utils/tailwind-utils');
|
|
8
|
+
|
|
9
|
+
// ------------------------------------------------------------------------------
|
|
10
|
+
// Rule Definition
|
|
11
|
+
// ------------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
module.exports = {
|
|
14
|
+
meta: {
|
|
15
|
+
type: 'error',
|
|
16
|
+
docs: {
|
|
17
|
+
description: 'Ensures Tailwind CSS is used according to our internal guidelines in Vue templates.',
|
|
18
|
+
category: 'css',
|
|
19
|
+
url: DOCS_BASE_URL + '/vue-tailwind.md',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
create(context) {
|
|
23
|
+
return defineTemplateBodyVisitor(context, {
|
|
24
|
+
BinaryExpression(node) {
|
|
25
|
+
validateInterpolatedUtils(context, node)
|
|
26
|
+
},
|
|
27
|
+
TemplateLiteral(node) {
|
|
28
|
+
validateInterpolatedUtils(context, node)
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
},
|
|
32
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const INTERPOLATION_PATTERN = /gl-[a-z0-9-]*$/i;
|
|
2
|
+
const INTERPOLATED_UTIL_ERROR =
|
|
3
|
+
'You are building a CSS utility class name using string interpolation which is forbidden because Tailwind CSS needs fully qualified names to properly generate the utilities we use.';
|
|
4
|
+
const INTERPOLATED_UTILS_VALIDATORS = {
|
|
5
|
+
BinaryExpression: binaryExpressionHasInterpolatedUtils,
|
|
6
|
+
TemplateLiteral: templateLiteralHasInterpolatedUtils,
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
function binaryExpressionHasInterpolatedUtils(node) {
|
|
10
|
+
return node.operator === '+' && INTERPOLATION_PATTERN.test(node.left.value);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function templateLiteralHasInterpolatedUtils(node) {
|
|
14
|
+
return node.quasis.some((quasi) => {
|
|
15
|
+
return quasi.tail === false && INTERPOLATION_PATTERN.test(quasi.value.raw);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function validateInterpolatedUtils(context, node) {
|
|
20
|
+
if (INTERPOLATED_UTILS_VALIDATORS[node.type] === undefined) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (INTERPOLATED_UTILS_VALIDATORS[node.type](node)) {
|
|
25
|
+
context.report({
|
|
26
|
+
node,
|
|
27
|
+
message: INTERPOLATED_UTIL_ERROR,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = {
|
|
33
|
+
validateInterpolatedUtils,
|
|
34
|
+
INTERPOLATED_UTIL_ERROR,
|
|
35
|
+
};
|