@gitlab/eslint-plugin 21.5.0 → 22.0.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.
Files changed (39) hide show
  1. package/CHANGELOG.md +217 -0
  2. package/README.md +16 -11
  3. package/docs/development.md +2 -1
  4. package/docs/usage.md +158 -47
  5. package/eslint9/index.js +6 -7
  6. package/lib/configs/base/best-practices.js +0 -4
  7. package/lib/configs/base/es6.js +0 -12
  8. package/lib/configs/base/imports.js +0 -9
  9. package/lib/configs/base/node.js +0 -4
  10. package/lib/confusing-browser-globals.js +68 -0
  11. package/lib/flat-configs/base.js +122 -0
  12. package/lib/flat-configs/default.js +13 -0
  13. package/lib/flat-configs/i18n.js +14 -0
  14. package/lib/flat-configs/jest.js +20 -0
  15. package/lib/flat-configs/tailwind.js +19 -0
  16. package/{eslint9/configs → lib/flat-configs}/typescript.js +47 -62
  17. package/lib/flat-configs/vue.js +16 -0
  18. package/lib/index.js +30 -39
  19. package/lib/plugin.js +32 -0
  20. package/lib/prettier-rules.js +10 -0
  21. package/lib/rules/no-runtime-template-compiler.js +5 -2
  22. package/lib/rules/vue-no-new-non-primitive-in-template.js +1 -1
  23. package/lib/rules/vue-no-undef-apollo-properties.js +1 -1
  24. package/lib/rules/vue-prefer-dollar-scopedslots.js +1 -1
  25. package/lib/rules/vue-require-required-key.js +1 -1
  26. package/lib/rules/vue-slot-name-casing.js +2 -2
  27. package/lib/vue-fragments.js +111 -0
  28. package/package.json +29 -11
  29. package/scripts/generateRuleMapFixtures.js +75 -0
  30. package/scripts/helpers/getConfigs.js +13 -6
  31. package/scripts/updateFiles.js +30 -6
  32. package/eslint9/configs/base.js +0 -140
  33. package/lib/configs/base.js +0 -115
  34. package/lib/configs/default.js +0 -17
  35. package/lib/configs/i18n.js +0 -10
  36. package/lib/configs/jest.js +0 -21
  37. package/lib/configs/tailwind.js +0 -10
  38. package/lib/configs/typescript.js +0 -95
  39. package/lib/configs/vue.js +0 -91
@@ -0,0 +1,111 @@
1
+ const vuePlugin = require('eslint-plugin-vue');
2
+ const vueParser = require('vue-eslint-parser');
3
+ const globals = require('globals');
4
+ const unicornPlugin = require('eslint-plugin-unicorn');
5
+ const promisePlugin = require('eslint-plugin-promise');
6
+ const importPlugin = require('eslint-plugin-import');
7
+
8
+ const gitlabPlugin = require('./plugin.js');
9
+
10
+ /*
11
+ The Vue config in two halves, so lib/flat-configs/vue.js and
12
+ lib/flat-configs/default.js can each place eslint-config-prettier where it
13
+ belongs for them: after the preset in the former, before it in the latter.
14
+
15
+ vue2-recommended, not the identically-named 'flat/recommended', which targets
16
+ Vue 3. The two names have never pointed at the same preset, and retargeting
17
+ would move 33 rules onto consumers -- a product decision, not a config-format
18
+ one.
19
+ */
20
+ const presetAndSetup = [
21
+ ...vuePlugin.configs['flat/vue2-recommended'],
22
+ {
23
+ name: '@gitlab/vue/setup',
24
+ languageOptions: {
25
+ parser: vueParser,
26
+ parserOptions: {
27
+ parser: require.resolve('espree'),
28
+ },
29
+ globals: {
30
+ ...globals.browser,
31
+ ...globals.es2020,
32
+ },
33
+ ecmaVersion: 'latest',
34
+ sourceType: 'module',
35
+ },
36
+ plugins: {
37
+ unicorn: unicornPlugin,
38
+ promise: promisePlugin,
39
+ import: importPlugin,
40
+ '@gitlab': gitlabPlugin,
41
+ },
42
+ },
43
+ ];
44
+
45
+ const gitlabRules = [
46
+ {
47
+ name: '@gitlab/vue/rules',
48
+ rules: {
49
+ 'vue/html-self-closing': [
50
+ 'error',
51
+ {
52
+ html: { void: 'any', normal: 'never', component: 'always' },
53
+ svg: 'always',
54
+ math: 'always',
55
+ },
56
+ ],
57
+ 'vue/block-order': ['error', { order: ['script', 'template', 'style'] }],
58
+ // Turning this off for now as we violate this rule in many places.
59
+ 'vue/max-attributes-per-line': 'off',
60
+ 'vue/component-options-name-casing': ['error', 'PascalCase'],
61
+ 'vue/component-name-in-template-casing': ['error', 'kebab-case'],
62
+ '@gitlab/vue-require-required-key': 'error',
63
+ 'vue/v-slot-style': ['error', { atComponent: 'shorthand' }],
64
+ '@gitlab/vue-no-data-toggle': 'error',
65
+ '@gitlab/vue-no-popover-target-dollar-el': 'warn',
66
+ '@gitlab/vue-prefer-dollar-scopedslots': 'error',
67
+ '@gitlab/vue-slot-name-casing': 'error',
68
+ '@gitlab/no-runtime-template-compiler': 'error',
69
+ 'import/order': [
70
+ 'error',
71
+ {
72
+ groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
73
+ },
74
+ ],
75
+ // See https://gitlab.com/gitlab-org/frontend/eslint-plugin/-/issues/52.
76
+ 'vue/component-api-style': ['error', ['options']],
77
+ // We might not want to enable vue/singleline-html-element-content-newline and
78
+ // vue/multiline-html-element-content-newline just yet as they might cause
79
+ // regression depending on how the consumers compile Vue templates.
80
+ 'vue/singleline-html-element-content-newline': 'off',
81
+ 'vue/multiline-html-element-content-newline': 'off',
82
+ // Disabling these as they might conflict with prettier.
83
+ 'vue/html-indent': 'off',
84
+ 'vue/html-closing-bracket-newline': 'off',
85
+ // BEGIN rules to aid migration from Vue 2.x to 3.x.
86
+ // See https://gitlab.com/groups/gitlab-org/-/epics/3174 for more details.
87
+ 'vue/no-deprecated-data-object-declaration': 'error',
88
+ 'vue/no-deprecated-events-api': 'error',
89
+ 'vue/no-deprecated-filter': 'error',
90
+ 'vue/no-deprecated-functional-template': 'error',
91
+ 'vue/no-deprecated-html-element-is': 'error',
92
+ 'vue/no-deprecated-inline-template': 'error',
93
+ 'vue/no-deprecated-props-default-this': 'error',
94
+ 'vue/no-deprecated-scope-attribute': 'error',
95
+ 'vue/no-deprecated-slot-attribute': 'error',
96
+ 'vue/no-deprecated-slot-scope-attribute': 'error',
97
+ 'vue/no-deprecated-v-on-number-modifiers': 'error',
98
+ 'vue/no-deprecated-vue-config-keycodes': 'error',
99
+ // END rules to aid migration from Vue 2.x to 3.x.
100
+ },
101
+ },
102
+ {
103
+ name: '@gitlab/vue/sfc-overrides',
104
+ files: ['**/*.vue'],
105
+ rules: {
106
+ 'import/no-default-export': 'off',
107
+ },
108
+ },
109
+ ];
110
+
111
+ module.exports = { presetAndSetup, gitlabRules };
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@gitlab/eslint-plugin",
3
- "version": "21.5.0",
3
+ "version": "22.0.0",
4
4
  "description": "GitLab package for our custom eslint rules",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
7
7
  "createRule": "./scripts/createRule.js && yarn update",
8
- "update": "./scripts/updateFiles.js && prettier --write lib/index.js",
8
+ "update": "./scripts/updateFiles.js && prettier --write lib/plugin.js lib/index.js",
9
9
  "commit": "npx git-cz",
10
10
  "test": "mocha"
11
11
  },
@@ -27,30 +27,48 @@
27
27
  },
28
28
  "homepage": "https://gitlab.com/gitlab-org/frontend/eslint-plugin#readme",
29
29
  "engines": {
30
- "node": ">=14"
30
+ "node": "^20.12.0 || ^22.0.0 || >=24.0.0"
31
31
  },
32
32
  "dependencies": {
33
- "@typescript-eslint/eslint-plugin": "^7.14.1",
34
- "confusing-browser-globals": "^1.0.11",
35
- "eslint-config-prettier": "^9.1.0",
33
+ "@eslint/js": "^9.0.0",
34
+ "eslint-config-prettier": "^10.0.0",
36
35
  "eslint-plugin-import": "^2.29.1",
37
- "eslint-plugin-jest": "^28.6.0",
36
+ "eslint-plugin-jest": "^29.0.0",
38
37
  "eslint-plugin-promise": "^7.0.0",
39
38
  "eslint-plugin-tailwindcss": "^3.18.3",
40
39
  "eslint-plugin-unicorn": "^55.0.0",
41
- "eslint-plugin-vue": "^9.33.0",
40
+ "eslint-plugin-vue": "^10.0.0",
41
+ "globals": "^17.0.0",
42
42
  "lodash": "^4.18.1",
43
- "vue-eslint-parser": "^9.4.3"
43
+ "semver": "^7.0.0",
44
+ "vue-eslint-parser": "^10.3.0"
44
45
  },
45
46
  "peerDependencies": {
46
- "eslint": "^8.57.0 || ^9.0.0"
47
+ "@typescript-eslint/eslint-plugin": "^8.0.0",
48
+ "@typescript-eslint/parser": "^8.0.0",
49
+ "eslint": "^9.0.0",
50
+ "typescript": ">=4.8.4"
51
+ },
52
+ "peerDependenciesMeta": {
53
+ "@typescript-eslint/eslint-plugin": {
54
+ "optional": true
55
+ },
56
+ "@typescript-eslint/parser": {
57
+ "optional": true
58
+ },
59
+ "typescript": {
60
+ "optional": true
61
+ }
47
62
  },
48
63
  "devDependencies": {
49
64
  "@changesets/cli": "^2.29.8",
50
- "eslint": "^8.57.0",
65
+ "@typescript-eslint/eslint-plugin": "^8.0.0",
66
+ "@typescript-eslint/parser": "^8.0.0",
67
+ "eslint": "^9.0.0",
51
68
  "glob": "^7.2.0",
52
69
  "mocha": "^11.7.5",
53
70
  "prettier": "^2.6.1",
71
+ "typescript": "^5.0.0",
54
72
  "yarn-deduplicate": "^6.0.2"
55
73
  }
56
74
  }
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ONE-SHOT generator. Resolves each eslintrc config in lib/configs/ into a
4
+ * flat map of rule -> [severity, ...options] and writes it to
5
+ * tests/fixtures/rule-maps/. Run once, on ESLint 8, BEFORE the flat-config
6
+ * migration. Committed for reviewability; not wired into CI.
7
+ *
8
+ * Its inputs are gone and it no longer runs. Kept only as the provenance of
9
+ * the frozen fixtures; deleted at the end of this stack.
10
+ */
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+ const { ESLint } = require('eslint');
14
+
15
+ const CONFIG_DIR = path.join(__dirname, '../lib/configs');
16
+ const OUT_DIR = path.join(__dirname, '../tests/fixtures/rule-maps');
17
+
18
+ // Top level only: lib/configs/base/ holds rule fragments, not configs.
19
+ const CONFIGS = fs
20
+ .readdirSync(CONFIG_DIR)
21
+ .filter((file) => file.endsWith('.js'))
22
+ .map((file) => path.basename(file, '.js'));
23
+ const SAMPLES = ['sample.js', 'sample.vue', 'sample.ts', 'sample.test.ts'];
24
+
25
+ const SEVERITIES = ['off', 'warn', 'error'];
26
+
27
+ /** Normalise [2, opts] / 'error' / ['error', opts] into 'error' or ['error', ...opts]. */
28
+ function normalizeEntry(entry) {
29
+ const value = Array.isArray(entry) ? entry : [entry];
30
+ const [severity, ...options] = value;
31
+ const name = typeof severity === 'number' ? SEVERITIES[severity] : severity;
32
+ return options.length > 0 ? [name, ...options] : name;
33
+ }
34
+
35
+ function normalizeRules(rules) {
36
+ return Object.fromEntries(
37
+ Object.keys(rules)
38
+ .sort()
39
+ .map((name) => [name, normalizeEntry(rules[name])]),
40
+ );
41
+ }
42
+
43
+ async function mapForConfig(configName) {
44
+ const configPath = require.resolve(`../lib/configs/${configName}.js`);
45
+ const eslint = new ESLint({
46
+ useEslintrc: false,
47
+ // The plugin cannot resolve itself by name from inside its own repo.
48
+ plugins: { '@gitlab': require('../lib/index.js') },
49
+ baseConfig: { extends: [configPath] },
50
+ });
51
+
52
+ const resolved = await Promise.all(
53
+ SAMPLES.map((sample) => eslint.calculateConfigForFile(path.join(process.cwd(), sample))),
54
+ );
55
+ return Object.fromEntries(
56
+ SAMPLES.map((sample, index) => [sample, normalizeRules(resolved[index].rules || {})]),
57
+ );
58
+ }
59
+
60
+ async function main() {
61
+ fs.mkdirSync(OUT_DIR, { recursive: true });
62
+ for (const name of CONFIGS) {
63
+ // eslint-disable-next-line no-await-in-loop
64
+ const map = await mapForConfig(name);
65
+ const file = path.join(OUT_DIR, `${name}.json`);
66
+ fs.writeFileSync(file, `${JSON.stringify(map, null, 2)}\n`);
67
+ const counts = SAMPLES.map((sample) => `${sample} ${Object.keys(map[sample]).length}`);
68
+ console.log(`Wrote ${path.relative(process.cwd(), file)} (${counts.join(', ')})`);
69
+ }
70
+ }
71
+
72
+ main().catch((error) => {
73
+ console.error(error);
74
+ process.exit(1);
75
+ });
@@ -1,19 +1,26 @@
1
1
  const path = require('path');
2
2
  const glob = require('glob');
3
3
 
4
- const rulesDir = path.join(__dirname, '../../lib/configs');
4
+ const configsDir = path.join(__dirname, '../../lib/flat-configs');
5
5
 
6
- function getRule(fullPath) {
7
- const relative = path.relative(rulesDir, fullPath);
6
+ /*
7
+ lib/flat-configs/ is a closed set: this glob decides what `yarn update`
8
+ publishes as `plugin.configs[<basename>]`, so a shared helper dropped in that
9
+ directory becomes a bogus public config. That is why lib/prettier-rules.js and
10
+ lib/vue-fragments.js sit at the lib/ root instead; put new shared code there.
11
+
12
+ No `.meta` spread, unlike getRules.js: a flat config exports an array.
13
+ */
14
+ function getConfig(fullPath) {
15
+ const relative = path.relative(configsDir, fullPath);
8
16
  const name = path.basename(relative, '.js');
9
17
  return {
10
- ...require(fullPath).meta,
11
18
  name,
12
19
  relative,
13
20
  fullPath,
14
21
  };
15
22
  }
16
23
 
17
- module.exports = function getRules() {
18
- return glob.sync(path.join(rulesDir, '**/*.js')).map(getRule);
24
+ module.exports = function getConfigs() {
25
+ return glob.sync(path.join(configsDir, '*.js')).map(getConfig);
19
26
  };
@@ -9,21 +9,40 @@ const libPath = path.join(__dirname, '../lib');
9
9
  const rules = getRules();
10
10
  const configs = getConfigs();
11
11
 
12
- const createIndexJs = (ruleImports, configImports) => `/**
12
+ const createPluginJs = (ruleImports) => `/**
13
13
  * This file is GENERATED, please run \`yarn update\` after adding or renaming a rule
14
14
  */
15
+ const { name, version } = require('../package.json');
16
+
15
17
  module.exports = {
18
+ meta: { name, version },
16
19
  rules: {
17
20
  ${ruleImports.join('\n')}
18
21
  },
22
+ };
23
+ `;
24
+
25
+ const createIndexJs = (configImports) => `/**
26
+ * This file is GENERATED, please run \`yarn update\` after adding or renaming a rule
27
+ */
28
+ const plugin = require('./plugin.js');
29
+
30
+ /*
31
+ Getters, so requiring the plugin never loads a config the consumer is not
32
+ using: \`typescript\` pulls in optional peer dependencies, and eagerly
33
+ requiring it would throw for anyone without the TypeScript toolchain. Getters
34
+ in an object literal are enumerable, so \`Object.keys(configs)\` is unaffected.
35
+ */
36
+ module.exports = {
37
+ ...plugin,
19
38
  configs: {
20
39
  ${configImports.join('\n')}
21
- }
40
+ },
22
41
  };
23
42
  `;
24
43
 
25
44
  const writeIndexJs = () => {
26
- console.log('Updating lib/index.js...');
45
+ console.log('Updating lib/plugin.js and lib/index.js...');
27
46
 
28
47
  const ruleImports = rules.map((rule) => {
29
48
  const relPath = path.relative(libPath, rule.fullPath);
@@ -32,12 +51,17 @@ const writeIndexJs = () => {
32
51
 
33
52
  const configImports = configs.map((config) => {
34
53
  const relPath = path.relative(libPath, config.fullPath);
35
- return ` '${config.name}': require('./${relPath}'),`;
54
+ // Quoted so a hyphenated filename cannot emit a syntax error; prettier
55
+ // drops the quotes again where they are redundant.
56
+ return ` get '${config.name}'() {
57
+ return require('./${relPath}');
58
+ },`;
36
59
  });
37
60
 
38
- fs.writeFileSync(path.join(libPath, 'index.js'), createIndexJs(ruleImports, configImports));
61
+ fs.writeFileSync(path.join(libPath, 'plugin.js'), createPluginJs(ruleImports));
62
+ fs.writeFileSync(path.join(libPath, 'index.js'), createIndexJs(configImports));
39
63
 
40
- console.log('Successfully updated lib/index.js');
64
+ console.log('Successfully updated lib/plugin.js and lib/index.js');
41
65
  };
42
66
 
43
67
  const createDoc = (ruleDocs) => `<!--
@@ -1,140 +0,0 @@
1
- const confusingBrowserGlobals = require('confusing-browser-globals');
2
- const globals = require('globals');
3
- const unicornPlugin = require('eslint-plugin-unicorn');
4
- const promisePlugin = require('eslint-plugin-promise');
5
- const importPlugin = require('eslint-plugin-import');
6
-
7
- // Import all the base configurations
8
- const bestPracticesConfig = require('../../lib/configs/base/best-practices');
9
- const errorsConfig = require('../../lib/configs/base/errors');
10
- const nodeConfig = require('../../lib/configs/base/node');
11
- const styleConfig = require('../../lib/configs/base/style');
12
- const variablesConfig = require('../../lib/configs/base/variables');
13
- const es6Config = require('../../lib/configs/base/es6');
14
- const importsConfig = require('../../lib/configs/base/imports');
15
- const strictConfig = require('../../lib/configs/base/strict');
16
-
17
- /*
18
- This plugin contains rules related to GitLab JavaScript style guide
19
- Vue specific rules are in lib/configs/vue.js
20
- */
21
- module.exports = {
22
- languageOptions: {
23
- globals: {
24
- ...globals.browser,
25
- ...globals.es2020,
26
- ...globals.node,
27
- ...globals.es6,
28
- },
29
- ecmaVersion: 'latest',
30
- sourceType: 'module',
31
- parserOptions: {
32
- parser: 'espree',
33
- },
34
- },
35
- plugins: {
36
- unicorn: unicornPlugin,
37
- promise: promisePlugin,
38
- import: importPlugin,
39
- },
40
- settings: {
41
- // Merge import settings from imports config
42
- ...importsConfig.settings,
43
- },
44
- rules: {
45
- ...promisePlugin.configs['flat/recommended'].rules,
46
- // Merge all rules from the base configurations
47
- ...bestPracticesConfig.rules,
48
- ...errorsConfig.rules,
49
- ...nodeConfig.rules,
50
- ...styleConfig.rules,
51
- ...variablesConfig.rules,
52
- ...es6Config.rules,
53
- ...importsConfig.rules,
54
- ...strictConfig.rules,
55
- // Override specific rules from base configs
56
- // Promise rule customizations
57
- 'promise/catch-or-return': [
58
- 'error',
59
- {
60
- allowFinally: true,
61
- },
62
- ],
63
- camelcase: [
64
- 'error',
65
- {
66
- properties: 'never',
67
- ignoreDestructuring: true,
68
- },
69
- ],
70
- 'default-param-last': 'off',
71
- 'arrow-body-style': 'off',
72
- 'unicorn/filename-case': ['error', { case: 'snakeCase' }],
73
- 'unicorn/no-array-callback-reference': 'error',
74
- 'import/prefer-default-export': 'off',
75
- 'import/no-default-export': 'error',
76
- 'import/no-deprecated': 'error',
77
- 'import/no-dynamic-require': ['error', { esmodule: true }],
78
- 'no-implicit-coercion': [
79
- 'error',
80
- {
81
- boolean: true,
82
- number: true,
83
- string: true,
84
- },
85
- ],
86
- 'no-param-reassign': [
87
- 'error',
88
- {
89
- props: true,
90
- ignorePropertyModificationsFor: ['acc', 'accumulator', 'el', 'element', 'state'],
91
- },
92
- ],
93
- 'no-restricted-exports': [
94
- 'error',
95
- {
96
- restrictedNamedExports: [
97
- 'then', // avoid confusion when used with dynamic `import()` promise
98
- ],
99
- },
100
- ],
101
- 'no-restricted-syntax': 'off',
102
- 'no-sequences': [
103
- 'error',
104
- {
105
- allowInParentheses: false,
106
- },
107
- ],
108
- 'no-restricted-globals': [
109
- 'error',
110
- {
111
- name: 'isFinite',
112
- message:
113
- 'Use Number.isFinite instead https://github.com/airbnb/javascript#standard-library--isfinite',
114
- },
115
- {
116
- name: 'isNaN',
117
- message:
118
- 'Use Number.isNaN instead https://github.com/airbnb/javascript#standard-library--isnan',
119
- },
120
- {
121
- name: 'escape',
122
- message:
123
- "The global `escape` function is unsafe. Did you mean to use `encodeURI`, `encodeURIComponent` or lodash's `escape` instead?",
124
- },
125
- {
126
- name: 'unescape',
127
- message:
128
- "The global `unescape` function is unsafe. Did you mean to use `decodeURI`, `decodeURIComponent` or lodash's `unescape` instead?",
129
- },
130
- ].concat(confusingBrowserGlobals),
131
- 'import/order': [
132
- 'error',
133
- {
134
- groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
135
- },
136
- ],
137
- // https://docs.gitlab.com/ee/development/fe_guide/style/javascript.html#limit-number-of-parameters
138
- 'max-params': ['error', { max: 3 }],
139
- },
140
- };
@@ -1,115 +0,0 @@
1
- const confusingBrowserGlobals = require('confusing-browser-globals');
2
-
3
- /*
4
- This plugin contains rules related to GitLab JavaScript style guide
5
- Vue specific rules are in lib/configs/vue.js
6
- */
7
- module.exports = {
8
- env: {
9
- browser: true,
10
- es2020: true,
11
- },
12
- extends: [
13
- ...[
14
- './base/best-practices.js',
15
- './base/errors',
16
- './base/node',
17
- './base/style',
18
- './base/variables',
19
- './base/es6',
20
- './base/imports',
21
- './base/strict',
22
- ].map((f) => require.resolve(f)),
23
- 'prettier',
24
- 'plugin:promise/recommended',
25
- ],
26
- parserOptions: {
27
- parser: 'espree',
28
- ecmaVersion: 'latest',
29
- },
30
- plugins: ['unicorn', 'promise', 'import', '@gitlab'],
31
- rules: {
32
- camelcase: [
33
- 'error',
34
- {
35
- properties: 'never',
36
- ignoreDestructuring: true,
37
- },
38
- ],
39
- 'default-param-last': 'off',
40
- 'arrow-body-style': 'off',
41
- 'unicorn/filename-case': ['error', { case: 'snakeCase' }],
42
- 'unicorn/no-array-callback-reference': 'error',
43
- 'import/prefer-default-export': 'off',
44
- 'import/no-default-export': 'error',
45
- 'import/no-deprecated': 'error',
46
- 'import/no-dynamic-require': ['error', { esmodule: true }],
47
- 'no-implicit-coercion': [
48
- 'error',
49
- {
50
- boolean: true,
51
- number: true,
52
- string: true,
53
- },
54
- ],
55
- 'no-param-reassign': [
56
- 'error',
57
- {
58
- props: true,
59
- ignorePropertyModificationsFor: ['acc', 'accumulator', 'el', 'element', 'state'],
60
- },
61
- ],
62
- 'no-restricted-exports': [
63
- 'error',
64
- {
65
- restrictedNamedExports: [
66
- 'then', // avoid confusion when used with dynamic `import()` promise
67
- ],
68
- },
69
- ],
70
- 'no-restricted-syntax': 'off',
71
- 'no-sequences': [
72
- 'error',
73
- {
74
- allowInParentheses: false,
75
- },
76
- ],
77
- 'promise/catch-or-return': [
78
- 'error',
79
- {
80
- allowFinally: true,
81
- },
82
- ],
83
- 'no-restricted-globals': [
84
- 'error',
85
- {
86
- name: 'isFinite',
87
- message:
88
- 'Use Number.isFinite instead https://github.com/airbnb/javascript#standard-library--isfinite',
89
- },
90
- {
91
- name: 'isNaN',
92
- message:
93
- 'Use Number.isNaN instead https://github.com/airbnb/javascript#standard-library--isnan',
94
- },
95
- {
96
- name: 'escape',
97
- message:
98
- "The global `escape` function is unsafe. Did you mean to use `encodeURI`, `encodeURIComponent` or lodash's `escape` instead?",
99
- },
100
- {
101
- name: 'unescape',
102
- message:
103
- "The global `unescape` function is unsafe. Did you mean to use `decodeURI`, `decodeURIComponent` or lodash's `unescape` instead?",
104
- },
105
- ].concat(confusingBrowserGlobals),
106
- 'import/order': [
107
- 'error',
108
- {
109
- groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
110
- },
111
- ],
112
- // https://docs.gitlab.com/ee/development/fe_guide/style/javascript.html#limit-number-of-parameters
113
- 'max-params': ['error', { max: 3 }],
114
- },
115
- };
@@ -1,17 +0,0 @@
1
- const baseConfig = require('./base');
2
- const vueConfig = require('./vue');
3
-
4
- module.exports = {
5
- ...baseConfig,
6
- extends: [
7
- ...baseConfig.extends,
8
- 'prettier',
9
- 'plugin:promise/recommended',
10
- 'plugin:vue/recommended',
11
- ],
12
- rules: {
13
- ...baseConfig.rules,
14
- ...vueConfig.rules,
15
- },
16
- overrides: vueConfig.overrides,
17
- };
@@ -1,10 +0,0 @@
1
- module.exports = {
2
- plugins: ['@gitlab'],
3
- rules: {
4
- '@gitlab/require-i18n-strings': 'error',
5
- '@gitlab/vue-require-i18n-attribute-strings': 'error',
6
- '@gitlab/vue-require-i18n-strings': 'error',
7
- '@gitlab/require-valid-i18n-helpers': 'error',
8
- '@gitlab/vue-require-valid-i18n-helpers': 'error',
9
- },
10
- };
@@ -1,21 +0,0 @@
1
- module.exports = {
2
- extends: ['plugin:jest/recommended'],
3
- rules: {
4
- 'jest/consistent-test-it': ['error', { fn: 'it', withinDescribe: 'it' }],
5
- 'jest/no-conditional-expect': 'off',
6
- 'jest/valid-title': [
7
- 'error',
8
- {
9
- ignoreTypeOfDescribeName: true,
10
- },
11
- ],
12
- 'jest/no-restricted-matchers': [
13
- 'error',
14
- {
15
- toBeFalsy: 'Prefer a stronger matcher like `toBe(false)`',
16
- toBeTruthy: 'Prefer a stronger matcher like `toBe(true)`',
17
- },
18
- ],
19
- 'jest/prefer-to-have-length': 'error',
20
- },
21
- };
@@ -1,10 +0,0 @@
1
- module.exports = {
2
- plugins: ['@gitlab', 'tailwindcss'],
3
- rules: {
4
- '@gitlab/tailwind-no-interpolation': 'error',
5
- '@gitlab/vue-tailwind-no-interpolation': 'error',
6
- '@gitlab/tailwind-no-max-width-media-queries': 'error',
7
- '@gitlab/vue-tailwind-no-max-width-media-queries': 'error',
8
- 'tailwindcss/no-arbitrary-value': 'error',
9
- },
10
- };