diff --git a/.circleci/config.yml b/.circleci/config.yml
index c10b2139e..b80032ae8 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -4,6 +4,8 @@ workflows:
jobs:
- node-v8
- node-v10
+ - eslint-v7
+ - eslint-v8
- node-v12
- node-v14
- lint
@@ -54,6 +56,42 @@ jobs:
<<: *node-base
docker:
- image: node:10
+ eslint-v7:
+ docker:
+ - image: node:10
+ steps:
+ - run:
+ name: Versions
+ command: npm version
+ - checkout
+ - run:
+ name: Install eslint@7
+ command: |
+ npm install --save-exact eslint@7
+ - run:
+ name: Install dependencies
+ command: npm install
+ - run:
+ name: Test
+ command: npm test
+ eslint-v8:
+ docker:
+ - image: node:14
+ steps:
+ - run:
+ name: Versions
+ command: npm version
+ - checkout
+ - run:
+ name: Install eslint@8
+ command: |
+ npm install --save-exact eslint@^8.0.0-0
+ - run:
+ name: Install dependencies
+ command: npm install
+ - run:
+ name: Test
+ command: npm test
node-v12:
<<: *node-base
docker:
diff --git a/.eslintrc.js b/.eslintrc.js
index 704f09732..af1b9e745 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -126,18 +126,21 @@ module.exports = {
{
files: ['lib/rules/*.js'],
rules: {
- 'consistent-docs-description': 'error',
- 'no-invalid-meta': 'error',
- 'no-invalid-meta-docs-categories': 'error',
- 'eslint-plugin/require-meta-type': 'error',
- 'require-meta-docs-url': [
+ 'eslint-plugin/no-deprecated-context-methods': 'error',
+ 'eslint-plugin/no-only-tests': 'error',
+ 'eslint-plugin/prefer-object-rule': 'error',
+ 'eslint-plugin/require-meta-docs-description': 'error',
+ 'eslint-plugin/require-meta-docs-url': [
'error',
{
pattern: `https://eslint.vuejs.org/rules/{{name}}.html`
}
],
-
- 'eslint-plugin/fixer-return': 'off'
+ 'eslint-plugin/require-meta-has-suggestions': 'error',
+ 'eslint-plugin/require-meta-schema': 'error',
+ 'eslint-plugin/require-meta-type': 'error',
+ 'no-invalid-meta': 'error',
+ 'no-invalid-meta-docs-categories': 'error'
}
}
]
diff --git a/docs/rules/README.md b/docs/rules/README.md
index 4d87f7cc9..5f86b7fc7 100644
--- a/docs/rules/README.md
+++ b/docs/rules/README.md
@@ -324,6 +324,7 @@ For example:
| [vue/no-use-computed-property-like-method](./no-use-computed-property-like-method.md) | disallow use computed property like method | |
| [vue/no-useless-mustaches](./no-useless-mustaches.md) | disallow unnecessary mustache interpolations | :wrench: |
| [vue/no-useless-v-bind](./no-useless-v-bind.md) | disallow unnecessary `v-bind` directives | :wrench: |
+| [vue/no-v-text](./no-v-text.md) | disallow use of v-text | |
| [vue/padding-line-between-blocks](./padding-line-between-blocks.md) | require or disallow padding lines between blocks | :wrench: |
| [vue/require-direct-export](./require-direct-export.md) | require the component to be directly exported | |
| [vue/require-emit-validator](./require-emit-validator.md) | require type definitions in emits | |
diff --git a/docs/rules/no-v-text.md b/docs/rules/no-v-text.md
new file mode 100644
index 000000000..84cece3a4
--- /dev/null
+++ b/docs/rules/no-v-text.md
@@ -0,0 +1,41 @@
+---
+pageClass: rule-details
+sidebarDepth: 0
+title: vue/no-v-text
+description: disallow use of v-text
+since: v7.17.0
+---
+# vue/no-v-text
+
+> disallow use of v-text
+
+## :book: Rule Details
+
+This rule reports all uses of `v-text` directive.
+
+
+
+```vue
+
+
+ {{ foobar }}
+
+
+
+
+```
+
+
+
+## :wrench: Options
+
+Nothing.
+
+## :rocket: Version
+
+This rule was introduced in eslint-plugin-vue v7.17.0
+
+## :mag: Implementation
+
+- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-v-text.js)
+- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-v-text.js)
diff --git a/docs/user-guide/README.md b/docs/user-guide/README.md
index a056c912b..39e44d9ab 100644
--- a/docs/user-guide/README.md
+++ b/docs/user-guide/README.md
@@ -25,6 +25,8 @@ yarn add -D eslint eslint-plugin-vue
- ESLint v6.2.0 and above
- Node.js v8.10.0 and above
+We have started supporting ESLint v8.0.0 beta, but note that beta support will be dropped once the stable version is released.
+
:::
## :book: Usage
@@ -93,13 +95,13 @@ If you installed [@vue/cli-plugin-eslint](https://github.com/vuejs/vue-cli/tree/
### How to use a custom parser?
-If you want to use custom parsers such as [babel-eslint](https://www.npmjs.com/package/babel-eslint) or [@typescript-eslint/parser](https://www.npmjs.com/package/@typescript-eslint/parser), you have to use the `parserOptions.parser` option instead of the `parser` option. Because this plugin requires [vue-eslint-parser](https://www.npmjs.com/package/vue-eslint-parser) to parse `.vue` files, this plugin doesn't work if you overwrite the `parser` option.
+If you want to use custom parsers such as [@babel/eslint-parser](https://www.npmjs.com/package/@babel/eslint-parser) or [@typescript-eslint/parser](https://www.npmjs.com/package/@typescript-eslint/parser), you have to use the `parserOptions.parser` option instead of the `parser` option. Because this plugin requires [vue-eslint-parser](https://www.npmjs.com/package/vue-eslint-parser) to parse `.vue` files, this plugin doesn't work if you overwrite the `parser` option.
```diff
-- "parser": "babel-eslint",
+- "parser": "@typescript-eslint/parser",
+ "parser": "vue-eslint-parser",
"parserOptions": {
-+ "parser": "babel-eslint",
++ "parser": "@typescript-eslint/parser",
"sourceType": "module"
}
```
@@ -238,13 +240,13 @@ Make sure you have one of the following settings in your **.eslintrc**:
- `"extends": ["plugin:vue/vue3-recommended"]`
- `"extends": ["plugin:vue/base"]`
-If you already use another parser (e.g. `"parser": "babel-eslint"`), please move it into `parserOptions`, so it doesn't collide with the `vue-eslint-parser` used by this plugin's configuration:
+If you already use another parser (e.g. `"parser": "@typescript-eslint/parser"`), please move it into `parserOptions`, so it doesn't collide with the `vue-eslint-parser` used by this plugin's configuration:
```diff
-- "parser": "babel-eslint",
+- "parser": "@typescript-eslint/parser",
+ "parser": "vue-eslint-parser",
"parserOptions": {
-+ "parser": "babel-eslint",
++ "parser": "@typescript-eslint/parser",
"ecmaVersion": 2020,
"sourceType": "module"
}
@@ -331,7 +333,7 @@ Note that you cannot use angle-bracket type assertion style (`var x = bar;`
- Turning off the rule in the ESLint configuration file does not ignore the warning.
- Using the `` comment does not suppress warnings.
- Duplicate warnings are displayed.
-- Used `babel-eslint`, but the template still show `vue/no-parsing-error` warnings.
+- Used `@babel/eslint-parser`, but the template still show `vue/no-parsing-error` warnings.
You need to turn off Vetur's template validation by adding `vetur.validation.template: false` to your `.vscode/settings.json`.
@@ -398,20 +400,18 @@ module.exports = {
However, note that the AST generated by `espree` v8+ may not work well with some rules of `ESLint` v7.x.
-
#### Other Problems
diff --git a/eslint-internal-rules/.eslintrc.json b/eslint-internal-rules/.eslintrc.json
index 936029a17..42c0f65b1 100644
--- a/eslint-internal-rules/.eslintrc.json
+++ b/eslint-internal-rules/.eslintrc.json
@@ -1,6 +1,6 @@
{
"rules": {
- "consistent-docs-description": "error",
+ "no-invalid-meta-docs-categories": "error",
"no-invalid-meta": "error"
}
}
diff --git a/eslint-internal-rules/consistent-docs-description.js b/eslint-internal-rules/consistent-docs-description.js
deleted file mode 100644
index 6ff7f8673..000000000
--- a/eslint-internal-rules/consistent-docs-description.js
+++ /dev/null
@@ -1,141 +0,0 @@
-/**
- * @fileoverview Internal rule to enforce meta.docs.description conventions.
- * @author Vitor Balocco
- */
-
-'use strict'
-
-const ALLOWED_FIRST_WORDS = ['enforce', 'require', 'disallow']
-
-// ------------------------------------------------------------------------------
-// Helpers
-// ------------------------------------------------------------------------------
-
-/**
- * Gets the property of the Object node passed in that has the name specified.
- *
- * @param {string} property Name of the property to return.
- * @param {ASTNode} node The ObjectExpression node.
- * @returns {ASTNode} The Property node or null if not found.
- */
-function getPropertyFromObject(property, node) {
- if (node && node.type === 'ObjectExpression') {
- const properties = node.properties
-
- for (let i = 0; i < properties.length; i++) {
- if (properties[i].key.name === property) {
- return properties[i]
- }
- }
- }
- return null
-}
-
-/**
- * Verifies that the meta.docs.description property follows our internal conventions.
- *
- * @param {RuleContext} context The ESLint rule context.
- * @param {ASTNode} exportsNode ObjectExpression node that the rule exports.
- * @returns {void}
- */
-function checkMetaDocsDescription(context, exportsNode) {
- if (exportsNode.type !== 'ObjectExpression') {
- // if the exported node is not the correct format, "internal-no-invalid-meta" will already report this.
- return
- }
-
- const metaProperty = getPropertyFromObject('meta', exportsNode)
- const metaDocs =
- metaProperty && getPropertyFromObject('docs', metaProperty.value)
- const metaDocsDescription =
- metaDocs && getPropertyFromObject('description', metaDocs.value)
-
- if (!metaDocsDescription) {
- // if there is no `meta.docs.description` property, "internal-no-invalid-meta" will already report this.
- return
- }
-
- const description = metaDocsDescription.value.value
-
- if (typeof description !== 'string') {
- context.report({
- node: metaDocsDescription.value,
- message: '`meta.docs.description` should be a string.'
- })
- return
- }
-
- if (description === '') {
- context.report({
- node: metaDocsDescription.value,
- message: '`meta.docs.description` should not be empty.'
- })
- return
- }
-
- if (description.indexOf(' ') === 0) {
- context.report({
- node: metaDocsDescription.value,
- message: '`meta.docs.description` should not start with whitespace.'
- })
- return
- }
-
- const firstWord = description.split(' ')[0]
-
- if (ALLOWED_FIRST_WORDS.indexOf(firstWord) === -1) {
- context.report({
- node: metaDocsDescription.value,
- message:
- '`meta.docs.description` should start with one of the following words: {{ allowedWords }}. Started with "{{ firstWord }}" instead.',
- data: {
- allowedWords: ALLOWED_FIRST_WORDS.join(', '),
- firstWord
- }
- })
- }
-
- if (description.endsWith('.')) {
- context.report({
- node: metaDocsDescription.value,
- message: '`meta.docs.description` should not end with `.`.',
- fix(fixer) {
- const pos = metaDocsDescription.range[1] - 2
- return fixer.removeRange([pos, pos + 1])
- }
- })
- }
-}
-
-// ------------------------------------------------------------------------------
-// Rule Definition
-// ------------------------------------------------------------------------------
-
-module.exports = {
- meta: {
- docs: {
- description:
- 'enforce correct conventions of `meta.docs.description` property in core rules',
- categories: ['Internal']
- },
- fixable: 'code',
- schema: []
- },
-
- create(context) {
- return {
- AssignmentExpression(node) {
- if (
- node.left &&
- node.right &&
- node.left.type === 'MemberExpression' &&
- node.left.object.name === 'module' &&
- node.left.property.name === 'exports' &&
- node.right.type === 'ObjectExpression'
- ) {
- checkMetaDocsDescription(context, node.right)
- }
- }
- }
- }
-}
diff --git a/eslint-internal-rules/no-invalid-meta-docs-categories.js b/eslint-internal-rules/no-invalid-meta-docs-categories.js
index 74cfff1cd..5a86d16ab 100644
--- a/eslint-internal-rules/no-invalid-meta-docs-categories.js
+++ b/eslint-internal-rules/no-invalid-meta-docs-categories.js
@@ -108,16 +108,6 @@ function checkMetaValidity(context, exportsNode) {
}
}
-/**
- * Whether this node is the correct format for a rule definition or not.
- *
- * @param {ASTNode} node node that the rule exports.
- * @returns {boolean} `true` if the exported node is the correct format for a rule definition
- */
-function isCorrectExportsFormat(node) {
- return node != null && node.type === 'ObjectExpression'
-}
-
// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------
@@ -149,15 +139,6 @@ module.exports = {
},
'Program:exit'(programNode) {
- if (!isCorrectExportsFormat(exportsNode)) {
- context.report({
- node: exportsNode || programNode,
- message:
- 'Rule does not export an Object. Make sure the rule follows the new rule format.'
- })
- return
- }
-
checkMetaValidity(context, exportsNode)
}
}
diff --git a/eslint-internal-rules/no-invalid-meta.js b/eslint-internal-rules/no-invalid-meta.js
index a032023f9..e96435cf9 100644
--- a/eslint-internal-rules/no-invalid-meta.js
+++ b/eslint-internal-rules/no-invalid-meta.js
@@ -49,18 +49,6 @@ function hasMetaDocs(metaPropertyNode) {
return Boolean(getPropertyFromObject('docs', metaPropertyNode.value))
}
-/**
- * Whether this `meta` ObjectExpression has a `docs.description` property defined or not.
- *
- * @param {ASTNode} metaPropertyNode The `meta` ObjectExpression for this rule.
- * @returns {boolean} `true` if a `docs.description` property exists.
- */
-function hasMetaDocsDescription(metaPropertyNode) {
- const metaDocs = getPropertyFromObject('docs', metaPropertyNode.value)
-
- return metaDocs && getPropertyFromObject('description', metaDocs.value)
-}
-
/**
* Whether this `meta` ObjectExpression has a `docs.category` property defined or not.
*
@@ -73,16 +61,6 @@ function hasMetaDocsCategories(metaPropertyNode) {
return metaDocs && getPropertyFromObject('categories', metaDocs.value)
}
-/**
- * Whether this `meta` ObjectExpression has a `schema` property defined or not.
- *
- * @param {ASTNode} metaPropertyNode The `meta` ObjectExpression for this rule.
- * @returns {boolean} `true` if a `schema` property exists.
- */
-function hasMetaSchema(metaPropertyNode) {
- return getPropertyFromObject('schema', metaPropertyNode.value)
-}
-
/**
* Checks the validity of the meta definition of this rule and reports any errors found.
*
@@ -104,14 +82,6 @@ function checkMetaValidity(context, exportsNode) {
return
}
- if (!hasMetaDocsDescription(metaProperty)) {
- context.report(
- metaProperty,
- 'Rule is missing a meta.docs.description property.'
- )
- return
- }
-
if (!hasMetaDocsCategories(metaProperty)) {
context.report(
metaProperty,
@@ -119,20 +89,6 @@ function checkMetaValidity(context, exportsNode) {
)
return
}
-
- if (!hasMetaSchema(metaProperty)) {
- context.report(metaProperty, 'Rule is missing a meta.schema property.')
- }
-}
-
-/**
- * Whether this node is the correct format for a rule definition or not.
- *
- * @param {ASTNode} node node that the rule exports.
- * @returns {boolean} `true` if the exported node is the correct format for a rule definition
- */
-function isCorrectExportsFormat(node) {
- return node != null && node.type === 'ObjectExpression'
}
// ------------------------------------------------------------------------------
@@ -166,15 +122,6 @@ module.exports = {
},
'Program:exit'(programNode) {
- if (!isCorrectExportsFormat(exportsNode)) {
- context.report({
- node: exportsNode || programNode,
- message:
- 'Rule does not export an Object. Make sure the rule follows the new rule format.'
- })
- return
- }
-
checkMetaValidity(context, exportsNode)
}
}
diff --git a/eslint-internal-rules/require-meta-docs-url.js b/eslint-internal-rules/require-meta-docs-url.js
deleted file mode 100644
index 88cd9de0f..000000000
--- a/eslint-internal-rules/require-meta-docs-url.js
+++ /dev/null
@@ -1,280 +0,0 @@
-/**
- * @author Toru Nagashima
- * @author Teddy Katz
- *
- * Three functions `isNormalFunctionExpression`, `getKeyName`, and `getRuleInfo`
- * are copied from https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/lib/utils.js
- *
- * I have a plan to send this rule to that plugin: https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/issues/55
- */
-
-'use strict'
-
-// -----------------------------------------------------------------------------
-// Requirements
-// -----------------------------------------------------------------------------
-
-const path = require('path')
-
-// -----------------------------------------------------------------------------
-// Helpers
-// -----------------------------------------------------------------------------
-
-/**
- * Determines whether a node is a 'normal' (i.e. non-async, non-generator) function expression.
- * @param {ASTNode} node The node in question
- * @returns {boolean} `true` if the node is a normal function expression
- */
-function isNormalFunctionExpression(node) {
- return (
- (node.type === 'FunctionExpression' ||
- node.type === 'ArrowFunctionExpression') &&
- !node.generator &&
- !node.async
- )
-}
-
-/**
- * Gets the key name of a Property, if it can be determined statically.
- * @param {ASTNode} node The `Property` node
- * @returns {string|null} The key name, or `null` if the name cannot be determined statically.
- */
-function getKeyName(property) {
- if (!property.computed && property.key.type === 'Identifier') {
- return property.key.name
- }
- if (property.key.type === 'Literal') {
- return `${property.key.value}`
- }
- if (
- property.key.type === 'TemplateLiteral' &&
- property.key.quasis.length === 1
- ) {
- return property.key.quasis[0].value.cooked
- }
- return null
-}
-
-/**
-* Performs static analysis on an AST to try to determine the final value of `module.exports`.
-* @param {ASTNode} ast The `Program` AST node
-* @returns {Object} An object with keys `meta`, `create`, and `isNewStyle`. `meta` and `create` correspond to the AST nodes
-for the final values of `module.exports.meta` and `module.exports.create`. `isNewStyle` will be `true` if `module.exports`
-is an object, and `false` if module.exports is just the `create` function. If no valid ESLint rule info can be extracted
-from the file, the return value will be `null`.
-*/
-function getRuleInfo(ast) {
- const INTERESTING_KEYS = new Set(['create', 'meta'])
- let exportsVarOverridden = false
- let exportsIsFunction = false
-
- const exportNodes = ast.body
- .filter((statement) => statement.type === 'ExpressionStatement')
- .map((statement) => statement.expression)
- .filter((expression) => expression.type === 'AssignmentExpression')
- .filter((expression) => expression.left.type === 'MemberExpression')
- .reduce((currentExports, node) => {
- if (
- node.left.object.type === 'Identifier' &&
- node.left.object.name === 'module' &&
- node.left.property.type === 'Identifier' &&
- node.left.property.name === 'exports'
- ) {
- exportsVarOverridden = true
-
- if (isNormalFunctionExpression(node.right)) {
- // Check `module.exports = function () {}`
-
- exportsIsFunction = true
- return { create: node.right, meta: null }
- } else if (node.right.type === 'ObjectExpression') {
- // Check `module.exports = { create: function () {}, meta: {} }`
-
- exportsIsFunction = false
- return node.right.properties.reduce((parsedProps, prop) => {
- const keyValue = getKeyName(prop)
- if (INTERESTING_KEYS.has(keyValue)) {
- parsedProps[keyValue] = prop.value
- }
- return parsedProps
- }, {})
- }
- return {}
- } else if (
- !exportsIsFunction &&
- node.left.object.type === 'MemberExpression' &&
- node.left.object.object.type === 'Identifier' &&
- node.left.object.object.name === 'module' &&
- node.left.object.property.type === 'Identifier' &&
- node.left.object.property.name === 'exports' &&
- node.left.property.type === 'Identifier' &&
- INTERESTING_KEYS.has(node.left.property.name)
- ) {
- // Check `module.exports.create = () => {}`
-
- currentExports[node.left.property.name] = node.right
- } else if (
- !exportsVarOverridden &&
- node.left.object.type === 'Identifier' &&
- node.left.object.name === 'exports' &&
- node.left.property.type === 'Identifier' &&
- INTERESTING_KEYS.has(node.left.property.name)
- ) {
- // Check `exports.create = () => {}`
-
- currentExports[node.left.property.name] = node.right
- }
- return currentExports
- }, {})
-
- return Object.prototype.hasOwnProperty.call(exportNodes, 'create')
- ? Object.assign({ isNewStyle: !exportsIsFunction, meta: null }, exportNodes)
- : null
-}
-
-// -----------------------------------------------------------------------------
-// Rule Definition
-// -----------------------------------------------------------------------------
-
-module.exports = {
- meta: {
- docs: {
- description: 'require rules to implement a meta.docs.url property',
- categories: ['Rules'],
- recommended: false
- },
- fixable: 'code',
- schema: [
- {
- type: 'object',
- properties: {
- pattern: { type: 'string' }
- },
- additionalProperties: false
- }
- ]
- },
-
- /**
- * Creates AST event handlers for require-meta-docs-url.
- * @param {RuleContext} context - The rule context.
- * @returns {Object} AST event handlers.
- */
- create(context) {
- const options = context.options[0] || {}
- const sourceCode = context.getSourceCode()
- const filename = context.getFilename()
- const ruleName =
- filename === '' ? undefined : path.basename(filename, '.js')
- const expectedUrl =
- !options.pattern || !ruleName
- ? undefined
- : options.pattern.replace(/{{\s*name\s*}}/g, ruleName)
-
- /**
- * Check whether a given node is the expected URL.
- * @param {Node} node The node of property value to check.
- * @returns {boolean} `true` if the node is the expected URL.
- */
- function isExpectedUrl(node) {
- return Boolean(
- node &&
- node.type === 'Literal' &&
- typeof node.value === 'string' &&
- (expectedUrl === undefined || node.value === expectedUrl)
- )
- }
-
- /**
- * Insert a given property into a given object literal.
- * @param {SourceCodeFixer} fixer The fixer.
- * @param {Node} node The ObjectExpression node to insert a property.
- * @param {string} propertyText The property code to insert.
- * @returns {void}
- */
- function insertProperty(fixer, node, propertyText) {
- if (node.properties.length === 0) {
- return fixer.replaceText(node, `{\n${propertyText}\n}`)
- }
- return fixer.insertTextAfter(
- sourceCode.getLastToken(node.properties[node.properties.length - 1]),
- `,\n${propertyText}`
- )
- }
-
- return {
- Program(node) {
- const info = getRuleInfo(node)
- if (!info) {
- return
- }
- const metaNode = info.meta
- const docsPropNode =
- metaNode &&
- metaNode.properties &&
- metaNode.properties.find(
- (p) => p.type === 'Property' && getKeyName(p) === 'docs'
- )
- const urlPropNode =
- docsPropNode &&
- docsPropNode.value.properties &&
- docsPropNode.value.properties.find(
- (p) => p.type === 'Property' && getKeyName(p) === 'url'
- )
-
- if (isExpectedUrl(urlPropNode && urlPropNode.value)) {
- return
- }
-
- context.report({
- loc:
- (urlPropNode && urlPropNode.value.loc) ||
- (docsPropNode && docsPropNode.value.loc) ||
- (metaNode && metaNode.loc) ||
- node.loc.start,
-
- message: !urlPropNode
- ? 'Rules should export a `meta.docs.url` property.'
- : !expectedUrl
- ? '`meta.docs.url` property must be a string.'
- : /* otherwise */ '`meta.docs.url` property must be `{{expectedUrl}}`.',
-
- data: {
- expectedUrl
- },
-
- fix(fixer) {
- if (expectedUrl) {
- const urlString = JSON.stringify(expectedUrl)
- if (urlPropNode) {
- return fixer.replaceText(urlPropNode.value, urlString)
- }
- if (
- docsPropNode &&
- docsPropNode.value.type === 'ObjectExpression'
- ) {
- return insertProperty(
- fixer,
- docsPropNode.value,
- `url: ${urlString}`
- )
- }
- if (
- !docsPropNode &&
- metaNode &&
- metaNode.type === 'ObjectExpression'
- ) {
- return insertProperty(
- fixer,
- metaNode,
- `docs: {\nurl: ${urlString}\n}`
- )
- }
- }
- return null
- }
- })
- }
- }
- }
-}
diff --git a/lib/index.js b/lib/index.js
index d9352faa1..af29765ca 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -132,6 +132,7 @@ module.exports = {
'no-v-for-template-key': require('./rules/no-v-for-template-key'),
'no-v-html': require('./rules/no-v-html'),
'no-v-model-argument': require('./rules/no-v-model-argument'),
+ 'no-v-text': require('./rules/no-v-text'),
'no-watch-after-await': require('./rules/no-watch-after-await'),
'object-curly-newline': require('./rules/object-curly-newline'),
'object-curly-spacing': require('./rules/object-curly-spacing'),
diff --git a/lib/rules/comment-directive.js b/lib/rules/comment-directive.js
index 9ff9d2fdf..942860f60 100644
--- a/lib/rules/comment-directive.js
+++ b/lib/rules/comment-directive.js
@@ -1,7 +1,7 @@
/**
* @author Toru Nagashima
*/
-/* eslint-disable eslint-plugin/report-message-format, consistent-docs-description */
+/* eslint-disable eslint-plugin/report-message-format */
'use strict'
@@ -285,7 +285,7 @@ module.exports = {
meta: {
type: 'problem',
docs: {
- description: 'support comment-directives in ``',
+ description: 'support comment-directives in ``', // eslint-disable-line eslint-plugin/require-meta-docs-description
categories: ['base'],
url: 'https://eslint.vuejs.org/rules/comment-directive.html'
},
diff --git a/lib/rules/experimental-script-setup-vars.js b/lib/rules/experimental-script-setup-vars.js
index b7fa2a810..14c498de5 100644
--- a/lib/rules/experimental-script-setup-vars.js
+++ b/lib/rules/experimental-script-setup-vars.js
@@ -20,7 +20,7 @@ module.exports = {
type: 'problem',
docs: {
description:
- 'prevent variables defined in `
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.strictEqual(messages.length, 1)
assert.strictEqual(messages[0].ruleId, 'no-unused-vars')
})
- it('disable specific rules if ', () => {
+ it('disable specific rules if ', async () => {
const code = `
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 0)
})
})
describe('eslint-disable-line', () => {
- it('disable all rules if ', () => {
+ it('disable all rules if ', async () => {
const code = `
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 0)
})
- it('disable specific rules if ', () => {
+ it('disable specific rules if ', async () => {
const code = `
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 1)
assert.deepEqual(messages[0].ruleId, 'vue/no-parsing-error')
})
- it("don't disable rules if is on another line", () => {
+ it("don't disable rules if is on another line", async () => {
const code = `
@@ -179,8 +173,9 @@ describe('comment-directive', () => {
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 2)
assert.deepEqual(messages[0].ruleId, 'vue/no-parsing-error')
@@ -189,34 +184,36 @@ describe('comment-directive', () => {
})
describe('eslint-disable-next-line', () => {
- it('disable all rules if ', () => {
+ it('disable all rules if ', async () => {
const code = `
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 0)
})
- it('disable specific rules if ', () => {
+ it('disable specific rules if ', async () => {
const code = `
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 1)
assert.deepEqual(messages[0].ruleId, 'vue/no-parsing-error')
})
- it("don't disable rules if is on another line", () => {
+ it("don't disable rules if is on another line", async () => {
const code = `
@@ -225,15 +222,16 @@ describe('comment-directive', () => {
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 2)
assert.deepEqual(messages[0].ruleId, 'vue/no-parsing-error')
assert.deepEqual(messages[1].ruleId, 'vue/no-duplicate-attributes')
})
- it('should affect only the next line', () => {
+ it('should affect only the next line', async () => {
const code = `
@@ -241,8 +239,10 @@ describe('comment-directive', () => {
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 2)
assert.deepEqual(messages[0].ruleId, 'vue/no-parsing-error')
@@ -253,20 +253,21 @@ describe('comment-directive', () => {
})
describe('allow description', () => {
- it('disable all rules if ', () => {
+ it('disable all rules if ', async () => {
const code = `
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 0)
})
- it('enable all rules if ', () => {
+ it('enable all rules if ', async () => {
const code = `
@@ -275,8 +276,9 @@ describe('comment-directive', () => {
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 2)
assert.deepEqual(messages[0].ruleId, 'vue/no-parsing-error')
@@ -285,7 +287,7 @@ describe('comment-directive', () => {
assert.deepEqual(messages[1].line, 6)
})
- it('enable specific rules if ', () => {
+ it('enable specific rules if ', async () => {
const code = `
@@ -294,61 +296,66 @@ describe('comment-directive', () => {
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 1)
assert.deepEqual(messages[0].ruleId, 'vue/no-duplicate-attributes')
assert.deepEqual(messages[0].line, 6)
})
- it('disable all rules if ', () => {
+ it('disable all rules if ', async () => {
const code = `
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 0)
})
- it('disable specific rules if ', () => {
+ it('disable specific rules if ', async () => {
const code = `
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 1)
assert.deepEqual(messages[0].ruleId, 'vue/no-parsing-error')
})
- it('disable all rules if ', () => {
+ it('disable all rules if ', async () => {
const code = `
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 0)
})
- it('disable specific rules if ', () => {
+ it('disable specific rules if ', async () => {
const code = `
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 1)
assert.deepEqual(messages[0].ruleId, 'vue/no-parsing-error')
@@ -356,20 +363,21 @@ describe('comment-directive', () => {
})
describe('block level directive', () => {
- it('disable all rules if ', () => {
+ it('disable all rules if ', async () => {
const code = `
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 0)
})
- it("don't disable rules if is on after block", () => {
+ it("don't disable rules if is on after block", async () => {
const code = `
@@ -378,8 +386,10 @@ describe('comment-directive', () => {
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 2)
assert.deepEqual(messages[0].ruleId, 'vue/no-parsing-error')
@@ -388,32 +398,36 @@ describe('comment-directive', () => {
})
describe('reportUnusedDisableDirectives', () => {
- const linter = new eslint.CLIEngine({
- parser: require.resolve('vue-eslint-parser'),
- parserOptions: {
- ecmaVersion: 2015
- },
- plugins: ['vue'],
- rules: {
- 'no-unused-vars': 'error',
- 'vue/comment-directive': [
- 'error',
- { reportUnusedDisableDirectives: true }
- ],
- 'vue/no-parsing-error': 'error',
- 'vue/no-duplicate-attributes': 'error'
+ const eslint = new ESLint({
+ overrideConfig: {
+ parser: require.resolve('vue-eslint-parser'),
+ parserOptions: {
+ ecmaVersion: 2015
+ },
+ plugins: ['vue'],
+ rules: {
+ 'no-unused-vars': 'error',
+ 'vue/comment-directive': [
+ 'error',
+ { reportUnusedDisableDirectives: true }
+ ],
+ 'vue/no-parsing-error': 'error',
+ 'vue/no-duplicate-attributes': 'error'
+ }
},
useEslintrc: false
})
- it('report unused ', () => {
+ it('report unused ', async () => {
const code = `
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 1)
assert.deepEqual(messages[0].ruleId, 'vue/comment-directive')
@@ -425,19 +439,21 @@ describe('comment-directive', () => {
assert.deepEqual(messages[0].column, 11)
})
- it('dont report unused ', () => {
+ it('dont report unused ', async () => {
const code = `
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 0)
})
- it('disable and report unused ', () => {
+ it('disable and report unused ', async () => {
const code = `
@@ -447,8 +463,10 @@ describe('comment-directive', () => {
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 1)
assert.deepEqual(messages[0].ruleId, 'vue/comment-directive')
@@ -460,15 +478,17 @@ describe('comment-directive', () => {
assert.deepEqual(messages[0].column, 11)
})
- it('report unused ', () => {
+ it('report unused ', async () => {
const code = `
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 2)
@@ -489,7 +509,7 @@ describe('comment-directive', () => {
assert.deepEqual(messages[1].column, 60)
})
- it('report unused ', () => {
+ it('report unused ', async () => {
const code = `
@@ -497,8 +517,10 @@ describe('comment-directive', () => {
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 4)
@@ -524,20 +546,22 @@ describe('comment-directive', () => {
assert.deepEqual(messages[3].line, 5)
})
- it('dont report used ', () => {
+ it('dont report used ', async () => {
const code = `
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 0)
})
- it('dont report used, with duplicate eslint-disable', () => {
+ it('dont report used, with duplicate eslint-disable', async () => {
const code = `
@@ -545,8 +569,10 @@ describe('comment-directive', () => {
Hello
`
- const messages = linter.executeOnText(code, 'test.vue').results[0]
- .messages
+
+ const messages = (
+ await eslint.lintText(code, { filePath: 'test.vue' })
+ )[0].messages
assert.deepEqual(messages.length, 0)
})
diff --git a/tests/lib/rules/func-call-spacing.js b/tests/lib/rules/func-call-spacing.js
index d92502006..74fa4cb88 100644
--- a/tests/lib/rules/func-call-spacing.js
+++ b/tests/lib/rules/func-call-spacing.js
@@ -3,7 +3,7 @@
*/
'use strict'
-const { RuleTester, CLIEngine } = require('eslint')
+const { RuleTester, ESLint } = require('../../eslint-compat')
const semver = require('semver')
const rule = require('../../../lib/rules/func-call-spacing')
@@ -62,7 +62,7 @@ tester.run('func-call-spacing', rule, {
`,
errors: [
{
- message: semver.lt(CLIEngine.version, '7.0.0')
+ message: semver.lt(ESLint.version, '7.0.0')
? 'Unexpected newline between function name and paren.'
: 'Unexpected whitespace between function name and paren.',
line: 3
@@ -105,7 +105,7 @@ tester.run('func-call-spacing', rule, {
`,
errors: [
{
- message: semver.lt(CLIEngine.version, '7.0.0')
+ message: semver.lt(ESLint.version, '7.0.0')
? 'Unexpected newline between function name and paren.'
: 'Unexpected whitespace between function name and paren.',
line: 4
diff --git a/tests/lib/rules/jsx-uses-vars.js b/tests/lib/rules/jsx-uses-vars.js
index ea00e836c..f8b700bd6 100644
--- a/tests/lib/rules/jsx-uses-vars.js
+++ b/tests/lib/rules/jsx-uses-vars.js
@@ -10,7 +10,9 @@
const eslint = require('eslint')
const rule = require('../../../lib/rules/jsx-uses-vars')
-const ruleNoUnusedVars = require('eslint/lib/rules/no-unused-vars')
+const ruleNoUnusedVars = new (require('eslint').Linter)()
+ .getRules()
+ .get('no-unused-vars')
const RuleTester = eslint.RuleTester
const ruleTester = new RuleTester({
diff --git a/tests/lib/rules/no-v-text.js b/tests/lib/rules/no-v-text.js
new file mode 100644
index 000000000..c9820ce1a
--- /dev/null
+++ b/tests/lib/rules/no-v-text.js
@@ -0,0 +1,45 @@
+/**
+ * @author tyankatsu
+ * See LICENSE file in root directory for full license.
+ */
+
+'use strict'
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+const RuleTester = require('eslint').RuleTester
+const rule = require('../../../lib/rules/no-v-text')
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+const ruleTester = new RuleTester({
+ parser: require.resolve('vue-eslint-parser'),
+ parserOptions: { ecmaVersion: 2015 }
+})
+
+ruleTester.run('no-v-text', rule, {
+ valid: [
+ {
+ filename: 'test.vue',
+ code: ''
+ },
+ {
+ filename: 'test.vue',
+ code: ''
+ },
+ {
+ filename: 'test.vue',
+ code: '{{foobar}}
'
+ }
+ ],
+ invalid: [
+ {
+ filename: 'test.vue',
+ code: '',
+ errors: ["Don't use 'v-text'."]
+ }
+ ]
+})
diff --git a/tests/lib/rules/script-setup-uses-vars.js b/tests/lib/rules/script-setup-uses-vars.js
index 3cf9cde0c..f8287c0c7 100644
--- a/tests/lib/rules/script-setup-uses-vars.js
+++ b/tests/lib/rules/script-setup-uses-vars.js
@@ -11,7 +11,9 @@
const eslint = require('eslint')
const rule = require('../../../lib/rules/script-setup-uses-vars')
-const ruleNoUnusedVars = require('eslint/lib/rules/no-unused-vars')
+const ruleNoUnusedVars = new (require('eslint').Linter)()
+ .getRules()
+ .get('no-unused-vars')
const RuleTester = eslint.RuleTester
const ruleTester = new RuleTester({
diff --git a/tests/lib/rules/space-in-parens.js b/tests/lib/rules/space-in-parens.js
index 57be0b52e..8791652ed 100644
--- a/tests/lib/rules/space-in-parens.js
+++ b/tests/lib/rules/space-in-parens.js
@@ -3,11 +3,11 @@
*/
'use strict'
-const { RuleTester, CLIEngine } = require('eslint')
+const { RuleTester, ESLint } = require('../../eslint-compat')
const semver = require('semver')
const rule = require('../../../lib/rules/space-in-parens')
-const errorMessage = semver.lt(CLIEngine.version, '6.4.0')
+const errorMessage = semver.lt(ESLint.version, '6.4.0')
? (obj) => {
const messageId = obj.messageId
delete obj.messageId
diff --git a/tests/lib/rules/space-infix-ops.js b/tests/lib/rules/space-infix-ops.js
index 26b008d86..b8a679787 100644
--- a/tests/lib/rules/space-infix-ops.js
+++ b/tests/lib/rules/space-infix-ops.js
@@ -3,7 +3,7 @@
*/
'use strict'
-const { RuleTester, CLIEngine } = require('eslint')
+const { RuleTester, ESLint } = require('../../eslint-compat')
const semver = require('semver')
const rule = require('../../../lib/rules/space-infix-ops')
@@ -12,7 +12,7 @@ const tester = new RuleTester({
parserOptions: { ecmaVersion: 2015 }
})
-const message = semver.lt(CLIEngine.version, '5.10.0')
+const message = semver.lt(ESLint.version, '5.10.0')
? () => 'Infix operators must be spaced.'
: (operator) => `Operator '${operator}' must be spaced.`
diff --git a/typings/eslint/index.d.ts b/typings/eslint/index.d.ts
index fdbca8503..0a1cd36c4 100644
--- a/typings/eslint/index.d.ts
+++ b/typings/eslint/index.d.ts
@@ -123,9 +123,6 @@ export class SourceCode /*extends ESLintSourceCode*/ {
): string
getLines(): string[]
getAllComments(): VNODE.Comment[]
- getComments(
- node: VAST.ESNode
- ): { leading: VNODE.Comment[]; trailing: VNODE.Comment[] }
getJSDocComment(node: VAST.ESNode): AST.Token | null
getNodeByRangeIndex(index: number): VAST.ESNode | VAST.JSXNode
isSpaceBetweenTokens(first: AST.Token, second: AST.Token): boolean