eslint-plugin-vuetify 2.4.0 → 2.5.1

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/README.md CHANGED
@@ -15,7 +15,7 @@ This package is for migrating from Vuetify v2 to v3, use [eslint-plugin-vuetify@
15
15
 
16
16
  ## 💿 Install
17
17
 
18
- You should have [`eslint`](https://eslint.org/docs/user-guide/getting-started) and [`eslint-plugin-vue`](https://eslint.vuejs.org/user-guide/#installation) set up first.
18
+ You should have [`eslint`](https://eslint.org/docs/latest/use/getting-started) and [`eslint-plugin-vue`](https://eslint.vuejs.org/user-guide/#installation) set up first.
19
19
 
20
20
  ```bash
21
21
  yarn add eslint-plugin-vuetify -D
@@ -23,6 +23,19 @@ yarn add eslint-plugin-vuetify -D
23
23
  npm install eslint-plugin-vuetify --save-dev
24
24
  ```
25
25
 
26
+ ```js
27
+ // eslint.config.js
28
+ import vue from 'eslint-plugin-vue'
29
+ import vuetify from 'eslint-plugin-vuetify'
30
+
31
+ export default [
32
+ ...vue.configs['flat/base'],
33
+ ...vuetify.configs['flat/base'],
34
+ ]
35
+ ```
36
+
37
+ Eslint 8 can alternatively use the older configuration format:
38
+
26
39
  ```js
27
40
  // .eslintrc.js
28
41
  module.exports = {
@@ -40,7 +53,7 @@ module.exports = {
40
53
 
41
54
  ### Deprecations
42
55
 
43
- These rules will help you avoid deprecated components, props, and classes. They are included in the `plugin:vuetify/base` preset.
56
+ These rules will help you avoid deprecated components, props, and classes. They are included in the `base` preset.
44
57
 
45
58
  - Prevent the use of components that have been removed from Vuetify ([`no-deprecated-components`])
46
59
  - Prevent the use of props that have been removed from Vuetify ([`no-deprecated-props`])
@@ -52,7 +65,7 @@ These rules will help you avoid deprecated components, props, and classes. They
52
65
 
53
66
  ### Grid system
54
67
 
55
- These rules are designed to help migrate to the new grid system in Vuetify v2. They are included in the `plugin:vuetify/recommended` preset.
68
+ These rules are designed to help migrate to the new grid system in Vuetify v2. They are included in the `recommended` preset.
56
69
 
57
70
  - Warn about unknown attributes not being converted to classes on new grid components ([`grid-unknown-attributes`])
58
71
 
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+
3
+ module.exports = [{
4
+ plugins: {
5
+ vue: require('eslint-plugin-vue'),
6
+ get vuetify() {
7
+ return require('../../index');
8
+ }
9
+ },
10
+ rules: require('../base').rules
11
+ }];
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+
3
+ module.exports = [...require('./base'), {
4
+ plugins: {
5
+ get vuetify() {
6
+ return require('../../index');
7
+ }
8
+ },
9
+ rules: require('../recommended').rules
10
+ }];
package/lib/index.js CHANGED
@@ -3,6 +3,11 @@
3
3
  const path = require('path');
4
4
  const requireindex = require('requireindex');
5
5
  module.exports = {
6
- configs: requireindex(path.join(__dirname, './configs')),
6
+ configs: {
7
+ base: require('./configs/base'),
8
+ recommended: require('./configs/recommended'),
9
+ 'flat/base': require('./configs/flat/base'),
10
+ 'flat/recommended': require('./configs/flat/recommended')
11
+ },
7
12
  rules: requireindex(path.join(__dirname, './rules'))
8
13
  };
@@ -3,7 +3,8 @@
3
3
  const {
4
4
  hyphenate,
5
5
  classify,
6
- getAttributes
6
+ getAttributes,
7
+ isVueTemplate
7
8
  } = require('../util/helpers');
8
9
  const {
9
10
  isGridAttribute
@@ -39,7 +40,8 @@ module.exports = {
39
40
  schema: []
40
41
  },
41
42
  create(context) {
42
- return context.parserServices.defineTemplateBodyVisitor({
43
+ if (!isVueTemplate(context)) return {};
44
+ return context.sourceCode.parserServices.defineTemplateBodyVisitor({
43
45
  VElement(element) {
44
46
  const tag = classify(element.rawName);
45
47
  if (!Object.keys(tags).includes(tag)) return;
@@ -2,7 +2,8 @@
2
2
 
3
3
  const {
4
4
  classify,
5
- getAttributes
5
+ getAttributes,
6
+ isVueTemplate
6
7
  } = require('../util/helpers');
7
8
 
8
9
  // ------------------------------------------------------------------------------
@@ -24,7 +25,8 @@ module.exports = {
24
25
  }
25
26
  },
26
27
  create(context) {
27
- return context.parserServices.defineTemplateBodyVisitor({
28
+ if (!isVueTemplate(context)) return {};
29
+ return context.sourceCode.parserServices.defineTemplateBodyVisitor({
28
30
  VElement(element) {
29
31
  const tag = classify(element.rawName);
30
32
  if (tag !== 'VBtn') return;
@@ -1,5 +1,9 @@
1
1
  'use strict';
2
2
 
3
+ const {
4
+ isVueTemplate
5
+ } = require('../util/helpers');
6
+
3
7
  /** @type {Map<RegExp, ((args: string[]) => string | false) | false> | Map<string, string | false>} */
4
8
  const replacements = new Map([[/^rounded-(r|l|tr|tl|br|bl)(-.*)?$/, ([side, rest]) => {
5
9
  side = {
@@ -30,11 +34,11 @@ module.exports = {
30
34
  }
31
35
  },
32
36
  create(context) {
33
- return context.parserServices.defineTemplateBodyVisitor({
37
+ if (!isVueTemplate(context)) return {};
38
+ return context.sourceCode.parserServices.defineTemplateBodyVisitor({
34
39
  'VAttribute[key.name="class"]'(node) {
35
40
  if (!node.value || !node.value.value) return;
36
41
  const classes = node.value.value.split(/\s+/).filter(s => !!s);
37
- const source = context.getSourceCode();
38
42
  const changed = [];
39
43
  classes.forEach(className => {
40
44
  for (const replacer of replacements) {
@@ -58,8 +62,8 @@ module.exports = {
58
62
  const idx = node.value.value.indexOf(change[0]) + 1;
59
63
  const range = [node.value.range[0] + idx, node.value.range[0] + idx + change[0].length];
60
64
  const loc = {
61
- start: source.getLocFromIndex(range[0]),
62
- end: source.getLocFromIndex(range[1])
65
+ start: context.sourceCode.getLocFromIndex(range[0]),
66
+ end: context.sourceCode.getLocFromIndex(range[1])
63
67
  };
64
68
  if (change[1]) {
65
69
  context.report({
@@ -1,5 +1,8 @@
1
1
  'use strict';
2
2
 
3
+ const {
4
+ isVueTemplate
5
+ } = require('../util/helpers');
3
6
  const cssColors = ['red', 'pink', 'purple', 'deep-purple', 'indigo', 'blue', 'light-blue', 'cyan', 'teal', 'green', 'light-green', 'lime', 'yellow', 'amber', 'orange', 'deep-orange', 'brown', 'blue-grey', 'grey', 'black', 'white', 'transparent'];
4
7
  const cssTextColors = cssColors.map(v => `${v}--text`);
5
8
  const variants = ['lighten-1', 'lighten-2', 'lighten-3', 'lighten-4', 'lighten-5', 'darken-1', 'darken-2', 'darken-3', 'darken-4', 'accent-1', 'accent-2', 'accent-3', 'accent-4'];
@@ -33,6 +36,7 @@ module.exports = {
33
36
  }
34
37
  },
35
38
  create(context) {
39
+ if (!isVueTemplate(context)) return {};
36
40
  const themeColors = ['primary', 'secondary', 'accent', 'error', 'warning', 'info', 'success', ...(context.options[0]?.themeColors || [])];
37
41
  const themeTextColors = themeColors.map(v => `${v}--text`);
38
42
  function findColor(classes) {
@@ -45,7 +49,7 @@ module.exports = {
45
49
  const variant = classes.findIndex(t => textVariants.includes(t));
46
50
  return [base, variant];
47
51
  }
48
- return context.parserServices.defineTemplateBodyVisitor({
52
+ return context.sourceCode.parserServices.defineTemplateBodyVisitor({
49
53
  'VAttribute[key.name="color"]'(node) {
50
54
  if (!node.value || !node.value.value) return;
51
55
  const color = node.value.value.split(/\s+/).filter(s => !!s);
@@ -2,7 +2,8 @@
2
2
 
3
3
  const {
4
4
  hyphenate,
5
- classify
5
+ classify,
6
+ isVueTemplate
6
7
  } = require('../util/helpers');
7
8
  const replacements = {
8
9
  VListTile: 'v-list-item',
@@ -38,8 +39,7 @@ const replacements = {
38
39
  VSimpleTable: 'v-table',
39
40
  VTabsSlider: false,
40
41
  VTabsItems: false,
41
- VTabItem: false,
42
- VTimePicker: false
42
+ VTabItem: false
43
43
  };
44
44
 
45
45
  // ------------------------------------------------------------------------------
@@ -61,10 +61,11 @@ module.exports = {
61
61
  }
62
62
  },
63
63
  create(context) {
64
- return context.parserServices.defineTemplateBodyVisitor({
64
+ if (!isVueTemplate(context)) return {};
65
+ return context.sourceCode.parserServices.defineTemplateBodyVisitor({
65
66
  VElement(element) {
66
67
  const tag = classify(element.rawName);
67
- const tokens = context.parserServices.getTemplateBodyTokenStore();
68
+ const tokens = context.sourceCode.parserServices.getTemplateBodyTokenStore();
68
69
  if (Object.prototype.hasOwnProperty.call(replacements, tag)) {
69
70
  const replacement = replacements[tag];
70
71
  if (typeof replacement === 'object' && 'custom' in replacement) {
@@ -2,7 +2,8 @@
2
2
 
3
3
  const {
4
4
  hyphenate,
5
- classify
5
+ classify,
6
+ isVueTemplate
6
7
  } = require('../util/helpers');
7
8
  const model = {
8
9
  input: 'update:modelValue'
@@ -156,7 +157,8 @@ module.exports = {
156
157
  }
157
158
  },
158
159
  create(context) {
159
- return context.parserServices.defineTemplateBodyVisitor({
160
+ if (!isVueTemplate(context)) return {};
161
+ return context.sourceCode.parserServices.defineTemplateBodyVisitor({
160
162
  VAttribute(attr) {
161
163
  if (!(attr.directive && attr.key.name.name === 'on' && attr.key.argument?.type === 'VIdentifier')) return;
162
164
  const tag = classify(attr.parent.parent.rawName);
@@ -2,7 +2,8 @@
2
2
 
3
3
  const {
4
4
  hyphenate,
5
- classify
5
+ classify,
6
+ isVueTemplate
6
7
  } = require('../util/helpers');
7
8
  const size = {
8
9
  maxHeight: false,
@@ -539,7 +540,8 @@ const replacements = {
539
540
  ...size
540
541
  },
541
542
  VForm: {
542
- value: 'model-value'
543
+ value: 'model-value',
544
+ lazyValidation: false
543
545
  },
544
546
  VHover: {
545
547
  value: 'model-value'
@@ -937,7 +939,8 @@ module.exports = {
937
939
  }
938
940
  },
939
941
  create(context) {
940
- return context.parserServices.defineTemplateBodyVisitor({
942
+ if (!isVueTemplate(context)) return {};
943
+ return context.sourceCode.parserServices.defineTemplateBodyVisitor({
941
944
  VStartTag(tag) {
942
945
  const attrGroups = {};
943
946
  tag.attributes.forEach(attr => {
@@ -993,7 +996,7 @@ module.exports = {
993
996
  }
994
997
  });
995
998
  } else if (typeof replace === 'object' && 'name' in replace && 'value' in replace) {
996
- const oldValue = attr.directive ? context.getSourceCode().getText(attr.value.expression) : attr.value?.value;
999
+ const oldValue = attr.directive ? context.sourceCode.getText(attr.value.expression) : attr.value?.value;
997
1000
  const value = typeof replace.value === 'function' ? replace.value(oldValue) : replace.value;
998
1001
  if (value == null || value === oldValue) return;
999
1002
  context.report({
@@ -1011,7 +1014,7 @@ module.exports = {
1011
1014
  }
1012
1015
  return [fixer.replaceText(propNameNode, replace.name), fixer.replaceText(attr.value, `"${value}"`)];
1013
1016
  } else {
1014
- const expression = context.getSourceCode().getText(attr.value.expression);
1017
+ const expression = context.sourceCode.getText(attr.value.expression);
1015
1018
  return [fixer.replaceText(propNameNode, replace.name), fixer.replaceText(attr.value, `"${expression} ? '${value}' : undefined"`)];
1016
1019
  }
1017
1020
  } else {
@@ -2,7 +2,8 @@
2
2
 
3
3
  const {
4
4
  classify,
5
- getAttributes
5
+ getAttributes,
6
+ isVueTemplate
6
7
  } = require('../util/helpers');
7
8
  const groups = [{
8
9
  components: ['VDialog', 'VMenu', 'VTooltip'],
@@ -96,7 +97,7 @@ const groups = [{
96
97
  yield fixer.replaceText(ref.id.parent.parent, `v-bind="props"`);
97
98
  }
98
99
  if (boundVariables.attrs) {
99
- const template = context.parserServices.getTemplateBodyTokenStore();
100
+ const template = context.sourceCode.parserServices.getTemplateBodyTokenStore();
100
101
  const ref = boundVariables.attrs;
101
102
  const isLast = ref.prop === param.properties.at(-1);
102
103
  if (isLast) {
@@ -187,8 +188,9 @@ module.exports = {
187
188
  }
188
189
  },
189
190
  create(context) {
191
+ if (!isVueTemplate(context)) return {};
190
192
  let scopeStack;
191
- return context.parserServices.defineTemplateBodyVisitor({
193
+ return context.sourceCode.parserServices.defineTemplateBodyVisitor({
192
194
  VElement(node) {
193
195
  scopeStack = {
194
196
  parent: scopeStack,
@@ -10,11 +10,11 @@ function addClass(context, fixer, element, className) {
10
10
  return fixer.insertTextAfter(classNode, `="${className}"`);
11
11
  } else {
12
12
  // nothing
13
- return fixer.insertTextAfter(context.parserServices.getTemplateBodyTokenStore().getFirstToken(element.startTag), ` class="${className}"`);
13
+ return fixer.insertTextAfter(context.sourceCode.parserServices.getTemplateBodyTokenStore().getFirstToken(element.startTag), ` class="${className}"`);
14
14
  }
15
15
  }
16
16
  function removeAttr(context, fixer, node) {
17
- const source = context.getSourceCode().text;
17
+ const source = context.sourceCode.text;
18
18
  let [start, end] = node.range;
19
19
  // Remove extra whitespace before attributes
20
20
  start -= /\s*$/g.exec(source.substring(0, start))[0].length;
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
- function hyphenate( /* istanbul ignore next */
3
+ const path = require('node:path');
4
+ function hyphenate(/* istanbul ignore next */
4
5
  str = '') {
5
6
  return str.replace(/\B([A-Z])/g, '-$1').toLowerCase();
6
7
  }
@@ -41,11 +42,18 @@ function mergeDeep(source, target) {
41
42
  }
42
43
  return source;
43
44
  }
45
+ function isVueTemplate(context) {
46
+ if (context.sourceCode.parserServices.defineTemplateBodyVisitor == null) {
47
+ return path.extname(context.getFilename()) === '.vue';
48
+ }
49
+ return true;
50
+ }
44
51
  module.exports = {
45
52
  hyphenate,
46
53
  classify,
47
54
  isBuiltinAttribute,
48
55
  getAttributes,
49
56
  isObject,
50
- mergeDeep
57
+ mergeDeep,
58
+ isVueTemplate
51
59
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-vuetify",
3
- "version": "2.4.0",
3
+ "version": "2.5.1",
4
4
  "description": "An eslint plugin for Vuetify",
5
5
  "main": "lib/index.js",
6
6
  "author": "Kael Watts-Deuchar <kaelwd@gmail.com>",
@@ -9,6 +9,7 @@
9
9
  "scripts": {
10
10
  "build": "rimraf lib && babel src --out-dir lib",
11
11
  "test": "mocha tests --recursive --reporter dot",
12
+ "test:8": "ESLINT8=true mocha tests --recursive --reporter dot",
12
13
  "test:coverage": "nyc mocha tests --recursive --reporter dot",
13
14
  "test:ci": "nyc --reporter=lcov mocha tests --recursive --reporter dot",
14
15
  "lint": "eslint src tests",
@@ -26,23 +27,24 @@
26
27
  "@babel/cli": "^7.19.3",
27
28
  "@babel/core": "^7.19.6",
28
29
  "@babel/preset-env": "^7.19.4",
30
+ "@stylistic/eslint-plugin": "^2.10.1",
29
31
  "conventional-changelog-cli": "^2.2.2",
30
32
  "conventional-changelog-vuetify": "^1.1.0",
31
33
  "conventional-github-releaser": "^3.1.5",
32
- "eslint": "^8.26.0",
33
- "eslint-config-standard": "^17.0.0",
34
- "eslint-plugin-import": "^2.26.0",
35
- "eslint-plugin-n": "^15.3.0",
36
- "eslint-plugin-promise": "^6.1.1",
34
+ "eslint": "^9.14.0",
35
+ "eslint8": "npm:eslint@8.57.1",
37
36
  "husky": "^8.0.1",
38
37
  "mocha": "^10.1.0",
38
+ "neostandard": "^0.11.8",
39
39
  "nyc": "^15.1.0",
40
40
  "rimraf": "^3.0.2",
41
- "vue": "^3.2.41",
42
- "vuetify": "^3.0.0"
41
+ "vue": "^3.5.12",
42
+ "vue-eslint-parser": "^9.4.3",
43
+ "vuetify": "^3.7.4"
43
44
  },
44
45
  "peerDependencies": {
45
- "eslint": "^8.0.0",
46
+ "eslint": "^8.0.0 || ^9.0.0",
46
47
  "vuetify": "^3.0.0"
47
- }
48
+ },
49
+ "packageManager": "pnpm@9.13.2"
48
50
  }