{{ foo | formatDate('YY/MM/DD') }}
14 | `) 15 | expect(warning).toBe(null) 16 | }) 17 | 18 | it('matches a filter with a single argument', () => { 19 | const warning = check(` 20 |{{ foo | formatDate 'YY/MM/DD' }}
21 | `) 22 | expect(warning).toBeTruthy() 23 | expect(warning.fix).toBe('Replace formatDate \'YY/MM/DD\' with formatDate(\'YY/MM/DD\')') 24 | }) 25 | 26 | it('matches a filter with a multiple arguments', () => { 27 | const warning = check(` 28 |{{ foo | formatDate 'YY/MM/DD' foo 'bar' baz }}
29 | `) 30 | expect(warning).toBeTruthy() 31 | expect(warning.fix).toBe('Replace formatDate \'YY/MM/DD\' foo \'bar\' baz with formatDate(\'YY/MM/DD\', foo, \'bar\', baz)') 32 | }) 33 | 34 | it('matches a filter with a multiple arguments and other filters chained after it', () => { 35 | const warning = check(` 36 |{{ foo | formatDate 'YY/MM/DD' foo 'bar' baz | anotherFilter hi ho hi ho }}
37 | `) 38 | expect(warning).toBeTruthy() 39 | expect(warning.fix).toBe('Replace formatDate \'YY/MM/DD\' foo \'bar\' baz with formatDate(\'YY/MM/DD\', foo, \'bar\', baz)') 40 | }) 41 | 42 | it('matches a filter with a multiple arguments and a fixed filter chained after it', () => { 43 | const warning = check(` 44 |{{ foo | formatDate 'YY/MM/DD' foo 'bar' baz | anotherFilter(hi, ho, hi, ho) }}
45 | `) 46 | expect(warning).toBeTruthy() 47 | expect(warning.fix).toBe('Replace formatDate \'YY/MM/DD\' foo \'bar\' baz with formatDate(\'YY/MM/DD\', foo, \'bar\', baz)') 48 | }) 49 | 50 | it('matches a filter with a multiple arguments and a fixed filter chained before it', () => { 51 | const warning = check(` 52 |{{ foo | formatDate('YY/MM/DD' foo 'bar' baz) | anotherFilter hi ho hi ho }}
53 | `) 54 | expect(warning).toBeTruthy() 55 | expect(warning.fix).toBe('Replace anotherFilter hi ho hi ho with anotherFilter(hi, ho, hi, ho)') 56 | }) 57 | }) 58 | -------------------------------------------------------------------------------- /rules/vue/html-interpolation.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /\{\{\{\s*?(.+?)\s*?\}\}\}/, 7 | warning: function (match, interpolationContents) { 8 | return { 9 | reason: 'HTML interpolation with {{{ }}} has been removed', 10 | fix: ( 11 | 'Replace ' + chalk.red(match) + ' with ' + 12 | chalk.green('v-html="' + interpolationContents.trim() + '"') + 13 | ' on a containing element' 14 | ), 15 | docsHash: 'HTML-Interpolation', 16 | type: 'template' 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /rules/vue/html-interpolation.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/html-interpolation') 4 | 5 | describe('Rule: html-interpolation', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('matches a simple interpolation', () => { 12 | const warning = check(` 13 |{{{ foo }}}
14 | `) 15 | expect(warning).toBeTruthy() 16 | expect(warning.fix).toBe('Replace {{{ foo }}} with v-html="foo" on a containing element') 17 | }) 18 | 19 | it('matches a standalone interpolation', () => { 20 | const warning = check(` 21 | {{{ foo }}} 22 | `) 23 | expect(warning).toBeTruthy() 24 | expect(warning.fix).toBe('Replace {{{ foo }}} with v-html="foo" on a containing element') 25 | }) 26 | 27 | it('matches an interpolation with two on the same line', () => { 28 | const warning = check(` 29 | {{{ foo }}} bar {{{ baz }}} 30 | `) 31 | expect(warning).toBeTruthy() 32 | expect(warning.fix).toBe('Replace {{{ foo }}} with v-html="foo" on a containing element') 33 | }) 34 | }) 35 | -------------------------------------------------------------------------------- /rules/vue/interpolation-within-attributes-no-quotes.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /\b([\w-:@\.]+)=\{\{(.+?)\}\}/, 7 | warning: function (match, attribute, value) { 8 | return { 9 | reason: 'Interpolation within attributes has been removed', 10 | fix: ( 11 | 'Update ' + chalk.red(match) + ' to ' + 12 | chalk.green( 13 | 'v-bind:' + attribute + '="' + 14 | value.trim() + 15 | '"' 16 | ) 17 | ), 18 | docsHash: 'Interpolation-within-Attributes', 19 | type: 'template' 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /rules/vue/interpolation-within-attributes-no-quotes.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/interpolation-within-attributes-no-quotes') 4 | 5 | describe('Rule: interpolation-within-attributes-no-quotes', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('does not match a simple interpolation with quotes', () => { 12 | const warning = check(` 13 | 14 | `) 15 | expect(warning).toBe(null) 16 | }) 17 | 18 | it('does not match a more complex interpolation with quotes', () => { 19 | const warning = check(` 20 | 21 | `) 22 | expect(warning).toBe(null) 23 | }) 24 | 25 | it('does not match a more complex attribute with a more complex interpolation with quotes', () => { 26 | const warning = check(` 27 | 28 | `) 29 | expect(warning).toBe(null) 30 | }) 31 | 32 | it('does not match interpolation with a string prefix with quotes', () => { 33 | const warning = check(` 34 | 35 | `) 36 | expect(warning).toBe(null) 37 | }) 38 | 39 | it('does not match interpolation with a string suffix with quotes', () => { 40 | const warning = check(` 41 | 42 | `) 43 | expect(warning).toBe(null) 44 | }) 45 | 46 | it('does not match interpolation with both a string prefix and string suffix with quotes', () => { 47 | const warning = check(` 48 | 49 | `) 50 | expect(warning).toBe(null) 51 | }) 52 | 53 | it('does not match multiple interpolations with quotes', () => { 54 | const warning = check(` 55 | 56 | `) 57 | expect(warning).toBe(null) 58 | }) 59 | 60 | it('matches interpolation without quotes', () => { 61 | const warning = check(` 62 | 63 | `) 64 | expect(warning).toBeTruthy() 65 | expect(warning.fix).toBe('Update target={{bar}} to v-bind:target="bar"') 66 | }) 67 | }) 68 | -------------------------------------------------------------------------------- /rules/vue/interpolation-within-attributes.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /\b([\w-:@\.]+)="([^"=]*?)\{\{(.+?)\}\}([^"=]*?)"/, 7 | warning: function (match, attribute, prefixString, value, suffixString) { 8 | return { 9 | reason: 'Interpolation within attributes has been removed', 10 | fix: suffixString.indexOf('{{') === -1 && suffixString.indexOf('}}') === -1 11 | ? ( 12 | 'Update ' + chalk.red(match) + ' to ' + 13 | chalk.green( 14 | 'v-bind:' + attribute + '="' + 15 | (prefixString.length 16 | ? '\'' + prefixString.replace('\'', '\\\'') + '\' + ' 17 | : '') + 18 | value.trim() + 19 | (suffixString.length 20 | ? ' + \'' + suffixString.replace('\'', '\\\'') + '\'' 21 | : '') + 22 | '"' 23 | ) 24 | ) 25 | : ( 26 | 'Update ' + chalk.red(match) + ' to ' + 27 | 'use v-bind with a computed property' 28 | ), 29 | docsHash: 'Interpolation-within-Attributes', 30 | type: 'template' 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /rules/vue/interpolation-within-attributes.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/interpolation-within-attributes') 4 | 5 | describe('Rule: interpolation-within-attributes', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('does not match interpolations without quotes', () => { 12 | const warning = check(` 13 | 14 | `) 15 | expect(warning).toBe(null) 16 | }) 17 | 18 | it('matches a simple interpolation', () => { 19 | const warning = check(` 20 | 21 | `) 22 | expect(warning).toBeTruthy() 23 | expect(warning.fix).toBe('Update href="{{ url }}" to v-bind:href="url"') 24 | }) 25 | 26 | it('matches a more complex interpolation', () => { 27 | const warning = check(` 28 | 29 | `) 30 | expect(warning).toBeTruthy() 31 | expect(warning.fix).toBe('Update href="{{ url + \'foo\' + bar }}" to v-bind:href="url + \'foo\' + bar"') 32 | }) 33 | 34 | it('matches a more complex attribute with a more complex interpolation', () => { 35 | const warning = check(` 36 | 37 | `) 38 | expect(warning).toBeTruthy() 39 | expect(warning.fix).toBe('Update data-foo1-6="{{ url + \'foo\' + bar }}" to v-bind:data-foo1-6="url + \'foo\' + bar"') 40 | }) 41 | 42 | it('matches interpolation with a string prefix', () => { 43 | const warning = check(` 44 | 45 | `) 46 | expect(warning).toBeTruthy() 47 | expect(warning.fix).toBe('Update class="btn-{{ type }}" to v-bind:class="\'btn-\' + type"') 48 | }) 49 | 50 | it('matches interpolation with a string suffix', () => { 51 | const warning = check(` 52 | 53 | `) 54 | expect(warning).toBeTruthy() 55 | expect(warning.fix).toBe('Update class="{{ type }}-center" to v-bind:class="type + \'-center\'"') 56 | }) 57 | 58 | it('matches interpolation with both a string prefix and string suffix', () => { 59 | const warning = check(` 60 | 61 | `) 62 | expect(warning).toBeTruthy() 63 | expect(warning.fix).toBe('Update class="foo-{{ bar }}-baz" to v-bind:class="\'foo-\' + bar + \'-baz\'"') 64 | }) 65 | 66 | it('matches multiple interpolations', () => { 67 | const warning = check(` 68 | 69 | `) 70 | expect(warning).toBeTruthy() 71 | expect(warning.fix).toBe('Update class="btn-{{ type }} btn-{{ size }}" to use v-bind with a computed property') 72 | }) 73 | }) 74 | -------------------------------------------------------------------------------- /rules/vue/keep-alive-attribute.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /<[\w-]+\s+.*?\bkeep-alive\b.*?>/, 7 | warning: function (match) { 8 | return { 9 | reason: 'keep-alive is now a wrapper element, rather than an attribute', 10 | fix: ( 11 | 'Refactor ' + chalk.red('keep-alive') + ' attribute ' + 12 | 'to a ' + chalk.green('{{* foo }}
14 | `) 15 | expect(warning).toBeTruthy() 16 | expect(warning.fix).toBe('Replace {{* foo }} with v-once="foo" on a containing element') 17 | }) 18 | 19 | it('matches a simple one-time binding with a space before the star', () => { 20 | const warning = check(` 21 |{{ * foo }}
22 | `) 23 | expect(warning).toBeTruthy() 24 | expect(warning.fix).toBe('Replace {{ * foo }} with v-once="foo" on a containing element') 25 | }) 26 | 27 | it('matches a complex one-time binding', () => { 28 | const warning = check(` 29 |{{* 2 * 3 / 5 + 11 + foo + bar + 'baz' - 42 }}
30 | `) 31 | expect(warning).toBeTruthy() 32 | expect(warning.fix).toBe('Replace {{* 2 * 3 / 5 + 11 + foo + bar + \'baz\' - 42 }} with v-once="2 * 3 / 5 + 11 + foo + bar + \'baz\' - 42" on a containing element') 33 | }) 34 | }) 35 | -------------------------------------------------------------------------------- /rules/vue/prop-coerce.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = { 4 | pattern: /coerce\s*?(?::|\()/, 5 | warning: function (match) { 6 | return { 7 | reason: 'Prop coercion has been removed in favor of local computed properties', 8 | fix: 'Replace prop coercion with a local computed property', 9 | docsHash: 'coerce-Prop-Option', 10 | type: 'js' 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /rules/vue/prop-coerce.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/prop-coerce') 4 | 5 | describe('Rule: prop-coerce', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('matches coerce with ES5 function', () => { 12 | const warning = check(` 13 | coerce: function () { 14 | `) 15 | expect(warning).toBeTruthy() 16 | }) 17 | }) 18 | -------------------------------------------------------------------------------- /rules/vue/replace-false.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /\breplace\s*?:\s*?false\b/, 7 | warning: function (match) { 8 | return { 9 | reason: 'The replace option has been removed, as it provides too little convenience', 10 | fix: ( 11 | 'Delete the ' + chalk.red(match) + ' option and instead wrap your root component with an element similar to the one you\'re replacing, e.g. ' + 12 | chalk.green('el: \'#app\'') + 13 | ' with ' + 14 | chalk.green('template: \'It\'s also a good idea to explicitly add `v-bind:css="false"` for JavaScript-only transitions so that Vue can skip the CSS detection. This also prevents CSS rules from accidentally interfering with the transition.
"', () => { 33 | const warning = check(` 34 |It's also a good idea to explicitly add \`v-bind:css="false"\` for JavaScript-only transitions so that Vue can skip the CSS detection. This also prevents CSS rules from accidentally interfering with the transition.
35 | `) 36 | expect(warning).toBe(null) 37 | }) 38 | 39 | it('matches an empty transition attribute', () => { 40 | const warning = check(` 41 |foo
42 | `) 43 | expect(warning).toBeTruthy() 44 | expect(warning.fix).toBe('Replace transition attribute with either afoo
50 | `) 51 | expect(warning).toBeTruthy() 52 | expect(warning.fix).toBe('Replace transition="fade" attribute with either a14 | `) 15 | expect(warning).toBeTruthy() 16 | expect(warning.fix).toBe('Update v-el:foo to ref="foo"') 17 | }) 18 | 19 | it('matches a simple v-ref', () => { 20 | const warning = check(` 21 |
22 | `) 23 | expect(warning).toBeTruthy() 24 | expect(warning.fix).toBe('Update v-ref:foo to ref="foo"') 25 | }) 26 | 27 | it('matches v-el with dashes and camelCases it', () => { 28 | const warning = check(` 29 |
30 | `) 31 | expect(warning).toBeTruthy() 32 | expect(warning.fix).toBe('Update v-ref:foo-bar to ref="fooBar"') 33 | }) 34 | }) 35 | -------------------------------------------------------------------------------- /rules/vue/v-el-els.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /(\w+)\.\$els(\.\w+|\[.+?\])?/, 7 | warning: function (match, vm, el) { 8 | return { 9 | reason: 'v-el and v-ref merged into ref attribute', 10 | fix: ( 11 | 'Update ' + chalk.red(match) + ' to ' + 12 | chalk.green(vm + '.$refs' + (el || '')) 13 | ), 14 | docsHash: 'v-el-and-v-ref', 15 | type: 'js' 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /rules/vue/v-el-els.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/v-el-els') 4 | 5 | describe('Rule: v-el-els', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('matches this.$els', () => { 12 | const warning = check(` 13 | this.$els 14 | `) 15 | expect(warning).toBeTruthy() 16 | expect(warning.fix).toBe('Update this.$els to this.$refs') 17 | }) 18 | 19 | it('matches vm.$els', () => { 20 | const warning = check(` 21 | vm.$els 22 | `) 23 | expect(warning).toBeTruthy() 24 | expect(warning.fix).toBe('Update vm.$els to vm.$refs') 25 | }) 26 | 27 | it('matches vm.$els.fooBar', () => { 28 | const warning = check(` 29 | vm.$els.fooBar 30 | `) 31 | expect(warning).toBeTruthy() 32 | expect(warning.fix).toBe('Update vm.$els.fooBar to vm.$refs.fooBar') 33 | }) 34 | 35 | it('matches vm.$els.fooBar with assignment', () => { 36 | const warning = check(` 37 | vm.$els.fooBar = 'baz' 38 | `) 39 | expect(warning).toBeTruthy() 40 | expect(warning.fix).toBe('Update vm.$els.fooBar to vm.$refs.fooBar') 41 | }) 42 | 43 | it('matches vm.$els[\'fooBar\']', () => { 44 | const warning = check(` 45 | vm.$els['fooBar'] 46 | `) 47 | expect(warning).toBeTruthy() 48 | expect(warning.fix).toBe('Update vm.$els[\'fooBar\'] to vm.$refs[\'fooBar\']') 49 | }) 50 | 51 | it('matches vm.$els[\'fooBar\'] with assignment', () => { 52 | const warning = check(` 53 | vm.$els['fooBar'] = 'baz' 54 | `) 55 | expect(warning).toBeTruthy() 56 | expect(warning.fix).toBe('Update vm.$els[\'fooBar\'] to vm.$refs[\'fooBar\']') 57 | }) 58 | 59 | it('matches vm.$els[fooBar] with assignment', () => { 60 | const warning = check(` 61 | vm.$els[fooBar] = 'baz' 62 | `) 63 | expect(warning).toBeTruthy() 64 | expect(warning.fix).toBe('Update vm.$els[fooBar] to vm.$refs[fooBar]') 65 | }) 66 | }) 67 | -------------------------------------------------------------------------------- /rules/vue/v-for-argument-order-with-object.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /\bv-for="\((key)\s*?,\s*?(\w+)\).+?"/, 7 | warning: function (match, keyVar, valueVar) { 8 | return { 9 | reason: 'Argument order for v-for has been updated to match JavaScript conventions', 10 | fix: ( 11 | 'Switch argument order in ' + chalk.red(match) + ' to ' + 12 | chalk.green('(' + valueVar + ', ' + keyVar + ')') 13 | ), 14 | docsHash: 'v-for-Argument-Order-for-Objects', 15 | type: 'template' 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /rules/vue/v-for-argument-order-with-object.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/v-for-argument-order-with-object') 4 | 5 | describe('Rule: v-for-argument-order-with-object', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('does not match a v-for the correct argument order', () => { 12 | const warning = check(` 13 |
{{ value }}, {{ key }}
14 | `) 15 | expect(warning).toBe(null) 16 | }) 17 | 18 | it('does not match a v-for without a key', () => { 19 | const warning = check(` 20 |{{ value }}
21 | `) 22 | expect(warning).toBe(null) 23 | }) 24 | 25 | it('matches a v-for key as the first property', () => { 26 | const warning = check(` 27 |{{ value }}, {{ key }}
28 | `) 29 | expect(warning).toBeTruthy() 30 | expect(warning.fix).toBe('Switch argument order in v-for="(key, value) in object" to (value, key)') 31 | }) 32 | }) 33 | -------------------------------------------------------------------------------- /rules/vue/v-for-argument-order.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /\bv-for="\(([ijk]|in?d?e?x?)\s*?,\s*?(\w+)\).+?"/, 7 | warning: function (match, indexVar, itemVar) { 8 | return { 9 | reason: 'Argument order for v-for has been updated to match JavaScript conventions', 10 | fix: ( 11 | 'Switch argument order in ' + chalk.red(match) + ' to ' + 12 | chalk.green('(' + itemVar + ', ' + indexVar + ')') 13 | ), 14 | docsHash: 'v-for-Argument-Order-for-Arrays', 15 | type: 'template' 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /rules/vue/v-for-argument-order.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/v-for-argument-order') 4 | 5 | describe('Rule: v-for-argument-order', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('does not match a v-for the correct argument order', () => { 12 | const warning = check(` 13 |{{ item }}, {{ index }}
14 | `) 15 | expect(warning).toBe(null) 16 | }) 17 | 18 | it('matches a v-for with index as first argument', () => { 19 | const warning = check(` 20 |{{ item }}, {{ index }}
21 | `) 22 | expect(warning).toBeTruthy() 23 | expect(warning.fix).toBe('Switch argument order in v-for="(index, item) in items" to (item, index)') 24 | }) 25 | 26 | it('matches a v-for with i as first argument', () => { 27 | const warning = check(` 28 |{{ item }}, {{ i }}
29 | `) 30 | expect(warning).toBeTruthy() 31 | expect(warning.fix).toBe('Switch argument order in v-for="(i, item) in items" to (item, i)') 32 | }) 33 | 34 | it('matches a v-for with j as first argument', () => { 35 | const warning = check(` 36 |{{ item }}, {{ j }}
37 | `) 38 | expect(warning).toBeTruthy() 39 | expect(warning.fix).toBe('Switch argument order in v-for="(j, item) in items" to (item, j)') 40 | }) 41 | 42 | it('matches a v-for with k as first argument', () => { 43 | const warning = check(` 44 |{{ item }}, {{ k }}
45 | `) 46 | expect(warning).toBeTruthy() 47 | expect(warning.fix).toBe('Switch argument order in v-for="(k, item) in items" to (item, k)') 48 | }) 49 | 50 | it('matches a v-for with ind as first argument', () => { 51 | const warning = check(` 52 |{{ item }}, {{ ind }}
53 | `) 54 | expect(warning).toBeTruthy() 55 | expect(warning.fix).toBe('Switch argument order in v-for="(ind, item) in items" to (item, ind)') 56 | }) 57 | }) 58 | -------------------------------------------------------------------------------- /rules/vue/v-for-implicit-index-and-key.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /\$(index|key)\b/, 7 | warning: function (match) { 8 | const exampleVFor = match === '$index' 9 | ? 'v-for="(item, index) in items"' 10 | : 'v-for="(value, key) in object"' 11 | return { 12 | reason: match + ' has been removed to avoid implicitly defined (i.e. "magic") variables', 13 | fix: ( 14 | 'Rename ' + chalk.red(match) + ' to ' + 15 | chalk.green(match.slice(1)) + ' and explicity declare it (e.g. ' + exampleVFor + ')' 16 | ), 17 | docsHash: 'index-and-key', 18 | type: 'template' 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /rules/vue/v-for-implicit-index-and-key.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/v-for-implicit-index-and-key') 4 | 5 | describe('Rule: v-for-implicit-index-and-key', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('matches an interpolated $index', () => { 12 | const warning = check(` 13 | {{ $index }} 14 | `) 15 | expect(warning).toBeTruthy() 16 | expect(warning.fix).toBe('Rename $index to index and explicity declare it (e.g. v-for="(item, index) in items")') 17 | }) 18 | 19 | it('matches a bound $index', () => { 20 | const warning = check(` 21 | 22 | `) 23 | expect(warning).toBeTruthy() 24 | expect(warning.fix).toBe('Rename $index to index and explicity declare it (e.g. v-for="(item, index) in items")') 25 | }) 26 | 27 | it('matches an interpolated $key', () => { 28 | const warning = check(` 29 | {{ $key }} 30 | `) 31 | expect(warning).toBeTruthy() 32 | expect(warning.fix).toBe('Rename $key to key and explicity declare it (e.g. v-for="(value, key) in object")') 33 | }) 34 | 35 | it('matches a bound $key', () => { 36 | const warning = check(` 37 | 38 | `) 39 | expect(warning).toBeTruthy() 40 | expect(warning.fix).toBe('Rename $key to key and explicity declare it (e.g. v-for="(value, key) in object")') 41 | }) 42 | 43 | it('does not match other words', () => { 44 | const warning = check(` 45 | {{ $keyword }} 46 | `) 47 | expect(warning).toBe(null) 48 | }) 49 | }) 50 | -------------------------------------------------------------------------------- /rules/vue/v-for-v-model-primitive-value.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /<[^>]+\b(?:(v-for=["'][^>]+?["'])[^>]+?\b(v-model=["'][^\[\.]+["'])|(v-model=["'][^\[\.]+["'])[^>]+?(v-for=["'][^>]+?["']))[^>]*?>/, 7 | warning: function (match, vForBefore, vModelAfter, vModelBefore, vForAfter) { 8 | const vFor = vForBefore || vForAfter 9 | const vModel = vModelBefore || vModelAfter 10 | return { 11 | reason: 'v-for iterated primitives are no longer supported in v-model', 12 | fix: 'Replace ' + chalk.red(vFor) + ' with an array of objects, then update ' + chalk.red(vModel) + ' to bind to a property on each object', 13 | docsHash: 'v-model-with-v-for-Iterated-Primitive-Values', 14 | type: 'template' 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /rules/vue/v-for-v-model-primitive-value.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/v-for-v-model-primitive-value') 4 | 5 | describe('Rule: v-for-v-model-primitive-value', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('matches a simple v-for primitive and v-model combination, with v-model second', () => { 12 | const warning = check(` 13 | 14 | `) 15 | expect(warning).toBeTruthy() 16 | expect(warning.fix).toBe('Replace v-for="item in items" with an array of objects, then update v-model="item" to bind to a property on each object') 17 | }) 18 | 19 | it('matches a v-for primitive and v-model combination, with v-model second, surrounded by other noise', () => { 20 | const warning = check(` 21 | 22 | `) 23 | expect(warning).toBeTruthy() 24 | expect(warning.fix).toBe('Replace v-for="item in items" with an array of objects, then update v-model="item" to bind to a property on each object') 25 | }) 26 | 27 | it('matches a simple v-for primitive and v-model combination, with v-model first', () => { 28 | const warning = check(` 29 | 30 | `) 31 | expect(warning).toBeTruthy() 32 | expect(warning.fix).toBe('Replace v-for="item in items" with an array of objects, then update v-model="item" to bind to a property on each object') 33 | }) 34 | 35 | it('matches a v-for primitive and v-model combination, with v-model second, surrounded by other noise', () => { 36 | const warning = check(` 37 | 38 | `) 39 | expect(warning).toBeTruthy() 40 | expect(warning.fix).toBe('Replace v-for="item in items" with an array of objects, then update v-model="item" to bind to a property on each object') 41 | }) 42 | }) 43 | -------------------------------------------------------------------------------- /rules/vue/v-leave-class.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /(\.([\w-]+)-leave)[^\w-]/, 7 | warning: function (match, cssClass, name) { 8 | return { 9 | reason: 'v-leave class now defines a starting state for leave transitions, rather than the ending state', 10 | fix: ( 11 | 'Replace ' + chalk.red(cssClass) + ' with ' + 12 | chalk.green('.' + name + '-leave-active') + 13 | ' (if it\'s left over from Vue 1.x)' 14 | ), 15 | docsHash: 'Transitions', 16 | type: 'style' 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /rules/vue/v-leave-class.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/v-leave-class') 4 | 5 | describe('Rule: v-leave-class', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('does not match a v-leave-active class', () => { 12 | const warning = check(` 13 | .v-leave-active { 14 | `) 15 | expect(warning).toBe(null) 16 | }) 17 | 18 | it('matches the default v-leave class', () => { 19 | const warning = check(` 20 | .v-leave { 21 | `) 22 | expect(warning).toBeTruthy() 23 | expect(warning.fix).toBe('Replace .v-leave with .v-leave-active (if it\'s left over from Vue 1.x)') 24 | }) 25 | 26 | it('matches a named leave class', () => { 27 | const warning = check(` 28 | .super-fade-leave { 29 | `) 30 | expect(warning).toBeTruthy() 31 | expect(warning.fix).toBe('Replace .super-fade-leave with .super-fade-leave-active (if it\'s left over from Vue 1.x)') 32 | }) 33 | }) 34 | -------------------------------------------------------------------------------- /rules/vue/v-on-keycodes.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /\bVue\s*\.\s*directive\s*\(\s*['"`]on['"`]\s*\)\s*\.\s*keyCodes\b/, 7 | warning: function (match) { 8 | return { 9 | reason: 'Vue.config.keyCodes is the new, more direct way to define custom keyCodes', 10 | fix: ( 11 | 'Replace ' + chalk.red(match) + ' with ' + 12 | chalk.green('Vue.config.keyCodes') 13 | ), 14 | docsHash: 'Vue-directive-39-on-39-keyCodes', 15 | type: 'js' 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /rules/vue/v-on-keycodes.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/v-on-keycodes') 4 | 5 | describe('Rule: v-on-keycodes', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('matches a simple keyCode setting with the old syntax', () => { 12 | const warning = check(` 13 | Vue.directive('on').keyCodes.f1 = 112 14 | `) 15 | expect(warning).toBeTruthy() 16 | expect(warning.fix).toBe('Replace Vue.directive(\'on\').keyCodes with Vue.config.keyCodes') 17 | }) 18 | }) 19 | -------------------------------------------------------------------------------- /rules/vue/v-show-with-v-else.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /<[^>]+\b(?:v-else[^>]+?\b(v-show=["'][^\[\.]+["'])|(v-show=["'][^\[\.]+["'])[^>]+?v-else)[^>]*?>/, 7 | warning: function (match, vShowAfter, vShowBefore) { 8 | return { 9 | reason: 'When used with v-show, a negation expression must be used instead of v-else, e.g. v-if="!foo"', 10 | fix: ( 11 | 'Replace ' + chalk.red('v-else') + ' with a ' + 12 | chalk.green('v-if') + ' negation expression' 13 | ), 14 | docsHash: 'v-else-with-v-show', 15 | type: 'template' 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /rules/vue/v-show-with-v-else.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/v-show-with-v-else') 4 | 5 | describe('Rule: v-show-with-v-else', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('does not match a simple v-else', () => { 12 | const warning = check(` 13 | 14 | `) 15 | expect(warning).toBe(null) 16 | }) 17 | 18 | it('matches a simple v-show with v-else, with v-else first', () => { 19 | const warning = check(` 20 | 21 | `) 22 | expect(warning).toBeTruthy() 23 | expect(warning.fix).toBe('Replace v-else with a v-if negation expression') 24 | }) 25 | 26 | it('matches a simple v-show with v-else, with v-show first', () => { 27 | const warning = check(` 28 | 29 | `) 30 | expect(warning).toBeTruthy() 31 | expect(warning.fix).toBe('Replace v-else with a v-if negation expression') 32 | }) 33 | }) 34 | -------------------------------------------------------------------------------- /rules/vue/v-transition-class.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /(\.([\w-]+)-transition)[^\w-]/, 7 | warning: function (match, cssClass, name) { 8 | return { 9 | reason: 'v-transition class has been replaced by the standard classes used by Angular and React CSSTransitionGroup', 10 | fix: ( 11 | 'Replace ' + chalk.red(cssClass) + ' with ' + 12 | chalk.green( 13 | '.' + name + '-enter-active, ' + 14 | '.' + name + '-leave-active' 15 | ) 16 | ), 17 | docsHash: 'transition-Attribute', 18 | type: 'style' 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /rules/vue/v-transition-class.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/v-transition-class') 4 | 5 | describe('Rule: v-transition-class', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('does not match v-transition-foo class', () => { 12 | const warning = check(` 13 | .v-transition-foo { 14 | `) 15 | expect(warning).toBe(null) 16 | }) 17 | 18 | it('matches the default v-transition class', () => { 19 | const warning = check(` 20 | .v-transition { 21 | `) 22 | expect(warning).toBeTruthy() 23 | expect(warning.fix).toBe('Replace .v-transition with .v-enter-active, .v-leave-active') 24 | }) 25 | 26 | it('matches a named transition class', () => { 27 | const warning = check(` 28 | .super-fade-transition { 29 | `) 30 | expect(warning).toBeTruthy() 31 | expect(warning.fix).toBe('Replace .super-fade-transition with .super-fade-enter-active, .super-fade-leave-active') 32 | }) 33 | }) 34 | -------------------------------------------------------------------------------- /rules/vue/vm-delete.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /(this|vm|self)\.\$delete\s*?\(\s*([^,\)]+?)\s*\)/, 7 | warning: function (match, vm, key) { 8 | const property = /['"`]\w+['"`]/.test(key) 9 | ? '.' + key.replace(/['"`]/g, '') 10 | : '[' + key + ']' 11 | return { 12 | reason: 'vm.$delete is now just an alias for Vue.delete and it is no longer possible to delete top-level reactive properties', 13 | fix: ( 14 | 'Replace ' + chalk.red(match) + ' with ' + 15 | chalk.green(vm + property + ' = null') 16 | ), 17 | docsHash: 'vm-delete', 18 | type: 'js' 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /rules/vue/vm-delete.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/vm-delete') 4 | 5 | describe('Rule: vm-delete', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('does not match this.$delete(myObj, key)', () => { 12 | const warning = check(` 13 | this.$delete(myObj, key) 14 | `) 15 | expect(warning).toBe(null) 16 | }) 17 | 18 | it('matches this.$delete(\'key\')', () => { 19 | const warning = check(` 20 | this.$delete('key') 21 | `) 22 | expect(warning).toBeTruthy() 23 | expect(warning.fix).toBe('Replace this.$delete(\'key\') with this.key = null') 24 | }) 25 | 26 | it('matches this.$delete(\'key-with-dashes\')', () => { 27 | const warning = check(` 28 | this.$delete('key-with-dashes') 29 | `) 30 | expect(warning).toBeTruthy() 31 | expect(warning.fix).toBe('Replace this.$delete(\'key-with-dashes\') with this[\'key-with-dashes\'] = null') 32 | }) 33 | 34 | it('matches this.$delete(`key-${with}-interpolated-string`)', () => { 35 | const warning = check(` 36 | this.$delete(\`key-\$\{with\}-interpolated-string\`) 37 | `) 38 | expect(warning).toBeTruthy() 39 | expect(warning.fix).toBe('Replace this.$delete(`key-${with}-interpolated-string`) with this[`key-${with}-interpolated-string`] = null') 40 | }) 41 | 42 | it('matches vm.$delete(\'key\')', () => { 43 | const warning = check(` 44 | vm.$delete('key') 45 | `) 46 | expect(warning).toBeTruthy() 47 | expect(warning.fix).toBe('Replace vm.$delete(\'key\') with vm.key = null') 48 | }) 49 | 50 | it('matches self.$delete(\'key\')', () => { 51 | const warning = check(` 52 | self.$delete('key') 53 | `) 54 | expect(warning).toBeTruthy() 55 | expect(warning.fix).toBe('Replace self.$delete(\'key\') with self.key = null') 56 | }) 57 | }) 58 | -------------------------------------------------------------------------------- /rules/vue/vm-dom-methods.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /(this|vm|self)\.\$(appendTo|before|after|remove)\s*?\(\s*?(.+?)\s*?\)/, 7 | warning: function (match, vm, method, elementOrSelector) { 8 | const element = /['"`]/.test(elementOrSelector) 9 | ? 'document.querySelector(' + elementOrSelector + ')' 10 | : elementOrSelector 11 | const replacement = { 12 | appendTo: element + '.appendChild(' + vm + '.$el' + ')', 13 | before: element + '.parentNode.insertBefore(' + vm + '.$el, ' + element + ')', 14 | after: element + '.parentNode.insertBefore(' + vm + '.$el, ' + element + '.nextSibling)', 15 | remove: vm + '.$el.remove()' 16 | }[method] 17 | return { 18 | reason: 'vm.$' + method + ' has been removed in favor of simply using the native DOM API on vm.$el', 19 | fix: ( 20 | 'Replace ' + chalk.red(match) + ' with ' + 21 | chalk.green(replacement) 22 | ), 23 | docsHash: 'vm-' + method + '', 24 | type: 'js' 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /rules/vue/vm-dom-methods.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/vm-dom-methods') 4 | 5 | describe('Rule: vm-dom-methods', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('matches this.$appendTo(myEl)', () => { 12 | const warning = check(` 13 | this.$appendTo(myEl) 14 | `) 15 | expect(warning).toBeTruthy() 16 | expect(warning.fix).toBe('Replace this.$appendTo(myEl) with myEl.appendChild(this.$el)') 17 | }) 18 | 19 | it('matches this.$appendTo("#my-el")', () => { 20 | const warning = check(` 21 | this.$appendTo("#my-el") 22 | `) 23 | expect(warning).toBeTruthy() 24 | expect(warning.fix).toBe('Replace this.$appendTo("#my-el") with document.querySelector("#my-el").appendChild(this.$el)') 25 | }) 26 | 27 | it('matches vm.$appendTo("#my-el")', () => { 28 | const warning = check(` 29 | vm.$appendTo("#my-el") 30 | `) 31 | expect(warning).toBeTruthy() 32 | expect(warning.fix).toBe('Replace vm.$appendTo("#my-el") with document.querySelector("#my-el").appendChild(vm.$el)') 33 | }) 34 | 35 | it('matches self.$appendTo("#my-el")', () => { 36 | const warning = check(` 37 | self.$appendTo("#my-el") 38 | `) 39 | expect(warning).toBeTruthy() 40 | expect(warning.fix).toBe('Replace self.$appendTo("#my-el") with document.querySelector("#my-el").appendChild(self.$el)') 41 | }) 42 | 43 | it('matches this.$before(myEl)', () => { 44 | const warning = check(` 45 | this.$before(myEl) 46 | `) 47 | expect(warning).toBeTruthy() 48 | expect(warning.fix).toBe('Replace this.$before(myEl) with myEl.parentNode.insertBefore(this.$el, myEl)') 49 | }) 50 | 51 | it('matches this.$after(myEl)', () => { 52 | const warning = check(` 53 | this.$after(myEl) 54 | `) 55 | expect(warning).toBeTruthy() 56 | expect(warning.fix).toBe('Replace this.$after(myEl) with myEl.parentNode.insertBefore(this.$el, myEl.nextSibling)') 57 | }) 58 | 59 | it('matches this.$remove(myEl)', () => { 60 | const warning = check(` 61 | this.$remove(myEl) 62 | `) 63 | expect(warning).toBeTruthy() 64 | expect(warning.fix).toBe('Replace this.$remove(myEl) with this.$el.remove()') 65 | }) 66 | }) 67 | -------------------------------------------------------------------------------- /rules/vue/vm-eval.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /(this|vm|self)\.\$eval\s*?\(\s*?["'`](.+?)["'`]\s*?\)/, 7 | warning: function (match, vm, property) { 8 | return { 9 | reason: 'vm.$eval has been removed, as it has no real use', 10 | fix: ( 11 | 'Replace ' + chalk.red(match) + ' with a solution using normal JavaScript' 12 | ), 13 | docsHash: 'vm-eval', 14 | type: 'js' 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /rules/vue/vm-eval.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/vm-eval') 4 | 5 | describe('Rule: vm-eval', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('matches this.$eval(\'msg | uppercase\')', () => { 12 | const warning = check(` 13 | this.$eval('msg | uppercase') 14 | `) 15 | expect(warning).toBeTruthy() 16 | expect(warning.fix).toBe('Replace this.$eval(\'msg | uppercase\') with a solution using normal JavaScript') 17 | }) 18 | 19 | it('matches vm.$eval(\'msg | uppercase\')', () => { 20 | const warning = check(` 21 | vm.$eval('msg | uppercase') 22 | `) 23 | expect(warning).toBeTruthy() 24 | expect(warning.fix).toBe('Replace vm.$eval(\'msg | uppercase\') with a solution using normal JavaScript') 25 | }) 26 | 27 | it('matches self.$eval(\'msg | uppercase\')', () => { 28 | const warning = check(` 29 | self.$eval('msg | uppercase') 30 | `) 31 | expect(warning).toBeTruthy() 32 | expect(warning.fix).toBe('Replace self.$eval(\'msg | uppercase\') with a solution using normal JavaScript') 33 | }) 34 | }) 35 | -------------------------------------------------------------------------------- /rules/vue/vm-get.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /(this|vm|self)\.\$get\s*?\(\s*?["'`](.+?)["'`]\s*?\)/, 7 | warning: function (match, vm, property) { 8 | return { 9 | reason: 'vm.$get has been removed, in favor of simply accessing properties the normal JavaScript way', 10 | fix: ( 11 | 'Replace ' + chalk.red(match) + ' with ' + 12 | chalk.green( 13 | vm + '.' + property 14 | ) 15 | ), 16 | docsHash: 'vm-get', 17 | type: 'js' 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /rules/vue/vm-get.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/vm-get') 4 | 5 | describe('Rule: vm-get', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('matches this.$get(\'foo\')', () => { 12 | const warning = check(` 13 | this.$get('foo') 14 | `) 15 | expect(warning).toBeTruthy() 16 | expect(warning.fix).toBe('Replace this.$get(\'foo\') with this.foo') 17 | }) 18 | 19 | it('matches this.$get(\'foo.bar.baz\')', () => { 20 | const warning = check(` 21 | this.$get('foo.bar.baz') 22 | `) 23 | expect(warning).toBeTruthy() 24 | expect(warning.fix).toBe('Replace this.$get(\'foo.bar.baz\') with this.foo.bar.baz') 25 | }) 26 | 27 | it('matches vm.$get(\'foo.bar.baz\')', () => { 28 | const warning = check(` 29 | vm.$get('foo.bar.baz') 30 | `) 31 | expect(warning).toBeTruthy() 32 | expect(warning.fix).toBe('Replace vm.$get(\'foo.bar.baz\') with vm.foo.bar.baz') 33 | }) 34 | 35 | it('matches self.$get(\'foo.bar.baz\')', () => { 36 | const warning = check(` 37 | self.$get('foo.bar.baz') 38 | `) 39 | expect(warning).toBeTruthy() 40 | expect(warning.fix).toBe('Replace self.$get(\'foo.bar.baz\') with self.foo.bar.baz') 41 | }) 42 | }) 43 | -------------------------------------------------------------------------------- /rules/vue/vm-interpolate.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /(this|vm|self)\.\$interpolate\s*?\(\s*?["'`](.+?)["'`]\s*?\)/, 7 | warning: function (match, vm, property) { 8 | return { 9 | reason: 'vm.$interpolate has been removed, as it has no real use', 10 | fix: ( 11 | 'Replace ' + chalk.red(match) + ' with a solution using normal JavaScript' 12 | ), 13 | docsHash: 'vm-interpolate', 14 | type: 'js' 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /rules/vue/vm-interpolate.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/vm-interpolate') 4 | 5 | describe('Rule: vm-interpolate', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('matches this.$interpolate(\'{{msg}} world!\')', () => { 12 | const warning = check(` 13 | this.$interpolate('{{msg}} world!') 14 | `) 15 | expect(warning).toBeTruthy() 16 | expect(warning.fix).toBe('Replace this.$interpolate(\'{{msg}} world!\') with a solution using normal JavaScript') 17 | }) 18 | 19 | it('matches vm.$interpolate(\'{{msg}} world!\')', () => { 20 | const warning = check(` 21 | vm.$interpolate('{{msg}} world!') 22 | `) 23 | expect(warning).toBeTruthy() 24 | expect(warning.fix).toBe('Replace vm.$interpolate(\'{{msg}} world!\') with a solution using normal JavaScript') 25 | }) 26 | 27 | it('matches self.$interpolate(\'{{msg}} world!\')', () => { 28 | const warning = check(` 29 | self.$interpolate('{{msg}} world!') 30 | `) 31 | expect(warning).toBeTruthy() 32 | expect(warning.fix).toBe('Replace self.$interpolate(\'{{msg}} world!\') with a solution using normal JavaScript') 33 | }) 34 | }) 35 | -------------------------------------------------------------------------------- /rules/vue/vm-log.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /(this|vm|self)\.\$log\s*?\(\s*?["'`](.+?)["'`]\s*?\)/, 7 | warning: function (match, vm, property) { 8 | return { 9 | reason: 'vm.$log has been removed, because the Vue Devtools offer a better debugging experience', 10 | fix: ( 11 | 'Delete ' + chalk.red(match) + ' and install the Vue Devtools instead: ' + chalk.underline.green('https://github.com/vuejs/vue-devtools') 12 | ), 13 | docsHash: 'vm-log', 14 | type: 'js' 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /rules/vue/vm-log.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/vm-log') 4 | 5 | describe('Rule: vm-log', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('matches this.$log(\'{{msg}} world!\')', () => { 12 | const warning = check(` 13 | this.$log('{{msg}} world!') 14 | `) 15 | expect(warning).toBeTruthy() 16 | expect(warning.fix).toBe('Delete this.$log(\'{{msg}} world!\') and install the Vue Devtools instead: https://github.com/vuejs/vue-devtools') 17 | }) 18 | 19 | it('matches vm.$log(\'{{msg}} world!\')', () => { 20 | const warning = check(` 21 | vm.$log('{{msg}} world!') 22 | `) 23 | expect(warning).toBeTruthy() 24 | expect(warning.fix).toBe('Delete vm.$log(\'{{msg}} world!\') and install the Vue Devtools instead: https://github.com/vuejs/vue-devtools') 25 | }) 26 | 27 | it('matches self.$log(\'{{msg}} world!\')', () => { 28 | const warning = check(` 29 | self.$log('{{msg}} world!') 30 | `) 31 | expect(warning).toBeTruthy() 32 | expect(warning.fix).toBe('Delete self.$log(\'{{msg}} world!\') and install the Vue Devtools instead: https://github.com/vuejs/vue-devtools') 33 | }) 34 | }) 35 | -------------------------------------------------------------------------------- /rules/vue/vm-set.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /(this|vm|self)\.\$set\s*?\(\s*['"`]([\w\.]+?)\.(\w+)['"`]\s*,\s*([^,]+?)\s*\)/, 7 | warning: function (match, vm, objectPath, leafProperty, value) { 8 | return { 9 | reason: 'vm.$set is now just an alias for Vue.set', 10 | fix: ( 11 | 'Replace ' + chalk.red(match) + ' with ' + 12 | chalk.green( 13 | vm + '.$set(' + 14 | vm + '.' + objectPath + ', ' + 15 | '\'' + leafProperty + '\'' + ', ' + 16 | value + 17 | ')' 18 | ) 19 | ), 20 | docsHash: 'vm-set', 21 | type: 'js' 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /rules/vue/vm-set.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/vm-set') 4 | 5 | describe('Rule: vm-set', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('does not match this.$set(obj, \'foo\', 42)', () => { 12 | const warning = check(` 13 | this.$set(obj, 'foo', 42) 14 | `) 15 | expect(warning).toBe(null) 16 | }) 17 | 18 | it('matches this.$set(\'foo.bar\', 42)', () => { 19 | const warning = check(` 20 | this.$set('foo.bar', 42) 21 | `) 22 | expect(warning).toBeTruthy() 23 | expect(warning.fix).toBe('Replace this.$set(\'foo.bar\', 42) with this.$set(this.foo, \'bar\', 42)') 24 | }) 25 | 26 | it('matches this.$set(\'foo.bar.baz\', 42)', () => { 27 | const warning = check(` 28 | this.$set('foo.bar.baz', 42) 29 | `) 30 | expect(warning).toBeTruthy() 31 | expect(warning.fix).toBe('Replace this.$set(\'foo.bar.baz\', 42) with this.$set(this.foo.bar, \'baz\', 42)') 32 | }) 33 | 34 | it('matches vm.$set(\'foo.bar.baz\', 42)', () => { 35 | const warning = check(` 36 | vm.$set('foo.bar.baz', 42) 37 | `) 38 | expect(warning).toBeTruthy() 39 | expect(warning.fix).toBe('Replace vm.$set(\'foo.bar.baz\', 42) with vm.$set(vm.foo.bar, \'baz\', 42)') 40 | }) 41 | 42 | it('matches self.$set(\'foo.bar.baz\', 42)', () => { 43 | const warning = check(` 44 | self.$set('foo.bar.baz', 42) 45 | `) 46 | expect(warning).toBeTruthy() 47 | expect(warning.fix).toBe('Replace self.$set(\'foo.bar.baz\', 42) with self.$set(self.foo.bar, \'baz\', 42)') 48 | }) 49 | }) 50 | -------------------------------------------------------------------------------- /rules/vue/vue-config-async.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /Vue\.config\.async/, 7 | warning: function (match) { 8 | return { 9 | reason: 'Async is now always required for performance', 10 | fix: 'Delete references to ' + chalk.red('Vue.config.async'), 11 | docsHash: 'Vue-config-async', 12 | type: 'js' 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /rules/vue/vue-config-async.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/vue-config-async') 4 | 5 | describe('Rule: vue-config-async', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('matches async set to true', () => { 12 | const warning = check(` 13 | Vue.config.async = true 14 | `) 15 | expect(warning).toBeTruthy() 16 | }) 17 | 18 | it('matches async set to false', () => { 19 | const warning = check(` 20 | Vue.config.async = false 21 | `) 22 | expect(warning).toBeTruthy() 23 | }) 24 | }) 25 | -------------------------------------------------------------------------------- /rules/vue/vue-config-debug.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /Vue\.config\.debug/, 7 | warning: function (match) { 8 | return { 9 | reason: 'Warnings come with stack traces by default now, making this option redundant', 10 | fix: 'Delete references to ' + chalk.red('Vue.config.debug'), 11 | docsHash: 'Vue-config-debug', 12 | type: 'js' 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /rules/vue/vue-config-debug.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/vue-config-debug') 4 | 5 | describe('Rule: vue-config-debug', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('matches debug set to true', () => { 12 | const warning = check(` 13 | Vue.config.debug = true 14 | `) 15 | expect(warning).toBeTruthy() 16 | }) 17 | 18 | it('matches debug set to false', () => { 19 | const warning = check(` 20 | Vue.config.debug = false 21 | `) 22 | expect(warning).toBeTruthy() 23 | }) 24 | }) 25 | -------------------------------------------------------------------------------- /rules/vue/vue-config-delimiters.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /Vue\.config\.delimiters/, 7 | warning: function (match) { 8 | return { 9 | reason: 'Delimiters are now a component-level option', 10 | fix: 'Refactor ' + chalk.red('Vue.config.delimiters') + ' to its component-level equivalent', 11 | docsHash: 'Vue-config-delimiters', 12 | type: 'js' 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /rules/vue/vue-config-delimiters.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/vue-config-delimiters') 4 | 5 | describe('Rule: vue-config-delimiters', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('matches delimiters set to true', () => { 12 | const warning = check(` 13 | Vue.config.delimiters = true 14 | `) 15 | expect(warning).toBeTruthy() 16 | }) 17 | 18 | it('matches delimiters set to false', () => { 19 | const warning = check(` 20 | Vue.config.delimiters = false 21 | `) 22 | expect(warning).toBeTruthy() 23 | }) 24 | }) 25 | -------------------------------------------------------------------------------- /rules/vue/vue-config-unsafe-delimiters.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /Vue\.config\.unsafeDelimiters/, 7 | warning: function (match) { 8 | return { 9 | reason: 'Unsafe interpolation has been removed', 10 | fix: 'Delete ' + chalk.red('Vue.config.unsafeDelimiters') + ' and replace all instances of unsafe interpolations with ' + chalk.green('v-html'), 11 | docsHash: 'Vue-config-unsafeDelimiters', 12 | type: 'js' 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /rules/vue/vue-config-unsafe-delimiters.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/vue-config-unsafe-delimiters') 4 | 5 | describe('Rule: vue-config-unsafe-delimiters', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('matches unsafeDelimiters set to true', () => { 12 | const warning = check(` 13 | Vue.config.unsafeDelimiters = true 14 | `) 15 | expect(warning).toBeTruthy() 16 | }) 17 | 18 | it('matches unsafeDelimiters set to false', () => { 19 | const warning = check(` 20 | Vue.config.unsafeDelimiters = false 21 | `) 22 | expect(warning).toBeTruthy() 23 | }) 24 | }) 25 | -------------------------------------------------------------------------------- /rules/vue/vue-delete-vm.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /Vue\.delete\(\s*?(this|vm|self)\s*?,([^,]+?)\)/, 7 | warning: function (match, vm, property) { 8 | return { 9 | reason: 'Vue.set and Vue.delete no longer work on Vue instances - it is now mandatory to properly declare all top-level reactive properties in the data option', 10 | fix: ( 11 | 'Replace ' + chalk.red(match) + ' with ' + 12 | chalk.green( 13 | 'Vue.delete(' + 14 | vm + '.newTopLevelObject, ' + 15 | property.trim() + 16 | ')' 17 | ) + 18 | ', then scope ' + property.replace(/['"]/g, '').trim() + ' underneath newTopLevelObject, rather than declaring it as a top-level $data property' 19 | ), 20 | docsHash: 'Vue-set-and-Vue-delete-on-Vue-instances', 21 | type: 'js' 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /rules/vue/vue-delete-vm.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/vue-delete-vm') 4 | 5 | describe('Rule: vue-delete-vm', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('does not match Vue.delete(foo, \'bar\')', () => { 12 | const warning = check(` 13 | Vue.delete(foo, 'bar') 14 | `) 15 | expect(warning).toBe(null) 16 | }) 17 | 18 | it('matches Vue.delete(this, \'foo\')', () => { 19 | const warning = check(` 20 | Vue.delete(this, 'foo') 21 | `) 22 | expect(warning).toBeTruthy() 23 | expect(warning.fix).toBe('Replace Vue.delete(this, \'foo\') with Vue.delete(this.newTopLevelObject, \'foo\'), then scope foo underneath newTopLevelObject, rather than declaring it as a top-level $data property') 24 | }) 25 | 26 | it('matches Vue.delete(vm, \'foo\')', () => { 27 | const warning = check(` 28 | Vue.delete(vm, 'foo') 29 | `) 30 | expect(warning).toBeTruthy() 31 | expect(warning.fix).toBe('Replace Vue.delete(vm, \'foo\') with Vue.delete(vm.newTopLevelObject, \'foo\'), then scope foo underneath newTopLevelObject, rather than declaring it as a top-level $data property') 32 | }) 33 | 34 | it('matches Vue.delete(self, \'foo\')', () => { 35 | const warning = check(` 36 | Vue.delete(self, 'foo') 37 | `) 38 | expect(warning).toBeTruthy() 39 | expect(warning.fix).toBe('Replace Vue.delete(self, \'foo\') with Vue.delete(self.newTopLevelObject, \'foo\'), then scope foo underneath newTopLevelObject, rather than declaring it as a top-level $data property') 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /rules/vue/vue-dependency.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /("vue"\s*:\s*)"[^\d"]*?[^2-9]\.\d+\.\d+"/, 7 | warning: function (match, preVersion) { 8 | return { 9 | reason: 'If you are using pre-2.0 Vue through NPM, you have to update it in your package.json file', 10 | fix: ( 11 | 'Replace ' + chalk.red(match) + ' with ' + 12 | chalk.green( 13 | preVersion + '"^2.0.0"' 14 | ) + 15 | ', then run: npm install' 16 | ), 17 | docsHash: '', 18 | type: 'package.json' 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /rules/vue/vue-dependency.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/vue-dependency') 4 | 5 | describe('Rule: vue-dependency', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('does not match "^2.0.0"', () => { 12 | const warning = check(` 13 | "vue": "^2.0.0" 14 | `) 15 | expect(warning).toBe(null) 16 | }) 17 | 18 | it('does not match "^2.0.0" with comma', () => { 19 | const warning = check(` 20 | "vue": "^2.0.0", 21 | `) 22 | expect(warning).toBe(null) 23 | }) 24 | 25 | it('does not match "^2.0.1"', () => { 26 | const warning = check(` 27 | "vue": "^2.0.1" 28 | `) 29 | expect(warning).toBe(null) 30 | }) 31 | 32 | it('does not match "2.0.0"', () => { 33 | const warning = check(` 34 | "vue": "2.0.0" 35 | `) 36 | expect(warning).toBe(null) 37 | }) 38 | 39 | it('is not limited to pre 3.0 versions', () => { 40 | const warning = check(` 41 | "vue": "3.0.0" 42 | `) 43 | expect(warning).toBe(null) 44 | }) 45 | 46 | it('is not limited to pre 3.0 versions, with comma', () => { 47 | const warning = check(` 48 | "vue": "3.0.0", 49 | `) 50 | expect(warning).toBe(null) 51 | }) 52 | 53 | it('does not match vuex "1.0.0"', () => { 54 | const warning = check(` 55 | "vuex": "1.0.0" 56 | `) 57 | expect(warning).toBe(null) 58 | }) 59 | 60 | it('matches "^1.0.27"', () => { 61 | const warning = check(` 62 | "vue": "^1.0.27" 63 | `) 64 | expect(warning).toBeTruthy() 65 | expect(warning.fix).toBe('Replace "vue": "^1.0.27" with "vue": "^2.0.0", then run: npm install') 66 | }) 67 | 68 | it('matches "^1.0.27" with comma', () => { 69 | const warning = check(` 70 | "vue": "^1.0.27", 71 | `) 72 | expect(warning).toBeTruthy() 73 | expect(warning.fix).toBe('Replace "vue": "^1.0.27" with "vue": "^2.0.0", then run: npm install') 74 | }) 75 | 76 | it('matches "1.0.27"', () => { 77 | const warning = check(` 78 | "vue": "1.0.27", 79 | `) 80 | expect(warning).toBeTruthy() 81 | expect(warning.fix).toBe('Replace "vue": "1.0.27" with "vue": "^2.0.0", then run: npm install') 82 | }) 83 | 84 | it('matches "0.12.1"', () => { 85 | const warning = check(` 86 | "vue": "0.12.1", 87 | `) 88 | expect(warning).toBeTruthy() 89 | expect(warning.fix).toBe('Replace "vue": "0.12.1" with "vue": "^2.0.0", then run: npm install') 90 | }) 91 | }) 92 | -------------------------------------------------------------------------------- /rules/vue/vue-directive.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /Vue\.directive\s*\(\s*(['"`].+['"`])/, 7 | warning: function (match, name) { 8 | return { 9 | reason: 'Directives have been vastly reduced in scope and components are preferred in most use cases', 10 | fix: ( 11 | 'Check ' + chalk.red('Vue.directive(' + name + ')') + ' to make sure its syntax has been updated and for anything beyond simple DOM manipulations, refactor to a component' 12 | ), 13 | docsHash: 'Custom-Directives-simplified', 14 | type: 'js' 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /rules/vue/vue-directive.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/vue-directive') 4 | 5 | describe('Rule: vue-directive', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('matches a directive declaration', () => { 12 | const warning = check(` 13 | Vue.directive('foo', { 14 | `) 15 | expect(warning).toBeTruthy() 16 | expect(warning.fix).toBe('Check Vue.directive(\'foo\') to make sure its syntax has been updated and for anything beyond simple DOM manipulations, refactor to a component') 17 | }) 18 | 19 | it('matches a directive declaration with double quotes', () => { 20 | const warning = check(` 21 | Vue.directive("foo", { 22 | `) 23 | expect(warning).toBeTruthy() 24 | expect(warning.fix).toBe('Check Vue.directive("foo") to make sure its syntax has been updated and for anything beyond simple DOM manipulations, refactor to a component') 25 | }) 26 | }) 27 | -------------------------------------------------------------------------------- /rules/vue/vue-element-directive.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /Vue\.elementDirective\s*\(\s*(['"`].+['"`])/, 7 | warning: function (match, name) { 8 | return { 9 | reason: 'Element directives have been removed in favor of components', 10 | fix: ( 11 | 'Replace ' + chalk.red('Vue.elementDirective(' + name + ')') + ' with a component' 12 | ), 13 | docsHash: 'Vue-elementDirective', 14 | type: 'js' 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /rules/vue/vue-element-directive.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/vue-element-directive') 4 | 5 | describe('Rule: vue-element-directive', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('matches an element directive declaration', () => { 12 | const warning = check(` 13 | Vue.elementDirective('foo', { 14 | `) 15 | expect(warning).toBeTruthy() 16 | expect(warning.fix).toBe('Replace Vue.elementDirective(\'foo\') with a component') 17 | }) 18 | 19 | it('matches an element directive declaration with double quotes', () => { 20 | const warning = check(` 21 | Vue.elementDirective("foo", { 22 | `) 23 | expect(warning).toBeTruthy() 24 | expect(warning.fix).toBe('Replace Vue.elementDirective("foo") with a component') 25 | }) 26 | }) 27 | -------------------------------------------------------------------------------- /rules/vue/vue-loader-dependency.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /("vue-loader"\s*:\s*)"[^\d"]*?[^9]\.\d+\.\d+"/, 7 | warning: function (match, preVersion) { 8 | return { 9 | reason: 'vue-loader 9.0 is the earliest supported version compatible with Vue 2.0', 10 | fix: ( 11 | 'Replace ' + chalk.red(match) + ' with ' + 12 | chalk.green( 13 | preVersion + '"^9.0.0"' 14 | ) + 15 | ', then run: npm install' 16 | ), 17 | docsHash: '', 18 | type: 'package.json' 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /rules/vue/vue-loader-dependency.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/vue-loader-dependency') 4 | 5 | describe('Rule: vue-loader-dependency', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('does not match "^9.0.0"', () => { 12 | const warning = check(` 13 | "vue-loader": "^9.0.0" 14 | `) 15 | expect(warning).toBe(null) 16 | }) 17 | 18 | it('does not match "^9.0.0" with comma', () => { 19 | const warning = check(` 20 | "vue-loader": "^9.0.0", 21 | `) 22 | expect(warning).toBe(null) 23 | }) 24 | 25 | it('does not match "^9.0.1"', () => { 26 | const warning = check(` 27 | "vue-loader": "^9.0.1" 28 | `) 29 | expect(warning).toBe(null) 30 | }) 31 | 32 | it('does not match "9.0.0"', () => { 33 | const warning = check(` 34 | "vue-loader": "9.0.0" 35 | `) 36 | expect(warning).toBe(null) 37 | }) 38 | 39 | it('does not match vuex "9.0.0"', () => { 40 | const warning = check(` 41 | "vuex": "9.0.0" 42 | `) 43 | expect(warning).toBe(null) 44 | }) 45 | 46 | it('matches "^7.1.5"', () => { 47 | const warning = check(` 48 | "vue-loader": "^7.1.5" 49 | `) 50 | expect(warning).toBeTruthy() 51 | expect(warning.fix).toBe('Replace "vue-loader": "^7.1.5" with "vue-loader": "^9.0.0", then run: npm install') 52 | }) 53 | 54 | it('matches "^7.1.5" with comma', () => { 55 | const warning = check(` 56 | "vue-loader": "^7.1.5", 57 | `) 58 | expect(warning).toBeTruthy() 59 | expect(warning.fix).toBe('Replace "vue-loader": "^7.1.5" with "vue-loader": "^9.0.0", then run: npm install') 60 | }) 61 | 62 | it('matches "7.1.5"', () => { 63 | const warning = check(` 64 | "vue-loader": "7.1.5", 65 | `) 66 | expect(warning).toBeTruthy() 67 | expect(warning.fix).toBe('Replace "vue-loader": "7.1.5" with "vue-loader": "^9.0.0", then run: npm install') 68 | }) 69 | 70 | it('matches "0.12.1"', () => { 71 | const warning = check(` 72 | "vue-loader": "0.12.1", 73 | `) 74 | expect(warning).toBeTruthy() 75 | expect(warning.fix).toBe('Replace "vue-loader": "0.12.1" with "vue-loader": "^9.0.0", then run: npm install') 76 | }) 77 | }) 78 | -------------------------------------------------------------------------------- /rules/vue/vue-partial.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /Vue\.partial\s*\(\s*(['"`].+['"`])/, 7 | warning: function (match, name) { 8 | return { 9 | reason: 'Partials have been removed in favor of functional components', 10 | fix: ( 11 | 'Replace ' + chalk.red('Vue.partial(' + name + ')') + ' with a normal component that receives props - or a functional component in performance-critical situations' 12 | ), 13 | docsHash: 'Vue-partial', 14 | type: 'js' 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /rules/vue/vue-partial.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/vue-partial') 4 | 5 | describe('Rule: vue-partial', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('matches a partial declaration', () => { 12 | const warning = check(` 13 | Vue.partial('foo', { 14 | `) 15 | expect(warning).toBeTruthy() 16 | expect(warning.fix).toBe('Replace Vue.partial(\'foo\') with a normal component that receives props - or a functional component in performance-critical situations') 17 | }) 18 | 19 | it('matches a partial declaration with double quotes', () => { 20 | const warning = check(` 21 | Vue.partial("foo", { 22 | `) 23 | expect(warning).toBeTruthy() 24 | expect(warning.fix).toBe('Replace Vue.partial("foo") with a normal component that receives props - or a functional component in performance-critical situations') 25 | }) 26 | }) 27 | -------------------------------------------------------------------------------- /rules/vue/vue-set-vm.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /(Vue\.set|(?:this|vm|self)\.\$set)\(\s*?(this|vm|self)\s*?,([^,]+?),([^,]+?)\)/, 7 | warning: function (match, command, vm, property, value) { 8 | const formattedProperty = property.replace(/['"]/g, '').trim() 9 | return { 10 | reason: 'Vue.set and Vue.delete no longer work on Vue instances - it is now mandatory to properly declare all top-level reactive properties in the data option', 11 | fix: ( 12 | 'Replace ' + chalk.red(match) + ' with ' + 13 | chalk.green( 14 | vm + '.' + formattedProperty + ' = ' + value.trim() 15 | ) + 16 | ' and declare ' + formattedProperty + ' in the data option with an initial value' 17 | ), 18 | docsHash: 'Vue-set-and-Vue-delete-on-Vue-instances', 19 | type: 'js' 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /rules/vue/vue-set-vm.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const check = createRuleChecker('vue/vue-set-vm') 4 | 5 | describe('Rule: vue-set-vm', () => { 6 | it('does not match an empty line', () => { 7 | const warning = check('') 8 | expect(warning).toBe(null) 9 | }) 10 | 11 | it('does not match Vue.set(foo, \'bar\', 42)', () => { 12 | const warning = check(` 13 | Vue.set(foo, 'bar', 42) 14 | `) 15 | expect(warning).toBe(null) 16 | }) 17 | 18 | it('matches Vue.set(this, \'foo\', 42)', () => { 19 | const warning = check(` 20 | Vue.set(this, 'foo', 42) 21 | `) 22 | expect(warning).toBeTruthy() 23 | expect(warning.fix).toBe('Replace Vue.set(this, \'foo\', 42) with this.foo = 42 and declare foo in the data option with an initial value') 24 | }) 25 | 26 | it('matches Vue.set(vm, \'foo\', 42)', () => { 27 | const warning = check(` 28 | Vue.set(vm, 'foo', 42) 29 | `) 30 | expect(warning).toBeTruthy() 31 | expect(warning.fix).toBe('Replace Vue.set(vm, \'foo\', 42) with vm.foo = 42 and declare foo in the data option with an initial value') 32 | }) 33 | 34 | it('matches Vue.set(self, \'foo\', 42)', () => { 35 | const warning = check(` 36 | Vue.set(self, 'foo', 42) 37 | `) 38 | expect(warning).toBeTruthy() 39 | expect(warning.fix).toBe('Replace Vue.set(self, \'foo\', 42) with self.foo = 42 and declare foo in the data option with an initial value') 40 | }) 41 | 42 | it('matches vm.$set(this, \'foo\', 42)', () => { 43 | const warning = check(` 44 | vm.$set(this, 'foo', 42) 45 | `) 46 | expect(warning).toBeTruthy() 47 | expect(warning.fix).toBe('Replace vm.$set(this, \'foo\', 42) with this.foo = 42 and declare foo in the data option with an initial value') 48 | }) 49 | }) 50 | -------------------------------------------------------------------------------- /rules/vue/vue-transition.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var chalk = require('chalk') 4 | 5 | module.exports = { 6 | pattern: /Vue\.transition\s*\(\s*(['"`].+['"`])/, 7 | warning: function (match, name) { 8 | return { 9 | reason: 'Vue.transition has been removed, as the new transition system uses components for reusable transitions', 10 | fix: ( 11 | 'Replace ' + chalk.red('Vue.transition(' + name + ')') + ' with a component that uses the new ' + 12 | chalk.green('