eslint-plugin-vue
Advanced tools
Comparing version 5.1.0 to 5.2.0
@@ -8,2 +8,7 @@ /* | ||
rules: { | ||
'vue/array-bracket-spacing': 'off', | ||
'vue/arrow-spacing': 'off', | ||
'vue/block-spacing': 'off', | ||
'vue/brace-style': 'off', | ||
'vue/comma-dangle': 'off', | ||
'vue/html-closing-bracket-newline': 'off', | ||
@@ -14,2 +19,3 @@ 'vue/html-closing-bracket-spacing': 'off', | ||
'vue/html-self-closing': 'off', | ||
'vue/key-spacing': 'off', | ||
'vue/max-attributes-per-line': 'off', | ||
@@ -20,5 +26,8 @@ 'vue/multiline-html-element-content-newline': 'off', | ||
'vue/no-spaces-around-equal-signs-in-attribute': 'off', | ||
'vue/object-curly-spacing': 'off', | ||
'vue/script-indent': 'off', | ||
'vue/singleline-html-element-content-newline': 'off' | ||
'vue/singleline-html-element-content-newline': 'off', | ||
'vue/space-infix-ops': 'off', | ||
'vue/space-unary-ops': 'off' | ||
} | ||
} |
@@ -10,6 +10,13 @@ /* | ||
rules: { | ||
'array-bracket-spacing': require('./rules/array-bracket-spacing'), | ||
'arrow-spacing': require('./rules/arrow-spacing'), | ||
'attribute-hyphenation': require('./rules/attribute-hyphenation'), | ||
'attributes-order': require('./rules/attributes-order'), | ||
'block-spacing': require('./rules/block-spacing'), | ||
'brace-style': require('./rules/brace-style'), | ||
'camelcase': require('./rules/camelcase'), | ||
'comma-dangle': require('./rules/comma-dangle'), | ||
'comment-directive': require('./rules/comment-directive'), | ||
'component-name-in-template-casing': require('./rules/component-name-in-template-casing'), | ||
'eqeqeq': require('./rules/eqeqeq'), | ||
'html-closing-bracket-newline': require('./rules/html-closing-bracket-newline'), | ||
@@ -22,2 +29,4 @@ 'html-closing-bracket-spacing': require('./rules/html-closing-bracket-spacing'), | ||
'jsx-uses-vars': require('./rules/jsx-uses-vars'), | ||
'key-spacing': require('./rules/key-spacing'), | ||
'match-component-file-name': require('./rules/match-component-file-name'), | ||
'max-attributes-per-line': require('./rules/max-attributes-per-line'), | ||
@@ -28,2 +37,3 @@ 'multiline-html-element-content-newline': require('./rules/multiline-html-element-content-newline'), | ||
'no-async-in-computed-properties': require('./rules/no-async-in-computed-properties'), | ||
'no-boolean-default': require('./rules/no-boolean-default'), | ||
'no-confusing-v-for-v-if': require('./rules/no-confusing-v-for-v-if'), | ||
@@ -35,2 +45,3 @@ 'no-dupe-keys': require('./rules/no-dupe-keys'), | ||
'no-reserved-keys': require('./rules/no-reserved-keys'), | ||
'no-restricted-syntax': require('./rules/no-restricted-syntax'), | ||
'no-shared-component-data': require('./rules/no-shared-component-data'), | ||
@@ -46,2 +57,3 @@ 'no-side-effects-in-computed-properties': require('./rules/no-side-effects-in-computed-properties'), | ||
'no-v-html': require('./rules/no-v-html'), | ||
'object-curly-spacing': require('./rules/object-curly-spacing'), | ||
'order-in-components': require('./rules/order-in-components'), | ||
@@ -51,2 +63,3 @@ 'prop-name-casing': require('./rules/prop-name-casing'), | ||
'require-default-prop': require('./rules/require-default-prop'), | ||
'require-direct-export': require('./rules/require-direct-export'), | ||
'require-prop-type-constructor': require('./rules/require-prop-type-constructor'), | ||
@@ -60,5 +73,8 @@ 'require-prop-types': require('./rules/require-prop-types'), | ||
'singleline-html-element-content-newline': require('./rules/singleline-html-element-content-newline'), | ||
'space-infix-ops': require('./rules/space-infix-ops'), | ||
'space-unary-ops': require('./rules/space-unary-ops'), | ||
'this-in-template': require('./rules/this-in-template'), | ||
'use-v-on-exact': require('./rules/use-v-on-exact'), | ||
'v-bind-style': require('./rules/v-bind-style'), | ||
'v-on-function-call': require('./rules/v-on-function-call'), | ||
'v-on-style': require('./rules/v-on-style'), | ||
@@ -65,0 +81,0 @@ 'valid-template-root': require('./rules/valid-template-root'), |
@@ -20,3 +20,3 @@ /** | ||
category: 'strongly-recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/attribute-hyphenation.html' | ||
url: 'https://eslint.vuejs.org/rules/attribute-hyphenation.html' | ||
}, | ||
@@ -23,0 +23,0 @@ fixable: 'code', |
@@ -110,3 +110,3 @@ /** | ||
category: 'recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/attributes-order.html' | ||
url: 'https://eslint.vuejs.org/rules/attributes-order.html' | ||
}, | ||
@@ -113,0 +113,0 @@ fixable: 'code', |
@@ -113,3 +113,3 @@ /** | ||
category: 'base', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/comment-directive.html' | ||
url: 'https://eslint.vuejs.org/rules/comment-directive.html' | ||
}, | ||
@@ -116,0 +116,0 @@ schema: [] |
@@ -13,3 +13,8 @@ /** | ||
const casing = require('../utils/casing') | ||
const { toRegExp } = require('../utils/regexp') | ||
// ----------------------------------------------------------------------------- | ||
// Helpers | ||
// ----------------------------------------------------------------------------- | ||
const allowedCaseOptions = ['PascalCase', 'kebab-case'] | ||
@@ -28,3 +33,3 @@ const defaultCase = 'PascalCase' | ||
category: undefined, | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/component-name-in-template-casing.html' | ||
url: 'https://eslint.vuejs.org/rules/component-name-in-template-casing.html' | ||
}, | ||
@@ -44,2 +49,5 @@ fixable: 'code', | ||
additionalItems: false | ||
}, | ||
registeredComponentsOnly: { | ||
type: 'boolean' | ||
} | ||
@@ -56,5 +64,39 @@ }, | ||
const caseType = allowedCaseOptions.indexOf(caseOption) !== -1 ? caseOption : defaultCase | ||
const ignores = options.ignores || [] | ||
const ignores = (options.ignores || []).map(toRegExp) | ||
const registeredComponentsOnly = options.registeredComponentsOnly !== false | ||
const tokens = context.parserServices.getTemplateBodyTokenStore && context.parserServices.getTemplateBodyTokenStore() | ||
const registeredComponents = [] | ||
/** | ||
* Checks whether the given node is the verification target node. | ||
* @param {VElement} node element node | ||
* @returns {boolean} `true` if the given node is the verification target node. | ||
*/ | ||
function isVerifyTarget (node) { | ||
if (ignores.some(re => re.test(node.rawName))) { | ||
// ignore | ||
return false | ||
} | ||
if (!registeredComponentsOnly) { | ||
// If the user specifies registeredComponentsOnly as false, it checks all component tags. | ||
if ((!utils.isHtmlElementNode(node) && !utils.isSvgElementNode(node)) || | ||
utils.isHtmlWellKnownElementName(node.rawName) || | ||
utils.isSvgWellKnownElementName(node.rawName) | ||
) { | ||
return false | ||
} | ||
return true | ||
} | ||
// We only verify the components registered in the component. | ||
if (registeredComponents | ||
.filter(name => casing.pascalCase(name) === name) // When defining a component with PascalCase, you can use either case | ||
.some(name => node.rawName === name || casing.pascalCase(node.rawName) === name)) { | ||
return true | ||
} | ||
return false | ||
} | ||
let hasInvalidEOF = false | ||
@@ -68,7 +110,3 @@ | ||
if ( | ||
(!utils.isHtmlElementNode(node) && !utils.isSvgElementNode(node)) || | ||
utils.isHtmlWellKnownElementName(node.rawName) || | ||
utils.isSvgWellKnownElementName(node.rawName) | ||
) { | ||
if (!isVerifyTarget(node)) { | ||
return | ||
@@ -78,5 +116,2 @@ } | ||
const name = node.rawName | ||
if (ignores.indexOf(name) >= 0) { | ||
return | ||
} | ||
const casingName = casing.getConverter(caseType)(name) | ||
@@ -109,8 +144,16 @@ if (casingName !== name) { | ||
} | ||
}, { | ||
Program (node) { | ||
hasInvalidEOF = utils.hasInvalidEOF(node) | ||
} | ||
}) | ||
}, | ||
Object.assign( | ||
{ | ||
Program (node) { | ||
hasInvalidEOF = utils.hasInvalidEOF(node) | ||
} | ||
}, | ||
registeredComponentsOnly | ||
? utils.executeOnVue(context, (obj) => { | ||
registeredComponents.push(...utils.getRegisteredComponents(obj).map(n => n.name)) | ||
}) | ||
: {} | ||
)) | ||
} | ||
} |
@@ -36,3 +36,3 @@ /** | ||
category: 'strongly-recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/html-closing-bracket-newline.html' | ||
url: 'https://eslint.vuejs.org/rules/html-closing-bracket-newline.html' | ||
}, | ||
@@ -39,0 +39,0 @@ fixable: 'whitespace', |
@@ -57,3 +57,3 @@ /** | ||
category: 'strongly-recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/html-closing-bracket-spacing.html' | ||
url: 'https://eslint.vuejs.org/rules/html-closing-bracket-spacing.html' | ||
}, | ||
@@ -60,0 +60,0 @@ schema: [{ |
@@ -24,3 +24,3 @@ /** | ||
category: 'strongly-recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/html-end-tags.html' | ||
url: 'https://eslint.vuejs.org/rules/html-end-tags.html' | ||
}, | ||
@@ -27,0 +27,0 @@ fixable: 'code', |
@@ -33,3 +33,3 @@ /** | ||
category: 'strongly-recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/html-indent.html' | ||
url: 'https://eslint.vuejs.org/rules/html-indent.html' | ||
}, | ||
@@ -36,0 +36,0 @@ fixable: 'whitespace', |
@@ -24,3 +24,3 @@ /** | ||
category: 'strongly-recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/html-quotes.html' | ||
url: 'https://eslint.vuejs.org/rules/html-quotes.html' | ||
}, | ||
@@ -27,0 +27,0 @@ fixable: 'code', |
@@ -92,3 +92,3 @@ /** | ||
category: 'strongly-recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/html-self-closing.html' | ||
url: 'https://eslint.vuejs.org/rules/html-self-closing.html' | ||
}, | ||
@@ -95,0 +95,0 @@ fixable: 'code', |
@@ -43,3 +43,3 @@ // the following rule is based on yannickcr/eslint-plugin-react | ||
category: 'base', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/jsx-uses-vars.html' | ||
url: 'https://eslint.vuejs.org/rules/jsx-uses-vars.html' | ||
}, | ||
@@ -46,0 +46,0 @@ schema: [] |
@@ -18,3 +18,3 @@ /** | ||
category: 'strongly-recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/max-attributes-per-line.html' | ||
url: 'https://eslint.vuejs.org/rules/max-attributes-per-line.html' | ||
}, | ||
@@ -21,0 +21,0 @@ fixable: 'whitespace', // or "code" or "whitespace" |
@@ -13,2 +13,3 @@ /** | ||
const casing = require('../utils/casing') | ||
const INLINE_ELEMENTS = require('../utils/inline-non-void-elements.json') | ||
@@ -25,4 +26,5 @@ // ------------------------------------------------------------------------------ | ||
return Object.assign({ | ||
ignores: ['pre', 'textarea'], | ||
ignoreWhenEmpty: true | ||
ignores: ['pre', 'textarea'].concat(INLINE_ELEMENTS), | ||
ignoreWhenEmpty: true, | ||
allowEmptyLines: false | ||
}, options) | ||
@@ -60,3 +62,3 @@ } | ||
category: 'strongly-recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/multiline-html-element-content-newline.html' | ||
url: 'https://eslint.vuejs.org/rules/multiline-html-element-content-newline.html' | ||
}, | ||
@@ -75,2 +77,5 @@ fixable: 'whitespace', | ||
additionalItems: false | ||
}, | ||
allowEmptyLines: { | ||
type: 'boolean' | ||
} | ||
@@ -90,2 +95,3 @@ }, | ||
const ignoreWhenEmpty = options.ignoreWhenEmpty | ||
const allowEmptyLines = options.allowEmptyLines | ||
const template = context.parserServices.getTemplateBodyTokenStore && context.parserServices.getTemplateBodyTokenStore() | ||
@@ -102,2 +108,10 @@ const sourceCode = context.getSourceCode() | ||
function isInvalidLineBreaks (lineBreaks) { | ||
if (allowEmptyLines) { | ||
return lineBreaks === 0 | ||
} else { | ||
return lineBreaks !== 1 | ||
} | ||
} | ||
return utils.defineTemplateBodyVisitor(context, { | ||
@@ -136,3 +150,3 @@ 'VElement' (node) { | ||
const afterLineBreaks = node.endTag.loc.start.line - contentLast.loc.end.line | ||
if (beforeLineBreaks !== 1) { | ||
if (isInvalidLineBreaks(beforeLineBreaks)) { | ||
context.report({ | ||
@@ -160,3 +174,3 @@ node: template.getLastToken(node.startTag), | ||
if (afterLineBreaks !== 1) { | ||
if (isInvalidLineBreaks(afterLineBreaks)) { | ||
context.report({ | ||
@@ -163,0 +177,0 @@ node: template.getFirstToken(node.endTag), |
@@ -23,3 +23,3 @@ /** | ||
category: 'strongly-recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/mustache-interpolation-spacing.html' | ||
url: 'https://eslint.vuejs.org/rules/mustache-interpolation-spacing.html' | ||
}, | ||
@@ -26,0 +26,0 @@ fixable: 'whitespace', |
@@ -21,3 +21,3 @@ /** | ||
category: 'strongly-recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/name-property-casing.html' | ||
url: 'https://eslint.vuejs.org/rules/name-property-casing.html' | ||
}, | ||
@@ -24,0 +24,0 @@ fixable: 'code', // or "code" or "whitespace" |
@@ -68,3 +68,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/no-async-in-computed-properties.html' | ||
url: 'https://eslint.vuejs.org/rules/no-async-in-computed-properties.html' | ||
}, | ||
@@ -77,2 +77,3 @@ fixable: null, | ||
const forbiddenNodes = [] | ||
const allowedScopes = [] | ||
@@ -93,2 +94,4 @@ const expressionTypes = { | ||
}) | ||
} else if (node.parent.type === 'ReturnStatement') { | ||
allowedScopes.push(node) | ||
} | ||
@@ -111,2 +114,4 @@ } | ||
}) | ||
} else if (node.parent.type === 'ReturnStatement') { | ||
allowedScopes.push(node) | ||
} | ||
@@ -121,4 +126,3 @@ }, | ||
}) | ||
} | ||
if (isTimedFunction(node)) { | ||
} else if (isTimedFunction(node)) { | ||
forbiddenNodes.push({ | ||
@@ -128,2 +132,4 @@ node: node, | ||
}) | ||
} else if (node.parent.type === 'ReturnStatement') { | ||
allowedScopes.push(node) | ||
} | ||
@@ -137,2 +143,11 @@ }, | ||
}) | ||
}, | ||
'ReturnStatement' (node) { | ||
if ( | ||
node.argument.type === 'ObjectExpression' || | ||
node.argument.type === 'ArrayExpression' | ||
) { | ||
allowedScopes.push(node.argument) | ||
} | ||
} | ||
@@ -148,3 +163,7 @@ }, | ||
el.node.loc.start.line >= cp.value.loc.start.line && | ||
el.node.loc.end.line <= cp.value.loc.end.line | ||
el.node.loc.end.line <= cp.value.loc.end.line && | ||
!allowedScopes.some(scope => | ||
scope.range[0] < el.node.range[0] && | ||
scope.range[1] > el.node.range[1] | ||
) | ||
) { | ||
@@ -151,0 +170,0 @@ context.report({ |
@@ -43,3 +43,3 @@ /** | ||
category: 'recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/no-confusing-v-for-v-if.html', | ||
url: 'https://eslint.vuejs.org/rules/no-confusing-v-for-v-if.html', | ||
replacedBy: ['no-use-v-if-with-v-for'] | ||
@@ -46,0 +46,0 @@ }, |
@@ -21,3 +21,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/no-dupe-keys.html' | ||
url: 'https://eslint.vuejs.org/rules/no-dupe-keys.html' | ||
}, | ||
@@ -24,0 +24,0 @@ fixable: null, // or "code" or "whitespace" |
@@ -43,3 +43,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/no-duplicate-attributes.html' | ||
url: 'https://eslint.vuejs.org/rules/no-duplicate-attributes.html' | ||
}, | ||
@@ -46,0 +46,0 @@ fixable: null, |
@@ -22,3 +22,3 @@ /** | ||
category: 'strongly-recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/no-multi-spaces.html' | ||
url: 'https://eslint.vuejs.org/rules/no-multi-spaces.html' | ||
}, | ||
@@ -25,0 +25,0 @@ fixable: 'whitespace', // or "code" or "whitespace" |
@@ -62,3 +62,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/no-parsing-error.html' | ||
url: 'https://eslint.vuejs.org/rules/no-parsing-error.html' | ||
}, | ||
@@ -65,0 +65,0 @@ fixable: null, |
@@ -22,3 +22,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/no-reserved-keys.html' | ||
url: 'https://eslint.vuejs.org/rules/no-reserved-keys.html' | ||
}, | ||
@@ -25,0 +25,0 @@ fixable: null, |
@@ -44,3 +44,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/no-shared-component-data.html' | ||
url: 'https://eslint.vuejs.org/rules/no-shared-component-data.html' | ||
}, | ||
@@ -47,0 +47,0 @@ fixable: 'code', |
@@ -19,3 +19,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/no-side-effects-in-computed-properties.html' | ||
url: 'https://eslint.vuejs.org/rules/no-side-effects-in-computed-properties.html' | ||
}, | ||
@@ -22,0 +22,0 @@ fixable: null, |
@@ -23,3 +23,3 @@ /** | ||
category: 'strongly-recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/no-spaces-around-equal-signs-in-attribute.html' | ||
url: 'https://eslint.vuejs.org/rules/no-spaces-around-equal-signs-in-attribute.html' | ||
}, | ||
@@ -26,0 +26,0 @@ fixable: 'whitespace', |
@@ -24,3 +24,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/no-template-key.html' | ||
url: 'https://eslint.vuejs.org/rules/no-template-key.html' | ||
}, | ||
@@ -27,0 +27,0 @@ fixable: null, |
@@ -25,3 +25,3 @@ /** | ||
category: 'strongly-recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/no-template-shadow.html' | ||
url: 'https://eslint.vuejs.org/rules/no-template-shadow.html' | ||
}, | ||
@@ -28,0 +28,0 @@ fixable: null, |
@@ -24,3 +24,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/no-textarea-mustache.html' | ||
url: 'https://eslint.vuejs.org/rules/no-textarea-mustache.html' | ||
}, | ||
@@ -27,0 +27,0 @@ fixable: null, |
@@ -24,3 +24,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/no-unused-components.html' | ||
url: 'https://eslint.vuejs.org/rules/no-unused-components.html' | ||
}, | ||
@@ -60,3 +60,7 @@ fixable: null, | ||
"VAttribute[directive=true][key.name='bind'][key.argument='is']" (node) { | ||
if (node.value.type !== 'VExpressionContainer') return | ||
if ( | ||
!node.value || // `<component :is>` | ||
node.value.type !== 'VExpressionContainer' || | ||
!node.value.expression // `<component :is="">` | ||
) return | ||
@@ -63,0 +67,0 @@ if (node.value.expression.type === 'Literal') { |
@@ -19,3 +19,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/no-unused-vars.html' | ||
url: 'https://eslint.vuejs.org/rules/no-unused-vars.html' | ||
}, | ||
@@ -22,0 +22,0 @@ fixable: null, |
@@ -56,3 +56,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/no-use-v-if-with-v-for.html' | ||
url: 'https://eslint.vuejs.org/rules/no-use-v-if-with-v-for.html' | ||
}, | ||
@@ -59,0 +59,0 @@ fixable: null, |
@@ -18,3 +18,3 @@ /** | ||
category: 'recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/no-v-html.html' | ||
url: 'https://eslint.vuejs.org/rules/no-v-html.html' | ||
}, | ||
@@ -21,0 +21,0 @@ fixable: null, |
@@ -25,2 +25,4 @@ /** | ||
'watch', | ||
'asyncData', | ||
'fetch', | ||
'LIFECYCLE_HOOKS', | ||
@@ -140,3 +142,3 @@ 'methods', | ||
category: 'recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/order-in-components.html' | ||
url: 'https://eslint.vuejs.org/rules/order-in-components.html' | ||
}, | ||
@@ -143,0 +145,0 @@ fixable: 'code', // null or "code" or "whitespace" |
@@ -78,3 +78,3 @@ /** | ||
category: 'strongly-recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/prop-name-casing.html' | ||
url: 'https://eslint.vuejs.org/rules/prop-name-casing.html' | ||
}, | ||
@@ -81,0 +81,0 @@ fixable: 'code', // null or "code" or "whitespace" |
@@ -24,3 +24,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/require-component-is.html' | ||
url: 'https://eslint.vuejs.org/rules/require-component-is.html' | ||
}, | ||
@@ -27,0 +27,0 @@ fixable: null, |
/** | ||
* @fileoverview Require default value for props | ||
* @author Michał Sajnóg <msajnog93@gmail.com> (http://github.com/michalsnik) | ||
* @author Michał Sajnóg <msajnog93@gmail.com> (https://github.com/michalsnik) | ||
*/ | ||
@@ -29,3 +29,3 @@ 'use strict' | ||
category: 'strongly-recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/require-default-prop.html' | ||
url: 'https://eslint.vuejs.org/rules/require-default-prop.html' | ||
}, | ||
@@ -145,2 +145,4 @@ fixable: null, // or "code" or "whitespace" | ||
for (const prop of propsToReport) { | ||
const propName = prop.propName != null ? prop.propName : `[${context.getSourceCode().getText(prop.key)}]` | ||
context.report({ | ||
@@ -150,3 +152,3 @@ node: prop.node, | ||
data: { | ||
propName: prop.key.name | ||
propName | ||
} | ||
@@ -153,0 +155,0 @@ }) |
@@ -30,3 +30,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/require-prop-type-constructor.html' | ||
url: 'https://eslint.vuejs.org/rules/require-prop-type-constructor.html' | ||
}, | ||
@@ -33,0 +33,0 @@ fixable: 'code', // or "code" or "whitespace" |
@@ -19,3 +19,3 @@ /** | ||
category: 'strongly-recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/require-prop-types.html' | ||
url: 'https://eslint.vuejs.org/rules/require-prop-types.html' | ||
}, | ||
@@ -22,0 +22,0 @@ fixable: null, // or "code" or "whitespace" |
@@ -19,3 +19,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/require-render-return.html' | ||
url: 'https://eslint.vuejs.org/rules/require-render-return.html' | ||
}, | ||
@@ -22,0 +22,0 @@ fixable: null, // or "code" or "whitespace" |
@@ -24,3 +24,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/require-v-for-key.html' | ||
url: 'https://eslint.vuejs.org/rules/require-v-for-key.html' | ||
}, | ||
@@ -27,0 +27,0 @@ fixable: null, |
@@ -28,3 +28,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/require-valid-default-prop.html' | ||
url: 'https://eslint.vuejs.org/rules/require-valid-default-prop.html' | ||
}, | ||
@@ -113,2 +113,3 @@ fixable: null, | ||
const propName = prop.propName != null ? prop.propName : `[${context.getSourceCode().getText(prop.key)}]` | ||
context.report({ | ||
@@ -118,3 +119,3 @@ node: def, | ||
data: { | ||
name: prop.key.name, | ||
name: propName, | ||
types: Array.from(typeNames).join(' or ').toLowerCase() | ||
@@ -121,0 +122,0 @@ } |
@@ -19,3 +19,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/return-in-computed-property.html' | ||
url: 'https://eslint.vuejs.org/rules/return-in-computed-property.html' | ||
}, | ||
@@ -22,0 +22,0 @@ fixable: null, // or "code" or "whitespace" |
@@ -23,3 +23,3 @@ /** | ||
category: undefined, | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/script-indent.html' | ||
url: 'https://eslint.vuejs.org/rules/script-indent.html' | ||
}, | ||
@@ -26,0 +26,0 @@ fixable: 'whitespace', |
@@ -13,2 +13,3 @@ /** | ||
const casing = require('../utils/casing') | ||
const INLINE_ELEMENTS = require('../utils/inline-non-void-elements.json') | ||
@@ -25,3 +26,3 @@ // ------------------------------------------------------------------------------ | ||
return Object.assign({ | ||
ignores: ['pre', 'textarea'], | ||
ignores: ['pre', 'textarea'].concat(INLINE_ELEMENTS), | ||
ignoreWhenNoAttributes: true, | ||
@@ -55,3 +56,3 @@ ignoreWhenEmpty: true | ||
category: 'strongly-recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/singleline-html-element-content-newline.html' | ||
url: 'https://eslint.vuejs.org/rules/singleline-html-element-content-newline.html' | ||
}, | ||
@@ -58,0 +59,0 @@ fixable: 'whitespace', |
@@ -24,3 +24,3 @@ /** | ||
category: 'recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/this-in-template.html' | ||
url: 'https://eslint.vuejs.org/rules/this-in-template.html' | ||
}, | ||
@@ -27,0 +27,0 @@ fixable: null, |
@@ -13,6 +13,122 @@ /** | ||
const SYSTEM_MODIFIERS = new Set(['ctrl', 'shift', 'alt', 'meta']) | ||
// ------------------------------------------------------------------------------ | ||
// Rule Definition | ||
// Helpers | ||
// ------------------------------------------------------------------------------ | ||
/** | ||
* Finds and returns all keys for event directives | ||
* | ||
* @param {array} attributes Element attributes | ||
* @returns {array[object]} [{ name, node, modifiers }] | ||
*/ | ||
function getEventDirectives (attributes) { | ||
return attributes | ||
.filter(attribute => | ||
attribute.directive && | ||
attribute.key.name === 'on' | ||
) | ||
.map(attribute => ({ | ||
name: attribute.key.argument, | ||
node: attribute.key, | ||
modifiers: attribute.key.modifiers | ||
})) | ||
} | ||
/** | ||
* Checks whether given modifier is system one | ||
* | ||
* @param {string} modifier | ||
* @returns {boolean} | ||
*/ | ||
function isSystemModifier (modifier) { | ||
return SYSTEM_MODIFIERS.has(modifier) | ||
} | ||
/** | ||
* Checks whether given any of provided modifiers | ||
* has system modifier | ||
* | ||
* @param {array} modifiers | ||
* @returns {boolean} | ||
*/ | ||
function hasSystemModifier (modifiers) { | ||
return modifiers.some(isSystemModifier) | ||
} | ||
/** | ||
* Groups all events in object, | ||
* with keys represinting each event name | ||
* | ||
* @param {array} events | ||
* @returns {object} { click: [], keypress: [] } | ||
*/ | ||
function groupEvents (events) { | ||
return events.reduce((acc, event) => { | ||
if (acc[event.name]) { | ||
acc[event.name].push(event) | ||
} else { | ||
acc[event.name] = [event] | ||
} | ||
return acc | ||
}, {}) | ||
} | ||
/** | ||
* Creates alphabetically sorted string with system modifiers | ||
* | ||
* @param {array[string]} modifiers | ||
* @returns {string} e.g. "alt,ctrl,del,shift" | ||
*/ | ||
function getSystemModifiersString (modifiers) { | ||
return modifiers.filter(isSystemModifier).sort().join(',') | ||
} | ||
/** | ||
* Compares two events based on their modifiers | ||
* to detect possible event leakeage | ||
* | ||
* @param {object} baseEvent | ||
* @param {object} event | ||
* @returns {boolean} | ||
*/ | ||
function hasConflictedModifiers (baseEvent, event) { | ||
if ( | ||
event.node === baseEvent.node || | ||
event.modifiers.includes('exact') | ||
) return false | ||
const eventModifiers = getSystemModifiersString(event.modifiers) | ||
const baseEventModifiers = getSystemModifiersString(baseEvent.modifiers) | ||
return ( | ||
baseEvent.modifiers.length >= 1 && | ||
baseEventModifiers !== eventModifiers && | ||
baseEventModifiers.indexOf(eventModifiers) > -1 | ||
) | ||
} | ||
/** | ||
* Searches for events that might conflict with each other | ||
* | ||
* @param {array} events | ||
* @returns {array} conflicted events, without duplicates | ||
*/ | ||
function findConflictedEvents (events) { | ||
return events.reduce((acc, event) => { | ||
return [ | ||
...acc, | ||
...events | ||
.filter(evt => !acc.find(e => evt === e)) // No duplicates | ||
.filter(hasConflictedModifiers.bind(null, event)) | ||
] | ||
}, []) | ||
} | ||
// ------------------------------------------------------------------------------ | ||
// Rule details | ||
// ------------------------------------------------------------------------------ | ||
module.exports = { | ||
@@ -24,3 +140,3 @@ meta: { | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/use-v-on-exact.html' | ||
url: 'https://eslint.vuejs.org/rules/use-v-on-exact.html' | ||
}, | ||
@@ -40,27 +156,32 @@ fixable: null, | ||
VStartTag (node) { | ||
if (node.attributes.length > 1) { | ||
const groups = node.attributes | ||
.map(item => item.key) | ||
.filter(item => item && item.type === 'VDirectiveKey' && item.name === 'on') | ||
.reduce((rv, item) => { | ||
(rv[item.argument] = rv[item.argument] || []).push(item) | ||
return rv | ||
}, {}) | ||
if (node.attributes.length === 0) return | ||
const directives = Object.keys(groups).map(key => groups[key]) | ||
// const directives = Object.values(groups) // Uncomment after node 6 is dropped | ||
.filter(item => item.length > 1) | ||
for (const group of directives) { | ||
if (group.some(item => item.modifiers.length > 0)) { // check if there are directives with modifiers | ||
const invalid = group.filter(item => item.modifiers.length === 0) | ||
for (const node of invalid) { | ||
context.report({ | ||
node, | ||
loc: node.loc, | ||
message: "Consider to use '.exact' modifier." | ||
}) | ||
} | ||
} | ||
} | ||
const isCustomComponent = utils.isCustomComponent(node.parent) | ||
let events = getEventDirectives(node.attributes) | ||
if (isCustomComponent) { | ||
// For components consider only events with `native` modifier | ||
events = events.filter(event => event.modifiers.includes('native')) | ||
} | ||
const grouppedEvents = groupEvents(events) | ||
Object.keys(grouppedEvents).forEach(eventName => { | ||
const eventsInGroup = grouppedEvents[eventName] | ||
const hasEventWithKeyModifier = eventsInGroup.some(event => | ||
hasSystemModifier(event.modifiers) | ||
) | ||
if (!hasEventWithKeyModifier) return | ||
const conflictedEvents = findConflictedEvents(eventsInGroup) | ||
conflictedEvents.forEach(e => { | ||
context.report({ | ||
node: e.node, | ||
loc: e.node.loc, | ||
message: "Consider to use '.exact' modifier." | ||
}) | ||
}) | ||
}) | ||
} | ||
@@ -67,0 +188,0 @@ }) |
@@ -24,3 +24,3 @@ /** | ||
category: 'strongly-recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/v-bind-style.html' | ||
url: 'https://eslint.vuejs.org/rules/v-bind-style.html' | ||
}, | ||
@@ -27,0 +27,0 @@ fixable: 'code', |
@@ -24,3 +24,3 @@ /** | ||
category: 'strongly-recommended', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/v-on-style.html' | ||
url: 'https://eslint.vuejs.org/rules/v-on-style.html' | ||
}, | ||
@@ -27,0 +27,0 @@ fixable: 'code', |
@@ -24,3 +24,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/valid-template-root.html' | ||
url: 'https://eslint.vuejs.org/rules/valid-template-root.html' | ||
}, | ||
@@ -27,0 +27,0 @@ fixable: null, |
@@ -30,3 +30,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/valid-v-bind.html' | ||
url: 'https://eslint.vuejs.org/rules/valid-v-bind.html' | ||
}, | ||
@@ -33,0 +33,0 @@ fixable: null, |
@@ -24,3 +24,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/valid-v-cloak.html' | ||
url: 'https://eslint.vuejs.org/rules/valid-v-cloak.html' | ||
}, | ||
@@ -27,0 +27,0 @@ fixable: null, |
@@ -24,3 +24,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/valid-v-else-if.html' | ||
url: 'https://eslint.vuejs.org/rules/valid-v-else-if.html' | ||
}, | ||
@@ -27,0 +27,0 @@ fixable: null, |
@@ -24,3 +24,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/valid-v-else.html' | ||
url: 'https://eslint.vuejs.org/rules/valid-v-else.html' | ||
}, | ||
@@ -27,0 +27,0 @@ fixable: null, |
@@ -110,3 +110,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/valid-v-for.html' | ||
url: 'https://eslint.vuejs.org/rules/valid-v-for.html' | ||
}, | ||
@@ -113,0 +113,0 @@ fixable: null, |
@@ -24,3 +24,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/valid-v-html.html' | ||
url: 'https://eslint.vuejs.org/rules/valid-v-html.html' | ||
}, | ||
@@ -27,0 +27,0 @@ fixable: null, |
@@ -24,3 +24,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/valid-v-if.html' | ||
url: 'https://eslint.vuejs.org/rules/valid-v-if.html' | ||
}, | ||
@@ -27,0 +27,0 @@ fixable: null, |
@@ -86,3 +86,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/valid-v-model.html' | ||
url: 'https://eslint.vuejs.org/rules/valid-v-model.html' | ||
}, | ||
@@ -89,0 +89,0 @@ fixable: null, |
@@ -13,2 +13,3 @@ /** | ||
const utils = require('../utils') | ||
const keyAliases = require('../utils/key-aliases.json') | ||
@@ -28,70 +29,3 @@ // ------------------------------------------------------------------------------ | ||
// https://www.w3.org/TR/uievents-key/ | ||
const KEY_ALIASES = new Set([ | ||
'unidentified', 'alt', 'alt-graph', 'caps-lock', 'control', 'fn', 'fn-lock', | ||
'meta', 'num-lock', 'scroll-lock', 'shift', 'symbol', 'symbol-lock', 'hyper', | ||
'super', 'enter', 'tab', 'arrow-down', 'arrow-left', 'arrow-right', | ||
'arrow-up', 'end', 'home', 'page-down', 'page-up', 'backspace', 'clear', | ||
'copy', 'cr-sel', 'cut', 'delete', 'erase-eof', 'ex-sel', 'insert', 'paste', | ||
'redo', 'undo', 'accept', 'again', 'attn', 'cancel', 'context-menu', 'escape', | ||
'execute', 'find', 'help', 'pause', 'select', 'zoom-in', 'zoom-out', | ||
'brightness-down', 'brightness-up', 'eject', 'log-off', 'power', | ||
'print-screen', 'hibernate', 'standby', 'wake-up', 'all-candidates', | ||
'alphanumeric', 'code-input', 'compose', 'convert', 'dead', 'final-mode', | ||
'group-first', 'group-last', 'group-next', 'group-previous', 'mode-change', | ||
'next-candidate', 'non-convert', 'previous-candidate', 'process', | ||
'single-candidate', 'hangul-mode', 'hanja-mode', 'junja-mode', 'eisu', | ||
'hankaku', 'hiragana', 'hiragana-katakana', 'kana-mode', 'kanji-mode', | ||
'katakana', 'romaji', 'zenkaku', 'zenkaku-hankaku', 'f1', 'f2', 'f3', 'f4', | ||
'f5', 'f6', 'f7', 'f8', 'f9', 'f10', 'f11', 'f12', 'soft1', 'soft2', 'soft3', | ||
'soft4', 'channel-down', 'channel-up', 'close', 'mail-forward', 'mail-reply', | ||
'mail-send', 'media-close', 'media-fast-forward', 'media-pause', | ||
'media-play-pause', 'media-record', 'media-rewind', 'media-stop', | ||
'media-track-next', 'media-track-previous', 'new', 'open', 'print', 'save', | ||
'spell-check', 'key11', 'key12', 'audio-balance-left', 'audio-balance-right', | ||
'audio-bass-boost-down', 'audio-bass-boost-toggle', 'audio-bass-boost-up', | ||
'audio-fader-front', 'audio-fader-rear', 'audio-surround-mode-next', | ||
'audio-treble-down', 'audio-treble-up', 'audio-volume-down', | ||
'audio-volume-up', 'audio-volume-mute', 'microphone-toggle', | ||
'microphone-volume-down', 'microphone-volume-up', 'microphone-volume-mute', | ||
'speech-correction-list', 'speech-input-toggle', 'launch-application1', | ||
'launch-application2', 'launch-calendar', 'launch-contacts', 'launch-mail', | ||
'launch-media-player', 'launch-music-player', 'launch-phone', | ||
'launch-screen-saver', 'launch-spreadsheet', 'launch-web-browser', | ||
'launch-web-cam', 'launch-word-processor', 'browser-back', | ||
'browser-favorites', 'browser-forward', 'browser-home', 'browser-refresh', | ||
'browser-search', 'browser-stop', 'app-switch', 'call', 'camera', | ||
'camera-focus', 'end-call', 'go-back', 'go-home', 'headset-hook', | ||
'last-number-redial', 'notification', 'manner-mode', 'voice-dial', 't-v', | ||
't-v3-d-mode', 't-v-antenna-cable', 't-v-audio-description', | ||
't-v-audio-description-mix-down', 't-v-audio-description-mix-up', | ||
't-v-contents-menu', 't-v-data-service', 't-v-input', 't-v-input-component1', | ||
't-v-input-component2', 't-v-input-composite1', 't-v-input-composite2', | ||
't-v-input-h-d-m-i1', 't-v-input-h-d-m-i2', 't-v-input-h-d-m-i3', | ||
't-v-input-h-d-m-i4', 't-v-input-v-g-a1', 't-v-media-context', 't-v-network', | ||
't-v-number-entry', 't-v-power', 't-v-radio-service', 't-v-satellite', | ||
't-v-satellite-b-s', 't-v-satellite-c-s', 't-v-satellite-toggle', | ||
't-v-terrestrial-analog', 't-v-terrestrial-digital', 't-v-timer', | ||
'a-v-r-input', 'a-v-r-power', 'color-f0-red', 'color-f1-green', | ||
'color-f2-yellow', 'color-f3-blue', 'color-f4-grey', 'color-f5-brown', | ||
'closed-caption-toggle', 'dimmer', 'display-swap', 'd-v-r', 'exit', | ||
'favorite-clear0', 'favorite-clear1', 'favorite-clear2', 'favorite-clear3', | ||
'favorite-recall0', 'favorite-recall1', 'favorite-recall2', | ||
'favorite-recall3', 'favorite-store0', 'favorite-store1', 'favorite-store2', | ||
'favorite-store3', 'guide', 'guide-next-day', 'guide-previous-day', 'info', | ||
'instant-replay', 'link', 'list-program', 'live-content', 'lock', | ||
'media-apps', 'media-last', 'media-skip-backward', 'media-skip-forward', | ||
'media-step-backward', 'media-step-forward', 'media-top-menu', 'navigate-in', | ||
'navigate-next', 'navigate-out', 'navigate-previous', 'next-favorite-channel', | ||
'next-user-profile', 'on-demand', 'pairing', 'pin-p-down', 'pin-p-move', | ||
'pin-p-toggle', 'pin-p-up', 'play-speed-down', 'play-speed-reset', | ||
'play-speed-up', 'random-toggle', 'rc-low-battery', 'record-speed-next', | ||
'rf-bypass', 'scan-channels-toggle', 'screen-mode-next', 'settings', | ||
'split-screen-toggle', 's-t-b-input', 's-t-b-power', 'subtitle', 'teletext', | ||
'video-mode-next', 'wink', 'zoom-toggle', 'audio-volume-down', | ||
'audio-volume-up', 'audio-volume-mute', 'browser-back', 'browser-forward', | ||
'channel-down', 'channel-up', 'context-menu', 'eject', 'end', 'enter', 'home', | ||
'media-fast-forward', 'media-play', 'media-play-pause', 'media-record', | ||
'media-rewind', 'media-stop', 'media-next-track', 'media-pause', | ||
'media-previous-track', 'power', 'unidentified' | ||
]) | ||
const KEY_ALIASES = new Set(keyAliases) | ||
@@ -123,3 +57,3 @@ function isValidModifier (modifier, customModifiers) { | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/valid-v-on.html' | ||
url: 'https://eslint.vuejs.org/rules/valid-v-on.html' | ||
}, | ||
@@ -126,0 +60,0 @@ fixable: null, |
@@ -24,3 +24,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/valid-v-once.html' | ||
url: 'https://eslint.vuejs.org/rules/valid-v-once.html' | ||
}, | ||
@@ -27,0 +27,0 @@ fixable: null, |
@@ -24,3 +24,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/valid-v-pre.html' | ||
url: 'https://eslint.vuejs.org/rules/valid-v-pre.html' | ||
}, | ||
@@ -27,0 +27,0 @@ fixable: null, |
@@ -24,3 +24,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/valid-v-show.html' | ||
url: 'https://eslint.vuejs.org/rules/valid-v-show.html' | ||
}, | ||
@@ -27,0 +27,0 @@ fixable: null, |
@@ -24,3 +24,3 @@ /** | ||
category: 'essential', | ||
url: 'https://vuejs.github.io/eslint-plugin-vue/rules/valid-v-text.html' | ||
url: 'https://eslint.vuejs.org/rules/valid-v-text.html' | ||
}, | ||
@@ -27,0 +27,0 @@ fixable: null, |
@@ -16,4 +16,25 @@ /** | ||
const assert = require('assert') | ||
const path = require('path') | ||
const vueEslintParser = require('vue-eslint-parser') | ||
/** | ||
* Wrap the rule context object to override methods which access to tokens (such as getTokenAfter). | ||
* @param {RuleContext} context The rule context object. | ||
* @param {TokenStore} tokenStore The token store object for template. | ||
*/ | ||
function wrapContextToOverrideTokenMethods (context, tokenStore) { | ||
const sourceCode = new Proxy(context.getSourceCode(), { | ||
get (object, key) { | ||
return key in tokenStore ? tokenStore[key] : object[key] | ||
} | ||
}) | ||
return { | ||
__proto__: context, | ||
getSourceCode () { | ||
return sourceCode | ||
} | ||
} | ||
} | ||
// ------------------------------------------------------------------------------ | ||
@@ -46,2 +67,45 @@ // 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. | ||
* @returns {Rule} The wrapped rule implementation. | ||
*/ | ||
wrapCoreRule (coreRule, category) { | ||
return { | ||
create (context) { | ||
const tokenStore = | ||
context.parserServices.getTemplateBodyTokenStore && | ||
context.parserServices.getTemplateBodyTokenStore() | ||
// The `context.getSourceCode()` cannot access the tokens of templates. | ||
// So override the methods which access to tokens by the `tokenStore`. | ||
if (tokenStore) { | ||
context = wrapContextToOverrideTokenMethods(context, tokenStore) | ||
} | ||
// Move `Program` handlers to `VElement[parent.type!='VElement']` | ||
const handlers = coreRule.create(context) | ||
if (handlers.Program) { | ||
handlers["VElement[parent.type!='VElement']"] = handlers.Program | ||
delete handlers.Program | ||
} | ||
if (handlers['Program:exit']) { | ||
handlers["VElement[parent.type!='VElement']:exit"] = handlers['Program:exit'] | ||
delete handlers['Program:exit'] | ||
} | ||
// Apply the handlers to templates. | ||
return module.exports.defineTemplateBodyVisitor(context, handlers) | ||
}, | ||
meta: Object.assign({}, coreRule.meta, { | ||
docs: Object.assign({}, coreRule.meta.docs, { | ||
category, | ||
url: `https://vuejs.github.io/eslint-plugin-vue/rules/${path.basename(coreRule.meta.docs.url || '')}.html` | ||
}) | ||
}) | ||
} | ||
}, | ||
/** | ||
* Check whether the given node is the root element or not. | ||
@@ -206,6 +270,7 @@ * @param {ASTNode} node The element node to check. | ||
.filter(p => p.type === 'Property') | ||
.map(node => ({ | ||
node, | ||
name: this.getStaticPropertyName(node.key) | ||
})) | ||
.map(node => { | ||
const name = this.getStaticPropertyName(node) | ||
return name ? { node, name } : null | ||
}) | ||
.filter(comp => comp != null) | ||
}, | ||
@@ -426,3 +491,6 @@ | ||
.map(prop => { | ||
return { key: prop.key, value: this.unwrapTypes(prop.value), node: prop } | ||
return { | ||
key: prop.key, value: this.unwrapTypes(prop.value), node: prop, | ||
propName: this.getStaticPropertyName(prop) | ||
} | ||
}) | ||
@@ -433,3 +501,3 @@ } else { | ||
const key = prop.type === 'Literal' && typeof prop.value === 'string' ? prop : null | ||
return { key, value: null, node: prop } | ||
return { key, value: null, node: prop, propName: key != null ? prop.value : null } | ||
}) | ||
@@ -480,2 +548,6 @@ } | ||
isVueFile (path) { | ||
return path.endsWith('.vue') || path.endsWith('.jsx') | ||
}, | ||
/** | ||
@@ -490,4 +562,3 @@ * Check whether the given node is a Vue component based | ||
isVueComponentFile (node, path) { | ||
const isVueFile = path.endsWith('.vue') || path.endsWith('.jsx') | ||
return isVueFile && | ||
return this.isVueFile(path) && | ||
node.type === 'ExportDefaultDeclaration' && | ||
@@ -494,0 +565,0 @@ node.declaration.type === 'ObjectExpression' |
{ | ||
"name": "eslint-plugin-vue", | ||
"version": "5.1.0", | ||
"version": "5.2.0", | ||
"description": "Official ESLint plugin for Vue.js", | ||
@@ -16,4 +16,3 @@ "main": "lib/index.js", | ||
"docs:watch": "vuepress dev docs", | ||
"docs:build": "vuepress build docs", | ||
"docs:deploy": "./tools/deploy.sh" | ||
"docs:build": "vuepress build docs" | ||
}, | ||
@@ -23,3 +22,3 @@ "files": [ | ||
], | ||
"homepage": "https://vuejs.github.io/eslint-plugin-vue/", | ||
"homepage": "https://eslint.vuejs.org", | ||
"keywords": [ | ||
@@ -35,3 +34,3 @@ "eslint", | ||
"contributors": [ | ||
"Michał Sajnóg <msajnog93@gmail.com> (http://github.com/michalsnik)" | ||
"Michał Sajnóg <msajnog93@gmail.com> (https://github.com/michalsnik)" | ||
], | ||
@@ -53,3 +52,3 @@ "license": "MIT", | ||
"dependencies": { | ||
"vue-eslint-parser": "^4.0.2" | ||
"vue-eslint-parser": "^5.0.0" | ||
}, | ||
@@ -67,2 +66,3 @@ "devDependencies": { | ||
"nyc": "^12.0.2", | ||
"semver": "^5.6.0", | ||
"typescript": "^3.1.3", | ||
@@ -69,0 +69,0 @@ "typescript-eslint-parser": "^20.0.0", |
@@ -12,27 +12,27 @@ # eslint-plugin-vue | ||
See https://vuejs.github.io/eslint-plugin-vue/ | ||
See [the official website](https://eslint.vuejs.org). | ||
## :anchor: Versioning Policy | ||
This plugin is following [Semantic Versioning](http://semver.org/) and [ESLint's Semantic Versioning Policy](https://github.com/eslint/eslint#semantic-versioning-policy). | ||
This plugin is following [Semantic Versioning](https://semver.org/) and [ESLint's Semantic Versioning Policy](https://github.com/eslint/eslint#semantic-versioning-policy). | ||
## :newspaper: Changelog | ||
We're using [GitHub Releases](https://github.com/vuejs/eslint-plugin-vue/releases). | ||
This project uses [GitHub Releases](https://github.com/vuejs/eslint-plugin-vue/releases). | ||
## :beers: Contribution guide | ||
## :beers: Contribution Guide | ||
Contributing is welcome! | ||
Contribution is welcome! | ||
See https://vuejs.github.io/eslint-plugin-vue/developer-guide/ | ||
See [The ESLint Vue Plugin Developer Guide](https://eslint.vuejs.org/developer-guide/). | ||
### Working with rules | ||
### Working with Rules | ||
Before you start writing new rule, please read the [official ESLint guide](https://eslint.org/docs/developer-guide/working-with-rules). | ||
Before you start writing a new rule, please read [the official ESLint guide](https://eslint.org/docs/developer-guide/working-with-rules). | ||
Next in order to get an idea how does the AST of the code that you want to check looks like, you can use one of the following applications: | ||
- [astexplorer.net](http://astexplorer.net/) - best tool to inspect ASTs, but it doesn't support Vue templates yet | ||
- [ast.js.org](https://ast.js.org/) - not fully featured, but supports Vue templates syntax | ||
Next, in order to get an idea how does the AST of the code that you want to check looks like, use one of the following applications: | ||
- [astexplorer.net](https://astexplorer.net/) - the best tool to inspect ASTs, but it doesn't support Vue template yet | ||
- [ast.js.org](https://ast.js.org/) - not fully featured, but supports Vue template syntax | ||
Since single file components in Vue are not plain JavaScript, we can't use the default parser, and we had to introduce additional one: `vue-eslint-parser`, that generates enhanced AST with nodes that represent specific parts of the template syntax, as well as what's inside the `<script>` tag. | ||
Since single file components in Vue are not plain JavaScript, the default parser couldn't be used, so a new one was introduced. `vue-eslint-parser` generates enhanced AST with nodes that represent specific parts of the template syntax, as well as what's inside the `<script>` tag. | ||
@@ -43,11 +43,11 @@ To know more about certain nodes in produced ASTs, go here: | ||
The `vue-eslint-parser` provides few useful parser services, to help traverse the produced AST and access tokens of the template: | ||
The `vue-eslint-parser` provides a few useful parser services that help traverse the produced AST and access tokens of the template: | ||
- `context.parserServices.defineTemplateBodyVisitor(visitor, scriptVisitor)` | ||
- `context.parserServices.getTemplateBodyTokenStore()` | ||
Check out an [example rule](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/mustache-interpolation-spacing.js) to get a better understanding of how these work. | ||
Check out [an example rule](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/mustache-interpolation-spacing.js) to get a better understanding of how these work. | ||
Please be aware that regarding what kind of code examples you'll write in tests, you'll have to accordingly setup the parser in `RuleTester` (you can do it on per test case basis though). [See an example here](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/attribute-hyphenation.js#L19) | ||
Please be aware that regarding what kind of code examples you'll write in tests, you'll have to accordingly set up the parser in `RuleTester` (you can do it on a per test case basis). See an example [here](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/attribute-hyphenation.js#L19). | ||
If you'll stuck, remember there are plenty of rules you can learn from already, and if you can't find the right solution - don't hesitate to reach out in issues. We're happy to help! | ||
If you'll stuck, remember there are plenty of rules you can learn from already. If you can't find the right solution, don't hesitate to reach out in [issues](https://github.com/vuejs/eslint-plugin-vue/issues) – we're happy to help! | ||
@@ -54,0 +54,0 @@ ## :lock: License |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
302160
99
8435
0
15
1
+ Addedvue-eslint-parser@5.0.0(transitive)
- Removedvue-eslint-parser@4.0.3(transitive)
Updatedvue-eslint-parser@^5.0.0