Skip to content

Commit 7e4ebde

Browse files
committed
feat(RFC0005): provide autofix fix for deprecated v-bind.prop.sync modifier
1 parent 7fcd2eb commit 7e4ebde

File tree

3 files changed

+57
-3
lines changed

3 files changed

+57
-3
lines changed

docs/rules/no-deprecated-v-bind-sync.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ description: disallow use of deprecated `.sync` modifier on `v-bind` directive (
77
# vue/no-deprecated-v-bind-sync
88
> disallow use of deprecated `.sync` modifier on `v-bind` directive (in Vue.js 3.0.0+)
99
10+
- :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
11+
1012
## :book: Rule Details
1113

1214
This rule reports use of deprecated `.sync` modifier on `v-bind` directive (in Vue.js 3.0.0+)
1315

14-
<eslint-code-block :rules="{'vue/no-deprecated-v-bind-sync': ['error']}">
16+
<eslint-code-block fix :rules="{'vue/no-deprecated-v-bind-sync': ['error']}">
1517

1618
```vue
1719
<template>
@@ -22,6 +24,7 @@ This rule reports use of deprecated `.sync` modifier on `v-bind` directive (in V
2224
2325
<!-- ✗ BAD -->
2426
<MyComponent v-bind:propName.sync="foo"/>
27+
<MyComponent v-bind:[dynamiArg].sync="foo"/>
2528
<MyComponent v-bind.sync="foo"/>
2629
<MyComponent :propName.sync="foo"/>
2730
</template>

lib/rules/no-deprecated-v-bind-sync.js

+12-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ module.exports = {
2222
category: undefined,
2323
url: 'https://eslint.vuejs.org/rules/no-deprecated-v-bind-sync.html'
2424
},
25-
fixable: null,
25+
fixable: 'code',
2626
schema: [],
2727
messages: {
2828
syncModifierIsDeprecated: "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead."
@@ -35,7 +35,17 @@ module.exports = {
3535
context.report({
3636
node,
3737
loc: node.loc,
38-
messageId: 'syncModifierIsDeprecated'
38+
messageId: 'syncModifierIsDeprecated',
39+
fix: (fixer) => {
40+
const isUsingSpreadSyntax = node.key.argument == null
41+
const hasMultipleModifiers = node.key.modifiers.length > 1
42+
if (isUsingSpreadSyntax || hasMultipleModifiers) {
43+
return
44+
}
45+
46+
const bindArgument = context.getSourceCode().getText(node.key.argument)
47+
return fixer.replaceText(node.key, `v-model:${bindArgument}`)
48+
}
3949
})
4050
}
4151
}

tests/lib/rules/no-deprecated-v-bind-sync.js

+41
Original file line numberDiff line numberDiff line change
@@ -30,83 +30,124 @@ ruleTester.run('no-deprecated-v-bind-sync', rule, {
3030
{
3131
filename: 'test.vue',
3232
code: "<template><MyComponent :foo='bar'/></template>"
33+
},
34+
{
35+
filename: 'test.vue',
36+
code: "<template><MyComponent v-bind:[dynamicArg]='bar'/></template>"
37+
},
38+
{
39+
filename: 'test.vue',
40+
code: "<template><MyComponent :[dynamicArg]='bar'/></template>"
3341
}
3442
],
3543

3644
invalid: [
3745
{
3846
filename: 'test.vue',
3947
code: "<template><MyComponent v-bind:foo.sync='bar'/></template>",
48+
output: "<template><MyComponent v-model:foo='bar'/></template>",
4049
errors: ["'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead."]
4150
},
4251
{
4352
filename: 'test.vue',
4453
code: "<template><MyComponent :foo.sync='bar'/></template>",
54+
output: "<template><MyComponent v-model:foo='bar'/></template>",
55+
errors: ["'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead."]
56+
},
57+
{
58+
filename: 'test.vue',
59+
code: "<template><MyComponent v-bind:[dynamicArg].sync='bar'/></template>",
60+
output: "<template><MyComponent v-model:[dynamicArg]='bar'/></template>",
61+
errors: ["'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead."]
62+
},
63+
{
64+
filename: 'test.vue',
65+
code: "<template><MyComponent :[dynamicArg].sync='bar'/></template>",
66+
output: "<template><MyComponent v-model:[dynamicArg]='bar'/></template>",
4567
errors: ["'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead."]
4668
},
4769
{
4870
filename: 'test.vue',
4971
code: "<template><MyComponent v-bind.sync='bar'/></template>",
72+
output: "<template><MyComponent v-bind.sync='bar'/></template>",
5073
errors: ["'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead."]
5174
},
5275
{
5376
filename: 'test.vue',
5477
code: '<template><MyComponent :foo.sync.unknown="foo" /></template>',
78+
output: '<template><MyComponent :foo.sync.unknown="foo" /></template>',
79+
errors: ["'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead."]
80+
},
81+
{
82+
filename: 'test.vue',
83+
code: '<template><MyComponent :[dynamicArg].sync.unknown="foo" /></template>',
84+
output: '<template><MyComponent :[dynamicArg].sync.unknown="foo" /></template>',
5585
errors: ["'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead."]
5686
},
5787
{
5888
filename: 'test.vue',
5989
code: '<template><div><div v-for="x in list"><MyComponent :foo.sync="x.foo" /></div></div></template>',
90+
output: '<template><div><div v-for="x in list"><MyComponent v-model:foo="x.foo" /></div></div></template>',
6091
errors: ["'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead."]
6192
},
6293
{
6394
filename: 'test.vue',
6495
code: '<template><div><div v-for="x in list"><MyComponent :foo.sync="foo[x]" /></div></div></template>',
96+
output: '<template><div><div v-for="x in list"><MyComponent v-model:foo="foo[x]" /></div></div></template>',
6597
errors: ["'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead."]
6698
},
6799
{
68100
filename: 'test.vue',
69101
code: '<template><div><div v-for="x in list"><MyComponent :foo.sync="foo[x - 1]" /></div></div></template>',
102+
output: '<template><div><div v-for="x in list"><MyComponent v-model:foo="foo[x - 1]" /></div></div></template>',
70103
errors: ["'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead."]
71104
},
72105
{
73106
filename: 'test.vue',
74107
code: '<template><div><div v-for="x in list"><MyComponent :foo.sync="foo[`${x}`]" /></div></div></template>',
108+
output: '<template><div><div v-for="x in list"><MyComponent v-model:foo="foo[`${x}`]" /></div></div></template>',
75109
errors: ["'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead."]
76110
},
77111
{
78112
filename: 'test.vue',
79113
code: '<template><div><div v-for="x in list"><MyComponent :foo.sync="foo[`prefix_${x}`]" /></div></div></template>',
114+
output: '<template><div><div v-for="x in list"><MyComponent v-model:foo="foo[`prefix_${x}`]" /></div></div></template>',
80115
errors: ["'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead."]
81116
},
82117
{
83118
filename: 'test.vue',
84119
code: '<template><div><div v-for="x in list"><MyComponent :foo.sync="foo[x ? x : \'_\']" /></div></div></template>',
120+
output: '<template><div><div v-for="x in list"><MyComponent v-model:foo="foo[x ? x : \'_\']" /></div></div></template>',
85121
errors: ["'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead."]
86122
},
87123
{
88124
filename: 'test.vue',
89125
code: '<template><div><div v-for="x in list"><MyComponent :foo.sync="foo[x || \'_\']" /></div></div></template>',
126+
output: '<template><div><div v-for="x in list"><MyComponent v-model:foo="foo[x || \'_\']" /></div></div></template>',
90127
errors: ["'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead."]
91128
},
92129
{
93130
filename: 'test.vue',
94131
code: '<template><div><div v-for="x in list"><MyComponent :foo.sync="foo[x()]" /></div></div></template>',
132+
output: '<template><div><div v-for="x in list"><MyComponent v-model:foo="foo[x()]" /></div></div></template>',
95133
errors: ["'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead."]
96134
},
97135
{
98136
filename: 'test.vue',
99137
code: '<template><div><div v-for="x in list"><MyComponent :foo.sync="foo[/r/.match(x) ? 0 : 1]" /></div></div></template>',
138+
output: '<template><div><div v-for="x in list"><MyComponent v-model:foo="foo[/r/.match(x) ? 0 : 1]" /></div></div></template>',
100139
errors: ["'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead."]
101140
},
102141
{
103142
filename: 'test.vue',
104143
code: '<template><div><div v-for="x in list"><MyComponent :foo.sync="foo[typeof x]" /></div></div></template>',
144+
output: '<template><div><div v-for="x in list"><MyComponent v-model:foo="foo[typeof x]" /></div></div></template>',
105145
errors: ["'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead."]
106146
},
107147
{
108148
filename: 'test.vue',
109149
code: '<template><div><div v-for="x in list"><MyComponent :foo.sync="foo[tag`${x}`]" /></div></div></template>',
150+
output: '<template><div><div v-for="x in list"><MyComponent v-model:foo="foo[tag`${x}`]" /></div></div></template>',
110151
errors: ["'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead."]
111152
}
112153
]

0 commit comments

Comments
 (0)