diff --git a/docs/rules/attributes-order.md b/docs/rules/attributes-order.md
index cbd38eee0..2f41dfa63 100644
--- a/docs/rules/attributes-order.md
+++ b/docs/rules/attributes-order.md
@@ -25,7 +25,7 @@ This rule aims to enforce ordering of component attributes. The default order is
- `GLOBAL`
ex: 'id'
- `UNIQUE`
- ex: 'ref', 'key', 'slot'
+ ex: 'ref', 'key', 'v-slot', 'slot'
- `TWO_WAY_BINDING`
ex: 'v-model'
- `OTHER_DIRECTIVES`
diff --git a/lib/rules/array-bracket-spacing.js b/lib/rules/array-bracket-spacing.js
index e03abeb08..359a29c72 100644
--- a/lib/rules/array-bracket-spacing.js
+++ b/lib/rules/array-bracket-spacing.js
@@ -5,5 +5,8 @@
const { wrapCoreRule } = require('../utils')
-// eslint-disable-next-line
-module.exports = wrapCoreRule(require('eslint/lib/rules/array-bracket-spacing'))
+// eslint-disable-next-line no-invalid-meta
+module.exports = wrapCoreRule(
+ require('eslint/lib/rules/array-bracket-spacing'),
+ { skipDynamicArguments: true }
+)
diff --git a/lib/rules/attribute-hyphenation.js b/lib/rules/attribute-hyphenation.js
index f2c95a52f..2ead228b7 100644
--- a/lib/rules/attribute-hyphenation.js
+++ b/lib/rules/attribute-hyphenation.js
@@ -92,7 +92,10 @@ module.exports = {
VAttribute (node) {
if (!utils.isCustomComponent(node.parent.parent)) return
- const name = !node.directive ? node.key.rawName : node.key.name === 'bind' ? node.key.raw.argument : false
+ const name =
+ !node.directive ? node.key.rawName
+ : node.key.name.name === 'bind' ? node.key.argument && node.key.argument.rawName
+ : /* otherwise */ false
if (!name || isIgnoredAttribute(name)) return
reportIssue(node, name)
diff --git a/lib/rules/attributes-order.js b/lib/rules/attributes-order.js
index 8aec48c00..1808d3817 100644
--- a/lib/rules/attributes-order.js
+++ b/lib/rules/attributes-order.js
@@ -9,8 +9,13 @@ const utils = require('../utils')
// Rule Definition
// ------------------------------------------------------------------------------
-function getAttributeType (name, isDirective) {
- if (isDirective) {
+function getAttributeType (attribute, sourceCode) {
+ const isBind = attribute.directive && attribute.key.name.name === 'bind'
+ const name = isBind
+ ? (attribute.key.argument ? sourceCode.getText(attribute.key.argument) : '')
+ : (attribute.directive ? attribute.key.name.name : attribute.key.name)
+
+ if (attribute.directive && !isBind) {
if (name === 'for') {
return 'LIST_RENDERING'
} else if (name === 'if' || name === 'else-if' || name === 'else' || name === 'show' || name === 'cloak') {
@@ -23,6 +28,8 @@ function getAttributeType (name, isDirective) {
return 'EVENTS'
} else if (name === 'html' || name === 'text') {
return 'CONTENT'
+ } else if (name === 'slot') {
+ return 'UNIQUE'
} else {
return 'OTHER_DIRECTIVES'
}
@@ -38,10 +45,9 @@ function getAttributeType (name, isDirective) {
}
}
}
-function getPosition (attribute, attributePosition) {
- const attributeType = attribute.directive && attribute.key.name === 'bind'
- ? getAttributeType(attribute.key.argument, false)
- : getAttributeType(attribute.key.name, attribute.directive)
+
+function getPosition (attribute, attributePosition, sourceCode) {
+ const attributeType = getAttributeType(attribute, sourceCode)
return attributePosition.hasOwnProperty(attributeType) ? attributePosition[attributeType] : -1
}
@@ -91,8 +97,8 @@ function create (context) {
previousNode = null
},
'VAttribute' (node) {
- if ((currentPosition === -1) || (currentPosition <= getPosition(node, attributePosition))) {
- currentPosition = getPosition(node, attributePosition)
+ if ((currentPosition === -1) || (currentPosition <= getPosition(node, attributePosition, sourceCode))) {
+ currentPosition = getPosition(node, attributePosition, sourceCode)
previousNode = node
} else {
reportIssue(node, previousNode)
diff --git a/lib/rules/block-spacing.js b/lib/rules/block-spacing.js
index 7cee52355..6877ce313 100644
--- a/lib/rules/block-spacing.js
+++ b/lib/rules/block-spacing.js
@@ -5,5 +5,8 @@
const { wrapCoreRule } = require('../utils')
-// eslint-disable-next-line
-module.exports = wrapCoreRule(require('eslint/lib/rules/block-spacing'))
+// eslint-disable-next-line no-invalid-meta
+module.exports = wrapCoreRule(
+ require('eslint/lib/rules/block-spacing'),
+ { skipDynamicArguments: true }
+)
diff --git a/lib/rules/brace-style.js b/lib/rules/brace-style.js
index c64880ba5..4d0999dda 100644
--- a/lib/rules/brace-style.js
+++ b/lib/rules/brace-style.js
@@ -5,5 +5,9 @@
const { wrapCoreRule } = require('../utils')
-// eslint-disable-next-line
-module.exports = wrapCoreRule(require('eslint/lib/rules/brace-style'))
+// eslint-disable-next-line no-invalid-meta
+module.exports = wrapCoreRule(
+ require('eslint/lib/rules/brace-style'),
+ { skipDynamicArguments: true }
+)
+
diff --git a/lib/rules/key-spacing.js b/lib/rules/key-spacing.js
index c7c46fcf6..5dd81f5fc 100644
--- a/lib/rules/key-spacing.js
+++ b/lib/rules/key-spacing.js
@@ -5,5 +5,8 @@
const { wrapCoreRule } = require('../utils')
-// eslint-disable-next-line
-module.exports = wrapCoreRule(require('eslint/lib/rules/key-spacing'))
+// eslint-disable-next-line no-invalid-meta
+module.exports = wrapCoreRule(
+ require('eslint/lib/rules/key-spacing'),
+ { skipDynamicArguments: true }
+)
diff --git a/lib/rules/max-attributes-per-line.js b/lib/rules/max-attributes-per-line.js
index f9f4deb84..eca53345e 100644
--- a/lib/rules/max-attributes-per-line.js
+++ b/lib/rules/max-attributes-per-line.js
@@ -67,6 +67,7 @@ module.exports = {
},
create: function (context) {
+ const sourceCode = context.getSourceCode()
const configuration = parseOptions(context.options[0])
const multilineMaximum = configuration.multiline
const singlelinemMaximum = configuration.singleline
@@ -130,23 +131,6 @@ module.exports = {
return defaults
}
- function getPropData (prop) {
- let propType = 'Attribute'
- let propName = prop.key.name
-
- if (utils.isBindingAttribute(prop)) {
- propType = 'Binding'
- propName = prop.key.raw.argument
- } else if (utils.isEventAttribute(prop)) {
- propType = 'Event'
- propName = prop.key.raw.argument
- } else if (prop.directive) {
- propType = 'Directive'
- }
-
- return { propType, propName }
- }
-
function showErrors (attributes) {
attributes.forEach((prop, i) => {
const fix = (fixer) => {
@@ -166,8 +150,8 @@ module.exports = {
context.report({
node: prop,
loc: prop.loc,
- message: '{{propType}} "{{propName}}" should be on a new line.',
- data: getPropData(prop),
+ message: '\'{{name}}\' should be on a new line.',
+ data: { name: sourceCode.getText(prop.key) },
fix
})
})
diff --git a/lib/rules/no-confusing-v-for-v-if.js b/lib/rules/no-confusing-v-for-v-if.js
index 2ab0188b6..0102ad55c 100644
--- a/lib/rules/no-confusing-v-for-v-if.js
+++ b/lib/rules/no-confusing-v-for-v-if.js
@@ -50,7 +50,7 @@ module.exports = {
create (context) {
return utils.defineTemplateBodyVisitor(context, {
- "VAttribute[directive=true][key.name='if']" (node) {
+ "VAttribute[directive=true][key.name.name='if']" (node) {
const element = node.parent.parent
if (utils.hasDirective(element, 'for') && !isUsingIterationVar(node)) {
diff --git a/lib/rules/no-duplicate-attributes.js b/lib/rules/no-duplicate-attributes.js
index a0bd3f901..d3c20c6ec 100644
--- a/lib/rules/no-duplicate-attributes.js
+++ b/lib/rules/no-duplicate-attributes.js
@@ -24,8 +24,8 @@ function getName (attribute) {
if (!attribute.directive) {
return attribute.key.name
}
- if (attribute.key.name === 'bind') {
- return attribute.key.argument || null
+ if (attribute.key.name.name === 'bind') {
+ return (attribute.key.argument && attribute.key.argument.name) || null
}
return null
}
diff --git a/lib/rules/no-unused-components.js b/lib/rules/no-unused-components.js
index a12b7d43d..bf012d558 100644
--- a/lib/rules/no-unused-components.js
+++ b/lib/rules/no-unused-components.js
@@ -55,7 +55,7 @@ module.exports = {
usedComponents.add(node.rawName)
},
- "VAttribute[directive=true][key.name='bind'][key.argument='is']" (node) {
+ "VAttribute[directive=true][key.name.name='bind'][key.argument.name='is']" (node) {
if (
!node.value || // ``
node.value.type !== 'VExpressionContainer' ||
diff --git a/lib/rules/no-use-v-if-with-v-for.js b/lib/rules/no-use-v-if-with-v-for.js
index ef3a19aaf..754086f7e 100644
--- a/lib/rules/no-use-v-if-with-v-for.js
+++ b/lib/rules/no-use-v-if-with-v-for.js
@@ -70,7 +70,7 @@ module.exports = {
const options = context.options[0] || {}
const allowUsingIterationVar = options.allowUsingIterationVar === true // default false
return utils.defineTemplateBodyVisitor(context, {
- "VAttribute[directive=true][key.name='if']" (node) {
+ "VAttribute[directive=true][key.name.name='if']" (node) {
const element = node.parent.parent
if (utils.hasDirective(element, 'for')) {
diff --git a/lib/rules/no-v-html.js b/lib/rules/no-v-html.js
index 17a47921f..878bbbd02 100644
--- a/lib/rules/no-v-html.js
+++ b/lib/rules/no-v-html.js
@@ -22,7 +22,7 @@ module.exports = {
},
create (context) {
return utils.defineTemplateBodyVisitor(context, {
- "VAttribute[directive=true][key.name='html']" (node) {
+ "VAttribute[directive=true][key.name.name='html']" (node) {
context.report({
node,
loc: node.loc,
diff --git a/lib/rules/object-curly-spacing.js b/lib/rules/object-curly-spacing.js
index fc41b0d36..db049bbf1 100644
--- a/lib/rules/object-curly-spacing.js
+++ b/lib/rules/object-curly-spacing.js
@@ -5,5 +5,8 @@
const { wrapCoreRule } = require('../utils')
-// eslint-disable-next-line
-module.exports = wrapCoreRule(require('eslint/lib/rules/object-curly-spacing'))
+// eslint-disable-next-line no-invalid-meta
+module.exports = wrapCoreRule(
+ require('eslint/lib/rules/object-curly-spacing'),
+ { skipDynamicArguments: true }
+)
diff --git a/lib/rules/require-v-for-key.js b/lib/rules/require-v-for-key.js
index 6de38f7ed..6a71e3aca 100644
--- a/lib/rules/require-v-for-key.js
+++ b/lib/rules/require-v-for-key.js
@@ -49,7 +49,7 @@ module.exports = {
}
return utils.defineTemplateBodyVisitor(context, {
- "VAttribute[directive=true][key.name='for']" (node) {
+ "VAttribute[directive=true][key.name.name='for']" (node) {
checkKey(node.parent.parent)
}
})
diff --git a/lib/rules/space-infix-ops.js b/lib/rules/space-infix-ops.js
index fb94b74b2..251004681 100644
--- a/lib/rules/space-infix-ops.js
+++ b/lib/rules/space-infix-ops.js
@@ -5,5 +5,8 @@
const { wrapCoreRule } = require('../utils')
-// eslint-disable-next-line
-module.exports = wrapCoreRule(require('eslint/lib/rules/space-infix-ops'))
+// eslint-disable-next-line no-invalid-meta
+module.exports = wrapCoreRule(
+ require('eslint/lib/rules/space-infix-ops'),
+ { skipDynamicArguments: true }
+)
diff --git a/lib/rules/space-unary-ops.js b/lib/rules/space-unary-ops.js
index 419607929..787aae6b3 100644
--- a/lib/rules/space-unary-ops.js
+++ b/lib/rules/space-unary-ops.js
@@ -5,5 +5,8 @@
const { wrapCoreRule } = require('../utils')
-// eslint-disable-next-line
-module.exports = wrapCoreRule(require('eslint/lib/rules/space-unary-ops'))
+// eslint-disable-next-line no-invalid-meta
+module.exports = wrapCoreRule(
+ require('eslint/lib/rules/space-unary-ops'),
+ { skipDynamicArguments: true }
+)
diff --git a/lib/rules/this-in-template.js b/lib/rules/this-in-template.js
index 0f96402eb..6e972ee96 100644
--- a/lib/rules/this-in-template.js
+++ b/lib/rules/this-in-template.js
@@ -84,6 +84,11 @@ module.exports = {
}
: {
'VExpressionContainer' (node) {
+ if (node.parent.type === 'VDirectiveKey') {
+ // We cannot use `.` in dynamic arguments because the right of the `.` becomes a modifier.
+ // For example, In `:[this.prop]` case, `:[this` is an argument and `prop]` is a modifier.
+ return
+ }
if (node.references) {
for (const reference of node.references) {
if (!scope.nodes.some(el => el.name === reference.id.name)) {
diff --git a/lib/rules/use-v-on-exact.js b/lib/rules/use-v-on-exact.js
index 3e110ec2a..bf194fd8e 100644
--- a/lib/rules/use-v-on-exact.js
+++ b/lib/rules/use-v-on-exact.js
@@ -20,18 +20,19 @@ const SYSTEM_MODIFIERS = new Set(['ctrl', 'shift', 'alt', 'meta'])
* Finds and returns all keys for event directives
*
* @param {array} attributes Element attributes
+ * @param {SourceCode} sourceCode The source code object.
* @returns {array[object]} [{ name, node, modifiers }]
*/
-function getEventDirectives (attributes) {
+function getEventDirectives (attributes, sourceCode) {
return attributes
.filter(attribute =>
attribute.directive &&
- attribute.key.name === 'on'
+ attribute.key.name.name === 'on'
)
.map(attribute => ({
- name: attribute.key.argument,
+ name: attribute.key.argument ? sourceCode.getText(attribute.key.argument) : '',
node: attribute.key,
- modifiers: attribute.key.modifiers
+ modifiers: attribute.key.modifiers.map(modifier => modifier.name)
}))
}
@@ -149,12 +150,14 @@ module.exports = {
* @returns {Object} AST event handlers.
*/
create (context) {
+ const sourceCode = context.getSourceCode()
+
return utils.defineTemplateBodyVisitor(context, {
VStartTag (node) {
if (node.attributes.length === 0) return
const isCustomComponent = utils.isCustomComponent(node.parent)
- let events = getEventDirectives(node.attributes)
+ let events = getEventDirectives(node.attributes, sourceCode)
if (isCustomComponent) {
// For components consider only events with `native` modifier
diff --git a/lib/rules/v-bind-style.js b/lib/rules/v-bind-style.js
index e2e813611..a5025ee65 100644
--- a/lib/rules/v-bind-style.js
+++ b/lib/rules/v-bind-style.js
@@ -30,23 +30,42 @@ module.exports = {
},
create (context) {
- const shorthand = context.options[0] !== 'longform'
+ const preferShorthand = context.options[0] !== 'longform'
return utils.defineTemplateBodyVisitor(context, {
- "VAttribute[directive=true][key.name='bind'][key.argument!=null]" (node) {
- if (node.key.shorthand === shorthand) {
+ "VAttribute[directive=true][key.name.name='bind'][key.argument!=null]" (node) {
+ const shorthandProp = node.key.name.rawName === '.'
+ const shorthand = node.key.name.rawName === ':' || shorthandProp
+ if (shorthand === preferShorthand) {
return
}
context.report({
node,
loc: node.loc,
- message: shorthand
- ? "Unexpected 'v-bind' before ':'."
- : "Expected 'v-bind' before ':'.",
- fix: (fixer) => shorthand
- ? fixer.removeRange([node.range[0], node.range[0] + 6])
- : fixer.insertTextBefore(node, 'v-bind')
+ message:
+ preferShorthand ? "Unexpected 'v-bind' before ':'."
+ : shorthandProp ? "Expected 'v-bind:' instead of '.'."
+ /* otherwise */ : "Expected 'v-bind' before ':'.",
+ * fix (fixer) {
+ if (preferShorthand) {
+ yield fixer.remove(node.key.name)
+ } else {
+ yield fixer.insertTextBefore(node, 'v-bind')
+
+ if (shorthandProp) {
+ // Replace `.` by `:`.
+ yield fixer.replaceText(node.key.name, ':')
+
+ // Insert `.prop` modifier if it doesn't exist.
+ const modifier = node.key.modifiers[0]
+ const isAutoGeneratedPropModifier = modifier.name === 'prop' && modifier.rawName === ''
+ if (isAutoGeneratedPropModifier) {
+ yield fixer.insertTextBefore(modifier, '.prop')
+ }
+ }
+ }
+ }
})
}
})
diff --git a/lib/rules/v-on-function-call.js b/lib/rules/v-on-function-call.js
index 5dd76b2e1..e044cf134 100644
--- a/lib/rules/v-on-function-call.js
+++ b/lib/rules/v-on-function-call.js
@@ -31,7 +31,7 @@ module.exports = {
const always = context.options[0] === 'always'
return utils.defineTemplateBodyVisitor(context, {
- "VAttribute[directive=true][key.name='on'][key.argument!=null] > VExpressionContainer > Identifier" (node) {
+ "VAttribute[directive=true][key.name.name='on'][key.argument!=null] > VExpressionContainer > Identifier" (node) {
if (!always) return
context.report({
node,
@@ -40,7 +40,7 @@ module.exports = {
})
},
- "VAttribute[directive=true][key.name='on'][key.argument!=null] VOnExpression > ExpressionStatement > *" (node) {
+ "VAttribute[directive=true][key.name.name='on'][key.argument!=null] VOnExpression > ExpressionStatement > *" (node) {
if (!always && node.type === 'CallExpression' && node.arguments.length === 0) {
context.report({
node,
diff --git a/lib/rules/v-on-style.js b/lib/rules/v-on-style.js
index a767ef1bc..191a12fcb 100644
--- a/lib/rules/v-on-style.js
+++ b/lib/rules/v-on-style.js
@@ -30,11 +30,12 @@ module.exports = {
},
create (context) {
- const shorthand = context.options[0] !== 'longform'
+ const preferShorthand = context.options[0] !== 'longform'
return utils.defineTemplateBodyVisitor(context, {
- "VAttribute[directive=true][key.name='on'][key.argument!=null]" (node) {
- if (node.key.shorthand === shorthand) {
+ "VAttribute[directive=true][key.name.name='on'][key.argument!=null]" (node) {
+ const shorthand = node.key.name.rawName === '@'
+ if (shorthand === preferShorthand) {
return
}
@@ -42,10 +43,10 @@ module.exports = {
context.report({
node,
loc: node.loc,
- message: shorthand
+ message: preferShorthand
? "Expected '@' instead of 'v-on:'."
: "Expected 'v-on:' instead of '@'.",
- fix: (fixer) => shorthand
+ fix: (fixer) => preferShorthand
? fixer.replaceTextRange([pos, pos + 5], '@')
: fixer.replaceTextRange([pos, pos + 1], 'v-on:')
})
diff --git a/lib/rules/valid-v-bind.js b/lib/rules/valid-v-bind.js
index ce47a1db8..f8bc3519f 100644
--- a/lib/rules/valid-v-bind.js
+++ b/lib/rules/valid-v-bind.js
@@ -35,14 +35,14 @@ module.exports = {
create (context) {
return utils.defineTemplateBodyVisitor(context, {
- "VAttribute[directive=true][key.name='bind']" (node) {
+ "VAttribute[directive=true][key.name.name='bind']" (node) {
for (const modifier of node.key.modifiers) {
- if (!VALID_MODIFIERS.has(modifier)) {
+ if (!VALID_MODIFIERS.has(modifier.name)) {
context.report({
node,
loc: node.key.loc,
message: "'v-bind' directives don't support the modifier '{{name}}'.",
- data: { name: modifier }
+ data: { name: modifier.name }
})
}
}
diff --git a/lib/rules/valid-v-cloak.js b/lib/rules/valid-v-cloak.js
index b64e6c6b6..b1676a083 100644
--- a/lib/rules/valid-v-cloak.js
+++ b/lib/rules/valid-v-cloak.js
@@ -29,7 +29,7 @@ module.exports = {
create (context) {
return utils.defineTemplateBodyVisitor(context, {
- "VAttribute[directive=true][key.name='cloak']" (node) {
+ "VAttribute[directive=true][key.name.name='cloak']" (node) {
if (node.key.argument) {
context.report({
node,
diff --git a/lib/rules/valid-v-else-if.js b/lib/rules/valid-v-else-if.js
index 67c5a05c2..a4b5987ed 100644
--- a/lib/rules/valid-v-else-if.js
+++ b/lib/rules/valid-v-else-if.js
@@ -29,7 +29,7 @@ module.exports = {
create (context) {
return utils.defineTemplateBodyVisitor(context, {
- "VAttribute[directive=true][key.name='else-if']" (node) {
+ "VAttribute[directive=true][key.name.name='else-if']" (node) {
const element = node.parent.parent
if (!utils.prevElementHasIf(element)) {
diff --git a/lib/rules/valid-v-else.js b/lib/rules/valid-v-else.js
index d2d63a9ee..e54122377 100644
--- a/lib/rules/valid-v-else.js
+++ b/lib/rules/valid-v-else.js
@@ -29,7 +29,7 @@ module.exports = {
create (context) {
return utils.defineTemplateBodyVisitor(context, {
- "VAttribute[directive=true][key.name='else']" (node) {
+ "VAttribute[directive=true][key.name.name='else']" (node) {
const element = node.parent.parent
if (!utils.prevElementHasIf(element)) {
diff --git a/lib/rules/valid-v-for.js b/lib/rules/valid-v-for.js
index 75edaf07c..28cf30c1a 100644
--- a/lib/rules/valid-v-for.js
+++ b/lib/rules/valid-v-for.js
@@ -117,7 +117,7 @@ module.exports = {
const sourceCode = context.getSourceCode()
return utils.defineTemplateBodyVisitor(context, {
- "VAttribute[directive=true][key.name='for']" (node) {
+ "VAttribute[directive=true][key.name.name='for']" (node) {
const element = node.parent.parent
checkKey(context, node, element)
diff --git a/lib/rules/valid-v-html.js b/lib/rules/valid-v-html.js
index 9ec65933b..1aeaeef15 100644
--- a/lib/rules/valid-v-html.js
+++ b/lib/rules/valid-v-html.js
@@ -29,7 +29,7 @@ module.exports = {
create (context) {
return utils.defineTemplateBodyVisitor(context, {
- "VAttribute[directive=true][key.name='html']" (node) {
+ "VAttribute[directive=true][key.name.name='html']" (node) {
if (node.key.argument) {
context.report({
node,
diff --git a/lib/rules/valid-v-if.js b/lib/rules/valid-v-if.js
index e08ccac2f..40e9259c2 100644
--- a/lib/rules/valid-v-if.js
+++ b/lib/rules/valid-v-if.js
@@ -29,7 +29,7 @@ module.exports = {
create (context) {
return utils.defineTemplateBodyVisitor(context, {
- "VAttribute[directive=true][key.name='if']" (node) {
+ "VAttribute[directive=true][key.name.name='if']" (node) {
const element = node.parent.parent
if (utils.hasDirective(element, 'else')) {
diff --git a/lib/rules/valid-v-model.js b/lib/rules/valid-v-model.js
index b9e16ab3a..d969f2c0e 100644
--- a/lib/rules/valid-v-model.js
+++ b/lib/rules/valid-v-model.js
@@ -91,7 +91,7 @@ module.exports = {
create (context) {
return utils.defineTemplateBodyVisitor(context, {
- "VAttribute[directive=true][key.name='model']" (node) {
+ "VAttribute[directive=true][key.name.name='model']" (node) {
const element = node.parent.parent
const name = element.name
@@ -121,12 +121,12 @@ module.exports = {
}
for (const modifier of node.key.modifiers) {
- if (!VALID_MODIFIERS.has(modifier)) {
+ if (!VALID_MODIFIERS.has(modifier.name)) {
context.report({
node,
loc: node.loc,
message: "'v-model' directives don't support the modifier '{{name}}'.",
- data: { name: modifier }
+ data: { name: modifier.name }
})
}
}
diff --git a/lib/rules/valid-v-on.js b/lib/rules/valid-v-on.js
index 76034844d..37e531f51 100644
--- a/lib/rules/valid-v-on.js
+++ b/lib/rules/valid-v-on.js
@@ -27,7 +27,8 @@ const VERB_MODIFIERS = new Set([
// https://www.w3.org/TR/uievents-key/
const KEY_ALIASES = new Set(keyAliases)
-function isValidModifier (modifier, customModifiers) {
+function isValidModifier (modifierNode, customModifiers) {
+ const modifier = modifierNode.name
return (
// built-in aliases
VALID_MODIFIERS.has(modifier) ||
@@ -74,21 +75,21 @@ module.exports = {
const sourceCode = context.getSourceCode()
return utils.defineTemplateBodyVisitor(context, {
- "VAttribute[directive=true][key.name='on']" (node) {
+ "VAttribute[directive=true][key.name.name='on']" (node) {
for (const modifier of node.key.modifiers) {
if (!isValidModifier(modifier, customModifiers)) {
context.report({
node,
loc: node.loc,
message: "'v-on' directives don't support the modifier '{{modifier}}'.",
- data: { modifier }
+ data: { modifier: modifier.name }
})
}
}
if (
!utils.hasAttributeValue(node) &&
- !node.key.modifiers.some(VERB_MODIFIERS.has, VERB_MODIFIERS)
+ !node.key.modifiers.some(modifier => VERB_MODIFIERS.has(modifier.name))
) {
if (node.value && sourceCode.getText(node.value.expression)) {
const value = sourceCode.getText(node.value)
diff --git a/lib/rules/valid-v-once.js b/lib/rules/valid-v-once.js
index f294a8098..e0ada5558 100644
--- a/lib/rules/valid-v-once.js
+++ b/lib/rules/valid-v-once.js
@@ -29,7 +29,7 @@ module.exports = {
create (context) {
return utils.defineTemplateBodyVisitor(context, {
- "VAttribute[directive=true][key.name='once']" (node) {
+ "VAttribute[directive=true][key.name.name='once']" (node) {
if (node.key.argument) {
context.report({
node,
diff --git a/lib/rules/valid-v-pre.js b/lib/rules/valid-v-pre.js
index eaf4ef038..40231a462 100644
--- a/lib/rules/valid-v-pre.js
+++ b/lib/rules/valid-v-pre.js
@@ -29,7 +29,7 @@ module.exports = {
create (context) {
return utils.defineTemplateBodyVisitor(context, {
- "VAttribute[directive=true][key.name='pre']" (node) {
+ "VAttribute[directive=true][key.name.name='pre']" (node) {
if (node.key.argument) {
context.report({
node,
diff --git a/lib/rules/valid-v-show.js b/lib/rules/valid-v-show.js
index 0855e92cc..6eb5183ca 100644
--- a/lib/rules/valid-v-show.js
+++ b/lib/rules/valid-v-show.js
@@ -29,7 +29,7 @@ module.exports = {
create (context) {
return utils.defineTemplateBodyVisitor(context, {
- "VAttribute[directive=true][key.name='show']" (node) {
+ "VAttribute[directive=true][key.name.name='show']" (node) {
if (node.key.argument) {
context.report({
node,
diff --git a/lib/rules/valid-v-text.js b/lib/rules/valid-v-text.js
index d1f823da3..c23d1f1de 100644
--- a/lib/rules/valid-v-text.js
+++ b/lib/rules/valid-v-text.js
@@ -29,7 +29,7 @@ module.exports = {
create (context) {
return utils.defineTemplateBodyVisitor(context, {
- "VAttribute[directive=true][key.name='text']" (node) {
+ "VAttribute[directive=true][key.name.name='text']" (node) {
if (node.key.argument) {
context.report({
node,
diff --git a/lib/utils/indent-common.js b/lib/utils/indent-common.js
index 28e68b0a8..227e85adc 100644
--- a/lib/utils/indent-common.js
+++ b/lib/utils/indent-common.js
@@ -879,13 +879,13 @@ module.exports.defineVisitor = function create (context, tokenStore, defaultOpti
return processIgnores({
VAttribute (node) {
const keyToken = tokenStore.getFirstToken(node)
- const eqToken = tokenStore.getFirstToken(node, 1)
+ const eqToken = tokenStore.getTokenAfter(node.key)
- if (eqToken != null) {
+ if (eqToken != null && eqToken.range[1] <= node.range[1]) {
setOffset(eqToken, 1, keyToken)
- const valueToken = tokenStore.getFirstToken(node, 2)
- if (valueToken != null) {
+ const valueToken = tokenStore.getTokenAfter(eqToken)
+ if (valueToken != null && valueToken.range[1] <= node.range[1]) {
setOffset(valueToken, 1, keyToken)
}
}
diff --git a/lib/utils/index.js b/lib/utils/index.js
index e2af0257f..5a02620b3 100644
--- a/lib/utils/index.js
+++ b/lib/utils/index.js
@@ -65,10 +65,13 @@ module.exports = {
/**
* Wrap a given core rule to apply it to Vue.js template.
* @param {Rule} coreRule The core rule implementation to wrap.
- * @param {string|undefined} category The category of this rule.
+ * @param {Object|undefined} options The option of this rule.
+ * @param {string|undefined} options.category The category of this rule.
+ * @param {boolean|undefined} options.skipDynamicArguments If `true`, skip validation within dynamic arguments.
* @returns {Rule} The wrapped rule implementation.
*/
- wrapCoreRule (coreRule, category) {
+ wrapCoreRule (coreRule, options) {
+ const { category, skipDynamicArguments } = options || {}
return {
create (context) {
const tokenStore =
@@ -92,6 +95,19 @@ module.exports = {
delete handlers['Program:exit']
}
+ if (skipDynamicArguments) {
+ let withinDynamicArguments = false
+ for (const name of Object.keys(handlers)) {
+ const original = handlers[name]
+ handlers[name] = (...args) => {
+ if (withinDynamicArguments) return
+ original(...args)
+ }
+ }
+ handlers['VDirectiveKey > VExpressionContainer'] = () => { withinDynamicArguments = true }
+ handlers['VDirectiveKey > VExpressionContainer:exit'] = () => { withinDynamicArguments = false }
+ }
+
// Apply the handlers to templates.
return module.exports.defineTemplateBodyVisitor(context, handlers)
},
@@ -140,25 +156,6 @@ module.exports = {
return null
},
- /**
- * Finds attribute in the given start tag
- * @param {ASTNode} node The start tag node to check.
- * @param {string} name The attribute name to check.
- * @param {string} [value] The attribute value to check.
- * @returns {ASTNode} attribute node
- */
- findAttribute (node, name, value) {
- assert(node && node.type === 'VElement')
- return node.startTag.attributes.find(attr => (
- !attr.directive &&
- attr.key.name === name &&
- (
- value === undefined ||
- (attr.value != null && attr.value.value === value)
- )
- ))
- },
-
/**
* Check whether the given start tag has specific directive.
* @param {ASTNode} node The start tag node to check.
@@ -168,23 +165,7 @@ module.exports = {
*/
hasAttribute (node, name, value) {
assert(node && node.type === 'VElement')
- return Boolean(this.findAttribute(node, name, value))
- },
-
- /**
- * Finds directive in the given start tag
- * @param {ASTNode} node The start tag node to check.
- * @param {string} name The directive name to check.
- * @param {string} [argument] The directive argument to check.
- * @returns {ASTNode} directive node
- */
- findDirective (node, name, argument) {
- assert(node && node.type === 'VElement')
- return node.startTag.attributes.find(a =>
- a.directive &&
- a.key.name === name &&
- (argument === undefined || a.key.argument === argument)
- )
+ return Boolean(this.getAttribute(node, name, value))
},
/**
@@ -196,7 +177,7 @@ module.exports = {
*/
hasDirective (node, name, argument) {
assert(node && node.type === 'VElement')
- return Boolean(this.findDirective(node, name, argument))
+ return Boolean(this.getDirective(node, name, argument))
},
/**
@@ -242,8 +223,8 @@ module.exports = {
assert(node && node.type === 'VElement')
return node.startTag.attributes.find(a =>
a.directive &&
- a.key.name === name &&
- (argument === undefined || a.key.argument === argument)
+ a.key.name.name === name &&
+ (argument === undefined || (a.key.argument && a.key.argument.name) === argument)
)
},
@@ -284,7 +265,7 @@ module.exports = {
prev != null &&
prev.startTag.attributes.some(a =>
a.directive &&
- (a.key.name === 'if' || a.key.name === 'else-if')
+ (a.key.name.name === 'if' || a.key.name.name === 'else-if')
)
)
},
@@ -369,26 +350,6 @@ module.exports = {
return VOID_ELEMENT_NAMES.has(name)
},
- /**
- * Check whether the given attribute node is a binding
- * @param {ASTNode} attribute The attribute to check.
- * @returns {boolean}
- */
- isBindingAttribute (attribute) {
- return attribute.directive &&
- attribute.key.name === 'bind' &&
- attribute.key.argument
- },
-
- /**
- * Check whether the given attribute node is an event
- * @param {ASTNode} name The attribute to check.
- * @returns {boolean}
- */
- isEventAttribute (attribute) {
- return attribute.directive && attribute.key.name === 'on'
- },
-
/**
* Parse member expression node to get array with all of its parts
* @param {ASTNode} node MemberExpression
diff --git a/package.json b/package.json
index afa4e7569..195060c87 100644
--- a/package.json
+++ b/package.json
@@ -46,7 +46,7 @@
"eslint": "^5.0.0"
},
"dependencies": {
- "vue-eslint-parser": "^5.0.0"
+ "vue-eslint-parser": "^6.0.2"
},
"devDependencies": {
"@types/node": "^4.2.16",
diff --git a/tests/lib/rules/array-bracket-spacing.js b/tests/lib/rules/array-bracket-spacing.js
index 509ebb1d1..2aafe9ba5 100644
--- a/tests/lib/rules/array-bracket-spacing.js
+++ b/tests/lib/rules/array-bracket-spacing.js
@@ -21,19 +21,32 @@ tester.run('array-bracket-spacing', rule, {
{
code: '
',
options: ['always']
+ },
+ '
',
+ {
+ code: '
',
+ options: ['always']
+ },
+ '
',
+ {
+ code: '
',
+ options: ['always']
}
],
invalid: [
{
code: '
',
+ output: '
',
errors: ["There should be no space after '['."]
},
{
code: '
',
+ output: '
',
errors: ["There should be no space before ']'."]
},
{
code: '
',
+ output: '
',
errors: [
"There should be no space after '['.",
"There should be no space before ']'."
@@ -42,16 +55,19 @@ tester.run('array-bracket-spacing', rule, {
{
code: '
',
options: ['never'],
+ output: '
',
errors: ["There should be no space after '['."]
},
{
code: '
',
options: ['never'],
+ output: '
',
errors: ["There should be no space before ']'."]
},
{
code: '
',
options: ['never'],
+ output: '
',
errors: [
"There should be no space after '['.",
"There should be no space before ']'."
@@ -60,16 +76,28 @@ tester.run('array-bracket-spacing', rule, {
{
code: '
',
options: ['always'],
+ output: '
',
errors: ["A space is required before ']'."]
},
{
code: '
',
options: ['always'],
+ output: '
',
errors: ["A space is required after '['."]
},
{
code: '
',
options: ['always'],
+ output: '
',
+ errors: [
+ "A space is required after '['.",
+ "A space is required before ']'."
+ ]
+ },
+ {
+ code: '
',
+ options: ['always'],
+ output: '
',
errors: [
"A space is required after '['.",
"A space is required before ']'."
diff --git a/tests/lib/rules/attribute-hyphenation.js b/tests/lib/rules/attribute-hyphenation.js
index 433a33823..e5aad05e0 100644
--- a/tests/lib/rules/attribute-hyphenation.js
+++ b/tests/lib/rules/attribute-hyphenation.js
@@ -47,6 +47,16 @@ ruleTester.run('attribute-hyphenation', rule, {
filename: 'test.vue',
code: ' ',
options: ['never', { 'ignore': ['custom-hyphen', 'second-custom'] }]
+ },
+ {
+ filename: 'test.vue',
+ code: ' ',
+ options: ['always']
+ },
+ {
+ filename: 'test.vue',
+ code: ' ',
+ options: ['never']
}
],
diff --git a/tests/lib/rules/attributes-order.js b/tests/lib/rules/attributes-order.js
index d36294411..48e70e60e 100644
--- a/tests/lib/rules/attributes-order.js
+++ b/tests/lib/rules/attributes-order.js
@@ -276,6 +276,23 @@ tester.run('attributes-order', rule, {
'GLOBAL'
]
}]
+ },
+ {
+ filename: 'test.vue',
+ code:
+ `
+
+
+ `
}
],
@@ -584,6 +601,32 @@ tester.run('attributes-order', rule, {
nodeType: 'VIdentifier'
}
]
+ },
+ {
+ code:
+ `
+
+
+ `,
+ output:
+ `
+
+
+ `,
+ errors: [
+ {
+ message: 'Attribute "v-slot" should go before "v-model".',
+ nodeType: 'VIdentifier'
+ }
+ ]
}
]
})
diff --git a/tests/lib/rules/block-spacing.js b/tests/lib/rules/block-spacing.js
index 8ffc55d62..ff3b44002 100644
--- a/tests/lib/rules/block-spacing.js
+++ b/tests/lib/rules/block-spacing.js
@@ -17,7 +17,8 @@ tester.run('block-spacing', rule, {
{
code: '
',
options: ['never']
- }
+ },
+ '
'
],
invalid: [
{
@@ -110,6 +111,27 @@ tester.run('block-spacing', rule, {
line: 3
}
]
+ },
+ {
+ code: '
',
+ output: '
',
+ errors: [
+ {
+ messageId: 'missing',
+ data: {
+ location: 'after',
+ token: '{'
+ }
+ // message: 'Requires a space after \'{\'',
+ },
+ {
+ messageId: 'missing',
+ data: {
+ location: 'before',
+ token: '}'
+ }
+ // message: 'Requires a space before \'}\'',
+ }]
}
]
})
diff --git a/tests/lib/rules/brace-style.js b/tests/lib/rules/brace-style.js
index cd4f3d36d..d8278e774 100644
--- a/tests/lib/rules/brace-style.js
+++ b/tests/lib/rules/brace-style.js
@@ -19,7 +19,8 @@ tester.run('brace-style', rule, {
{
code: `
`,
options: ['1tbs', { 'allowSingleLine': true }]
- }
+ },
+ `
`
],
invalid: [
{
@@ -64,6 +65,19 @@ tester.run('brace-style', rule, {
line: 3
}
]
+ },
+ {
+ code: '
',
+ output: `
`,
+ errors: [
+ {
+ message: 'Statement inside of curly braces should be on next line.'
+ },
+ {
+ message: 'Closing curly brace should be on the same line as opening curly brace or on the line after the previous block.'
+ }]
}
]
})
diff --git a/tests/lib/rules/comma-dangle.js b/tests/lib/rules/comma-dangle.js
index aca710198..1d5c3e7b1 100644
--- a/tests/lib/rules/comma-dangle.js
+++ b/tests/lib/rules/comma-dangle.js
@@ -33,6 +33,19 @@ tester.run('comma-dangle', rule, {
options: [{
'arrays': 'ignore'
}]
+ },
+ {
+ code: `
+
+
+ `
+ },
+ {
+ code: `
+
+
+ `,
+ options: ['always']
}
],
invalid: [
@@ -103,6 +116,37 @@ tester.run('comma-dangle', rule, {
line: 7
}
]
+ },
+ {
+ code: `
+
+
+ `,
+ output: `
+
+
+ `,
+ errors: [
+ {
+ message: 'Unexpected trailing comma.'
+ }
+ ]
+ },
+ {
+ code: `
+
+
+ `,
+ output: `
+
+
+ `,
+ options: ['always'],
+ errors: [
+ {
+ message: 'Missing trailing comma.'
+ }
+ ]
}
]
})
diff --git a/tests/lib/rules/key-spacing.js b/tests/lib/rules/key-spacing.js
index 52adaaf9d..167e1f381 100644
--- a/tests/lib/rules/key-spacing.js
+++ b/tests/lib/rules/key-spacing.js
@@ -13,15 +13,30 @@ const tester = new RuleTester({
tester.run('key-spacing', rule, {
valid: [
- '
'
+ '
',
+ '
',
+ {
+ code: '
',
+ options: [{ 'beforeColon': true }]
+ }
],
invalid: [
{
code: '
',
+ output: '
',
errors: [
"Extra space after key 'a'.",
"Missing space before value for key 'a'."
]
+ },
+ {
+ code: '
',
+ options: [{ 'beforeColon': true }],
+ output: '
',
+ errors: [
+ "Missing space after key 'a'.",
+ "Missing space before value for key 'a'."
+ ]
}
]
})
diff --git a/tests/lib/rules/max-attributes-per-line.js b/tests/lib/rules/max-attributes-per-line.js
index ce4d45ffe..382492659 100644
--- a/tests/lib/rules/max-attributes-per-line.js
+++ b/tests/lib/rules/max-attributes-per-line.js
@@ -93,43 +93,43 @@ ruleTester.run('max-attributes-per-line', rule, {
code: ` `,
output: ` `,
- errors: ['Attribute "age" should be on a new line.']
+ errors: ['\'age\' should be on a new line.']
},
{
code: ` `,
output: ` `,
- errors: ['Binding "age" should be on a new line.']
+ errors: ['\':age\' should be on a new line.']
},
{
code: ` `,
output: ` `,
- errors: ['Directive "bind" should be on a new line.']
+ errors: ['\'v-bind\' should be on a new line.']
},
{
code: ` `,
output: ` `,
- errors: ['Event "buy" should be on a new line.']
+ errors: ['\'@buy\' should be on a new line.']
},
{
code: ` `,
output: ` `,
- errors: ['Event "click" should be on a new line.']
+ errors: ['\'@click.stop\' should be on a new line.']
},
{
code: ` `,
output: ` `,
- errors: ['Directive "if" should be on a new line.']
+ errors: ['\'v-if\' should be on a new line.']
},
{
code: ` `,
output: ` `,
- errors: ['Binding "age" should be on a new line.']
+ errors: ['\'v-bind:age\' should be on a new line.']
},
{
code: `
`,
errors: [{
- message: 'Attribute "job" should be on a new line.',
+ message: '\'job\' should be on a new line.',
type: 'VAttribute',
line: 1
}]
@@ -155,7 +155,7 @@ job="Vet"
output: ` `,
errors: [{
- message: 'Attribute "job" should be on a new line.',
+ message: '\'job\' should be on a new line.',
type: 'VAttribute',
line: 1
}]
@@ -166,11 +166,11 @@ job="Vet"> `,
output: ` `,
errors: [{
- message: 'Attribute "age" should be on a new line.',
+ message: '\'age\' should be on a new line.',
type: 'VAttribute',
line: 1
}, {
- message: 'Attribute "job" should be on a new line.',
+ message: '\'job\' should be on a new line.',
type: 'VAttribute',
line: 1
}]
@@ -187,7 +187,7 @@ name="John Doe"
`,
errors: [{
- message: 'Attribute "name" should be on a new line.',
+ message: '\'name\' should be on a new line.',
type: 'VAttribute',
line: 1
}]
@@ -206,7 +206,7 @@ age="30"
`,
errors: [{
- message: 'Attribute "age" should be on a new line.',
+ message: '\'age\' should be on a new line.',
type: 'VAttribute',
line: 2
}]
@@ -225,7 +225,7 @@ age="30"
`,
errors: [{
- message: 'Attribute "age" should be on a new line.',
+ message: '\'age\' should be on a new line.',
type: 'VAttribute',
line: 2
}]
@@ -244,7 +244,7 @@ petname="Snoopy">
`,
errors: [{
- message: 'Attribute "petname" should be on a new line.',
+ message: '\'petname\' should be on a new line.',
type: 'VAttribute',
line: 3
}]
@@ -263,11 +263,11 @@ petname="Snoopy" extra="foo">
`,
errors: [{
- message: 'Attribute "petname" should be on a new line.',
+ message: '\'petname\' should be on a new line.',
type: 'VAttribute',
line: 3
}, {
- message: 'Attribute "extra" should be on a new line.',
+ message: '\'extra\' should be on a new line.',
type: 'VAttribute',
line: 3
}]
diff --git a/tests/lib/rules/no-duplicate-attributes.js b/tests/lib/rules/no-duplicate-attributes.js
index 03cd71c74..aeef7fa8a 100644
--- a/tests/lib/rules/no-duplicate-attributes.js
+++ b/tests/lib/rules/no-duplicate-attributes.js
@@ -52,6 +52,14 @@ tester.run('no-duplicate-attributes', rule, {
filename: 'test.vue',
code: ' ',
options: [{ allowCoexistStyle: true }]
+ },
+ {
+ filename: 'test.vue',
+ code: ' '
+ },
+ {
+ filename: 'test.vue',
+ code: ' '
}
],
invalid: [
diff --git a/tests/lib/rules/no-multi-spaces.js b/tests/lib/rules/no-multi-spaces.js
index 68433af44..225f81c08 100644
--- a/tests/lib/rules/no-multi-spaces.js
+++ b/tests/lib/rules/no-multi-spaces.js
@@ -118,8 +118,8 @@ ruleTester.run('no-multi-spaces', rule, {
output: '
',
errors: [
{
- message: "Multiple spaces found before ':class'.",
- type: 'HTMLIdentifier'
+ message: "Multiple spaces found before ':'.",
+ type: 'Punctuator'
},
{
message: "Multiple spaces found before '/>'.",
diff --git a/tests/lib/rules/no-restricted-syntax.js b/tests/lib/rules/no-restricted-syntax.js
index 3fcdbc24a..36d7b9a02 100644
--- a/tests/lib/rules/no-restricted-syntax.js
+++ b/tests/lib/rules/no-restricted-syntax.js
@@ -24,6 +24,18 @@ tester.run('no-restricted-syntax', rule, {
'message': 'Call expressions are not allowed.'
}
]
+ },
+ {
+ code: `
+
+
+ `,
+ options: [
+ {
+ 'selector': 'CallExpression',
+ 'message': 'Call expressions are not allowed.'
+ }
+ ]
}
],
invalid: [
@@ -113,6 +125,20 @@ tester.run('no-restricted-syntax', rule, {
endColumn: 53
}
]
+ },
+
+ {
+ code: `
+
+
+ `,
+ options: [
+ {
+ 'selector': 'CallExpression',
+ 'message': 'Call expressions are not allowed.'
+ }
+ ],
+ errors: ['Call expressions are not allowed.', 'Call expressions are not allowed.']
}
]
})
diff --git a/tests/lib/rules/no-unused-vars.js b/tests/lib/rules/no-unused-vars.js
index f717e7af9..663740e92 100644
--- a/tests/lib/rules/no-unused-vars.js
+++ b/tests/lib/rules/no-unused-vars.js
@@ -49,6 +49,9 @@ tester.run('no-unused-vars', rule, {
},
{
code: '{{value | f(x)}}
'
+ },
+ {
+ code: '
'
}
],
invalid: [
diff --git a/tests/lib/rules/object-curly-spacing.js b/tests/lib/rules/object-curly-spacing.js
index bf6cbc8a8..6471f3afc 100644
--- a/tests/lib/rules/object-curly-spacing.js
+++ b/tests/lib/rules/object-curly-spacing.js
@@ -21,19 +21,27 @@ tester.run('object-curly-spacing', rule, {
{
code: '
',
options: ['always']
+ },
+ '
',
+ {
+ code: '
',
+ options: ['always']
}
],
invalid: [
{
code: '
',
+ output: '
',
errors: ["There should be no space after '{'."]
},
{
code: '
',
+ output: '
',
errors: ["There should be no space before '}'."]
},
{
code: '
',
+ output: '
',
errors: [
"There should be no space after '{'.",
"There should be no space before '}'."
@@ -42,16 +50,19 @@ tester.run('object-curly-spacing', rule, {
{
code: '
',
options: ['never'],
+ output: '
',
errors: ["There should be no space after '{'."]
},
{
code: '
',
options: ['never'],
+ output: '
',
errors: ["There should be no space before '}'."]
},
{
code: '
',
options: ['never'],
+ output: '
',
errors: [
"There should be no space after '{'.",
"There should be no space before '}'."
@@ -60,16 +71,28 @@ tester.run('object-curly-spacing', rule, {
{
code: '
',
options: ['always'],
+ output: '
',
errors: ["A space is required before '}'."]
},
{
code: '
',
options: ['always'],
+ output: '
',
errors: ["A space is required after '{'."]
},
{
code: '
',
options: ['always'],
+ output: '
',
+ errors: [
+ "A space is required after '{'.",
+ "A space is required before '}'."
+ ]
+ },
+ {
+ code: '
',
+ options: ['always'],
+ output: '
',
errors: [
"A space is required after '{'.",
"A space is required before '}'."
diff --git a/tests/lib/rules/space-infix-ops.js b/tests/lib/rules/space-infix-ops.js
index ba67575ff..2c3da144a 100644
--- a/tests/lib/rules/space-infix-ops.js
+++ b/tests/lib/rules/space-infix-ops.js
@@ -19,20 +19,29 @@ const message = semver.lt(CLIEngine.version, '5.10.0')
tester.run('space-infix-ops', rule, {
valid: [
'
',
- '
'
+ '
',
+ '
'
],
invalid: [
{
code: '
',
+ output: '
',
errors: [message('+')]
},
{
code: '
',
+ output: '
',
errors: [message('?')]
},
{
code: '
',
+ output: '
',
errors: [message(':')]
+ },
+ {
+ code: '
',
+ output: '
',
+ errors: [message('+')]
}
]
})
diff --git a/tests/lib/rules/space-unary-ops.js b/tests/lib/rules/space-unary-ops.js
index 2f36302bb..f6accb202 100644
--- a/tests/lib/rules/space-unary-ops.js
+++ b/tests/lib/rules/space-unary-ops.js
@@ -14,16 +14,38 @@ const tester = new RuleTester({
tester.run('space-unary-ops', rule, {
valid: [
'
',
- '
'
+ '
',
+ '
',
+ {
+ code: '
',
+ options: [{ nonwords: true }]
+ },
+ {
+ code: '
',
+ options: [{ nonwords: true }]
+ }
],
invalid: [
{
code: '
',
+ output: '
',
errors: ['Unexpected space after unary operator \'-\'.']
},
{
code: '
',
+ output: '
',
errors: ['Unary word operator \'typeof\' must be followed by whitespace.']
+ },
+ {
+ code: '
',
+ output: '
',
+ errors: ['Unary word operator \'typeof\' must be followed by whitespace.']
+ },
+ {
+ code: '
',
+ options: [{ nonwords: true }],
+ output: '
',
+ errors: ['Unary operator \'!\' must be followed by whitespace.']
}
]
})
diff --git a/tests/lib/rules/this-in-template.js b/tests/lib/rules/this-in-template.js
index 1f7c7c69b..294882941 100644
--- a/tests/lib/rules/this-in-template.js
+++ b/tests/lib/rules/this-in-template.js
@@ -106,6 +106,12 @@ function createValidTests (prefix, options) {
`,
options
+ },
+
+ // We cannot use `.` in dynamic arguments because the right of the `.` becomes a modifier.
+ {
+ code: `
`,
+ options
}
]
}
@@ -153,6 +159,13 @@ function createInvalidTests (prefix, options, message, type) {
errors: [{ message, type }],
options
}
+
+ // We cannot use `.` in dynamic arguments because the right of the `.` becomes a modifier.
+ // {
+ // code: `
`,
+ // errors: [{ message, type }],
+ // options
+ // }
].concat(options[0] === 'always'
? []
: [
diff --git a/tests/lib/rules/use-v-on-exact.js b/tests/lib/rules/use-v-on-exact.js
index be90196b1..2bb990403 100644
--- a/tests/lib/rules/use-v-on-exact.js
+++ b/tests/lib/rules/use-v-on-exact.js
@@ -152,6 +152,12 @@ ruleTester.run('use-v-on-exact', rule, {
},
{
code: ` `
+ },
+ {
+ code: ` `
+ },
+ {
+ code: ` `
}
],
@@ -272,6 +278,17 @@ ruleTester.run('use-v-on-exact', rule, {
{ message: "Consider to use '.exact' modifier.", line: 3 },
{ message: "Consider to use '.exact' modifier.", line: 4 }
]
+ },
+ {
+ code: `
+
+ `,
+ errors: [
+ { message: "Consider to use '.exact' modifier.", line: 3 }
+ ]
}
]
})
diff --git a/tests/lib/rules/v-bind-style.js b/tests/lib/rules/v-bind-style.js
index eeab4b9ab..bc9afb971 100644
--- a/tests/lib/rules/v-bind-style.js
+++ b/tests/lib/rules/v-bind-style.js
@@ -44,6 +44,26 @@ tester.run('v-bind-style', rule, {
filename: 'test.vue',
code: '
',
options: ['longform']
+ },
+
+ // Don't enforce `.prop` shorthand because of experimental.
+ {
+ filename: 'test.vue',
+ code: '
'
+ },
+ {
+ filename: 'test.vue',
+ code: '
'
+ },
+ {
+ filename: 'test.vue',
+ code: '
',
+ options: ['shorthand']
+ },
+ {
+ filename: 'test.vue',
+ code: '
',
+ options: ['shorthand']
}
],
invalid: [
@@ -66,6 +86,34 @@ tester.run('v-bind-style', rule, {
code: '
',
output: '
',
errors: ["Expected 'v-bind' before ':'."]
+ },
+ {
+ filename: 'test.vue',
+ options: ['longform'],
+ code: '
',
+ output: '
',
+ errors: ["Expected 'v-bind:' instead of '.'."]
+ },
+ {
+ filename: 'test.vue',
+ options: ['longform'],
+ code: '
',
+ output: '
',
+ errors: ["Expected 'v-bind:' instead of '.'."]
+ },
+ {
+ filename: 'test.vue',
+ options: ['longform'],
+ code: '
',
+ output: '
',
+ errors: ["Expected 'v-bind:' instead of '.'."]
+ },
+ {
+ filename: 'test.vue',
+ options: ['longform'],
+ code: '
',
+ output: '
',
+ errors: ["Expected 'v-bind:' instead of '.'."]
}
]
})