@gitlab/eslint-plugin 20.2.1 → 20.4.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 CHANGED
@@ -1,3 +1,17 @@
1
+ # [20.4.0](https://gitlab.com/gitlab-org/frontend/eslint-plugin/compare/v20.3.0...v20.4.0) (2024-10-10)
2
+
3
+
4
+ ### Features
5
+
6
+ * **Tailwind:** split up Tailwind rules into separate rules ([e581cee](https://gitlab.com/gitlab-org/frontend/eslint-plugin/commit/e581ceede5a4637deab52a204555be4ea43724b4))
7
+
8
+ # [20.3.0](https://gitlab.com/gitlab-org/frontend/eslint-plugin/compare/v20.2.1...v20.3.0) (2024-10-02)
9
+
10
+
11
+ ### Features
12
+
13
+ * **tailwind:** add check for max-width CSS utils ([ec8026a](https://gitlab.com/gitlab-org/frontend/eslint-plugin/commit/ec8026a4bf1961b90808cdfc7984640ab16fdc40))
14
+
1
15
  ## [20.2.1](https://gitlab.com/gitlab-org/frontend/eslint-plugin/compare/v20.2.0...v20.2.1) (2024-09-06)
2
16
 
3
17
 
@@ -1,4 +1,4 @@
1
- # @gitlab/tailwind
1
+ # @gitlab/tailwind-no-interpolation
2
2
 
3
3
  This rule lints against string interpolation being used to build CSS utility class
4
4
  names as that would prevent Tailwind from parsing those classes and adding them to the bundle.
@@ -31,7 +31,7 @@ No options.
31
31
 
32
32
  ## Related rules
33
33
 
34
- - [vue-tailwind](./vue-tailwind.md)
34
+ - [vue-tailwind-no-interpolation](./vue-tailwind-no-interpolation.md)
35
35
 
36
36
  ## When Not To Use It
37
37
 
@@ -0,0 +1,30 @@
1
+ # @gitlab/tailwind-no-max-width-media-queries
2
+
3
+ This rule lints against using max-width media query Tailwind classes.
4
+ Min-width media query Tailwind classes should be used instead.
5
+
6
+ ## Rule Details
7
+
8
+ ### Examples of **incorrect** code for this rule
9
+
10
+ ```js
11
+ const cssClasses = ['gl-mt-5', 'max-md:gl-mt-3'];
12
+ ```
13
+
14
+ ### Examples of **correct** code for this rule
15
+
16
+ ```js
17
+ const cssClasses = ['gl-mt-3', 'md:gl-mt-5'];
18
+ ```
19
+
20
+ ## Options
21
+
22
+ No options.
23
+
24
+ ## Related rules
25
+
26
+ - [vue-tailwind-no-max-width-media-queries](./vue-tailwind-no-max-width-media-queries.md)
27
+
28
+ ## When Not To Use It
29
+
30
+ If the codebase doesn't leverage Tailwind CSS, keep this rule disabled.
@@ -1,6 +1,6 @@
1
- # @gitlab/vue-tailwind
1
+ # @gitlab/vue-tailwind-no-interpolation
2
2
 
3
- This rule enforces the same conventions as [tailwind](./tailwind.md) in Vue templates.
3
+ This rule enforces the same conventions as [tailwind-no-interpolation](./tailwind-no-interpolation.md) in Vue templates.
4
4
 
5
5
  ## Rule Details
6
6
 
@@ -38,7 +38,7 @@ No options.
38
38
 
39
39
  ## Related rules
40
40
 
41
- - [tailwind](./tailwind.md)
41
+ - [tailwind-no-interpolation](./tailwind-no-interpolation.md)
42
42
 
43
43
  ## When Not To Use It
44
44
 
@@ -0,0 +1,33 @@
1
+ # @gitlab/vue-tailwind-no-max-width-media-queries
2
+
3
+ This rule enforces the same conventions as [tailwind-no-max-width-media-queries](./tailwind-no-max-width-media-queries.md) in Vue templates.
4
+
5
+ ## Rule Details
6
+
7
+ ### Examples of **incorrect** code for this rule
8
+
9
+ ```html
10
+ <template>
11
+ <span class="gl-mt-5 max-md:gl-mt-3"></span>
12
+ </template>
13
+ ```
14
+
15
+ ### Examples of **correct** code for this rule
16
+
17
+ ```html
18
+ <template>
19
+ <span class="gl-mt-3 md:gl-mt-5"></span>
20
+ </template>
21
+ ```
22
+
23
+ ## Options
24
+
25
+ No options.
26
+
27
+ ## Related rules
28
+
29
+ - [tailwind-no-max-width-media-queries](./tailwind-no-max-width-media-queries.md)
30
+
31
+ ## When Not To Use It
32
+
33
+ If the codebase doesn't leverage Tailwind CSS, keep this rule disabled.
@@ -48,6 +48,12 @@ const tsConfig = {
48
48
  '@typescript-eslint/no-shadow': 'error',
49
49
  '@typescript-eslint/return-await': 'error',
50
50
  '@typescript-eslint/no-floating-promises': 'error',
51
+ '@typescript-eslint/explicit-member-accessibility': [
52
+ 'error',
53
+ {
54
+ accessibility: 'no-public',
55
+ },
56
+ ],
51
57
  'class-methods-use-this': 'off',
52
58
  'import/no-cycle': 'error',
53
59
  'promise/param-names': 'off',
@@ -12,9 +12,9 @@ module.exports = {
12
12
  meta: {
13
13
  type: 'error',
14
14
  docs: {
15
- description: 'Ensures Tailwind CSS is used according to our internal guidelines.',
15
+ description: 'Prevents building Tailwind CSS utility classes with string interpolation.',
16
16
  category: 'css',
17
- url: DOCS_BASE_URL + '/tailwind.md',
17
+ url: DOCS_BASE_URL + '/tailwind-no-interpolation.md',
18
18
  },
19
19
  },
20
20
  create(context) {
@@ -0,0 +1,30 @@
1
+ // ------------------------------------------------------------------------------
2
+ // Requirements
3
+ // ------------------------------------------------------------------------------
4
+ const { DOCS_BASE_URL } = require('../constants');
5
+ const { validateMaxWidthMediaQueryUtils } = require('../utils/tailwind-utils');
6
+
7
+ // ------------------------------------------------------------------------------
8
+ // Rule Definition
9
+ // ------------------------------------------------------------------------------
10
+
11
+ module.exports = {
12
+ meta: {
13
+ type: 'error',
14
+ docs: {
15
+ description: 'Prevents the usage of max-width media query Tailwind CSS utility classes.',
16
+ category: 'css',
17
+ url: DOCS_BASE_URL + '/tailwind-no-max-width-media-queries.md',
18
+ },
19
+ },
20
+ create(context) {
21
+ return {
22
+ TemplateElement(node) {
23
+ validateMaxWidthMediaQueryUtils(context, node);
24
+ },
25
+ Literal(node) {
26
+ validateMaxWidthMediaQueryUtils(context, node);
27
+ },
28
+ };
29
+ },
30
+ };
@@ -1,4 +1,3 @@
1
-
2
1
  // ------------------------------------------------------------------------------
3
2
  // Requirements
4
3
  // ------------------------------------------------------------------------------
@@ -14,18 +13,18 @@ module.exports = {
14
13
  meta: {
15
14
  type: 'error',
16
15
  docs: {
17
- description: 'Ensures Tailwind CSS is used according to our internal guidelines in Vue templates.',
16
+ description: 'Prevents building Tailwind CSS utility classes with string interpolation.',
18
17
  category: 'css',
19
- url: DOCS_BASE_URL + '/vue-tailwind.md',
18
+ url: DOCS_BASE_URL + '/vue-tailwind-no-interpolation.md',
20
19
  },
21
20
  },
22
21
  create(context) {
23
22
  return defineTemplateBodyVisitor(context, {
24
23
  BinaryExpression(node) {
25
- validateInterpolatedUtils(context, node)
24
+ validateInterpolatedUtils(context, node);
26
25
  },
27
26
  TemplateLiteral(node) {
28
- validateInterpolatedUtils(context, node)
27
+ validateInterpolatedUtils(context, node);
29
28
  },
30
29
  });
31
30
  },
@@ -0,0 +1,34 @@
1
+ // ------------------------------------------------------------------------------
2
+ // Requirements
3
+ // ------------------------------------------------------------------------------
4
+ const { DOCS_BASE_URL } = require('../constants');
5
+ const { defineTemplateBodyVisitor } = require('../utils/index');
6
+ const { validateMaxWidthMediaQueryUtils } = require('../utils/tailwind-utils');
7
+
8
+ // ------------------------------------------------------------------------------
9
+ // Rule Definition
10
+ // ------------------------------------------------------------------------------
11
+
12
+ module.exports = {
13
+ meta: {
14
+ type: 'error',
15
+ docs: {
16
+ description: 'Prevents the usage of max-width media query Tailwind CSS utility classes.',
17
+ category: 'css',
18
+ url: DOCS_BASE_URL + '/vue-tailwind-no-max-width-media-queries.md',
19
+ },
20
+ },
21
+ create(context) {
22
+ return defineTemplateBodyVisitor(context, {
23
+ VLiteral(node) {
24
+ validateMaxWidthMediaQueryUtils(context, node);
25
+ },
26
+ Literal(node) {
27
+ validateMaxWidthMediaQueryUtils(context, node);
28
+ },
29
+ TemplateElement(node) {
30
+ validateMaxWidthMediaQueryUtils(context, node);
31
+ },
32
+ });
33
+ },
34
+ };
@@ -6,6 +6,15 @@ const INTERPOLATED_UTILS_VALIDATORS = {
6
6
  TemplateLiteral: templateLiteralHasInterpolatedUtils,
7
7
  };
8
8
 
9
+ const MAX_WIDTH_MEDIA_QUERY_PATTERN = /max-(sm|md|lg|xl):gl-/;
10
+ const MAX_WIDTH_MEDIA_QUERY_UTIL_ERROR =
11
+ 'Do not use max-width media query utility classes unless absolutely necessary. Use min-width media query utility classes instead.';
12
+ const MAX_WIDTH_MEDIA_QUERY_UTIL_VALIDATORS = {
13
+ Literal: literalHasMaxWidthUtils,
14
+ VLiteral: literalHasMaxWidthUtils,
15
+ TemplateElement: templateElementHasMaxWidthUtils,
16
+ };
17
+
9
18
  function binaryExpressionHasInterpolatedUtils(node) {
10
19
  return node.operator === '+' && INTERPOLATION_PATTERN.test(node.left.value);
11
20
  }
@@ -29,7 +38,30 @@ function validateInterpolatedUtils(context, node) {
29
38
  }
30
39
  }
31
40
 
41
+ function literalHasMaxWidthUtils(node) {
42
+ return MAX_WIDTH_MEDIA_QUERY_PATTERN.test(node.value);
43
+ }
44
+
45
+ function templateElementHasMaxWidthUtils(node) {
46
+ return MAX_WIDTH_MEDIA_QUERY_PATTERN.test(node.value.raw);
47
+ }
48
+
49
+ function validateMaxWidthMediaQueryUtils(context, node) {
50
+ if (MAX_WIDTH_MEDIA_QUERY_UTIL_VALIDATORS[node.type] === undefined) {
51
+ return;
52
+ }
53
+
54
+ if (MAX_WIDTH_MEDIA_QUERY_UTIL_VALIDATORS[node.type](node)) {
55
+ context.report({
56
+ node,
57
+ message: MAX_WIDTH_MEDIA_QUERY_UTIL_ERROR,
58
+ });
59
+ }
60
+ }
61
+
32
62
  module.exports = {
33
63
  validateInterpolatedUtils,
64
+ validateMaxWidthMediaQueryUtils,
34
65
  INTERPOLATED_UTIL_ERROR,
66
+ MAX_WIDTH_MEDIA_QUERY_UTIL_ERROR,
35
67
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/eslint-plugin",
3
- "version": "20.2.1",
3
+ "version": "20.4.0",
4
4
  "description": "GitLab package for our custom eslint rules",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {