/** * @author Yosuke Ota * See LICENSE file in root directory for full license. */ 'use strict' const semver = require('semver') const utils = require('../utils') /** * @typedef {object} SyntaxRule * @property {string} supported * @property { (context: RuleContext) => TemplateListener } [createTemplateBodyVisitor] * @property { (context: RuleContext) => RuleListener } [createScriptVisitor] */ const FEATURES = { // Vue.js 2.5.0+ 'slot-scope-attribute': require('./syntaxes/slot-scope-attribute'), // Vue.js 2.6.0+ 'dynamic-directive-arguments': require('./syntaxes/dynamic-directive-arguments'), 'v-slot': require('./syntaxes/v-slot'), // Vue.js 2.7.0+ 'script-setup': require('./syntaxes/script-setup'), 'style-css-vars-injection': require('./syntaxes/style-css-vars-injection'), // Vue.js 3.0.0+ 'v-model-argument': require('./syntaxes/v-model-argument'), 'v-model-custom-modifiers': require('./syntaxes/v-model-custom-modifiers'), 'v-is': require('./syntaxes/v-is'), // Vue.js 3.1.0+ 'is-attribute-with-vue-prefix': require('./syntaxes/is-attribute-with-vue-prefix'), // Vue.js 3.2.0+ 'v-memo': require('./syntaxes/v-memo'), 'v-bind-prop-modifier-shorthand': require('./syntaxes/v-bind-prop-modifier-shorthand'), 'v-bind-attr-modifier': require('./syntaxes/v-bind-attr-modifier'), // Vue.js 3.3.0+ 'define-options': require('./syntaxes/define-options'), 'define-slots': require('./syntaxes/define-slots'), // Vue.js 3.4.0+ 'define-model': require('./syntaxes/define-model'), 'v-bind-same-name-shorthand': require('./syntaxes/v-bind-same-name-shorthand') } const SYNTAX_NAMES = /** @type {(keyof FEATURES)[]} */ (Object.keys(FEATURES)) const cache = new Map() /** * Get the `semver.Range` object of a given range text. * @param {string} x The text expression for a semver range. * @returns {semver.Range} The range object of a given range text. * It's null if the `x` is not a valid range text. */ function getSemverRange(x) { const s = String(x) let ret = cache.get(s) || null if (!ret) { try { ret = new semver.Range(s) } catch (_error) { // Ignore parsing error. } cache.set(s, ret) } return ret } module.exports = { meta: { type: 'suggestion', docs: { description: 'disallow unsupported Vue.js syntax on the specified version', categories: undefined, url: 'https://eslint.vuejs.org/rules/no-unsupported-features.html' }, // eslint-disable-next-line eslint-plugin/require-meta-fixable -- fixer is not recognized fixable: 'code', schema: [ { type: 'object', properties: { version: { type: 'string' }, ignores: { type: 'array', items: { enum: SYNTAX_NAMES }, uniqueItems: true } }, additionalProperties: false } ], messages: { // Vue.js 2.5.0+ forbiddenSlotScopeAttribute: '`slot-scope` are not supported except Vue.js ">=2.5.0 <3.0.0".', // Vue.js 2.6.0+ forbiddenDynamicDirectiveArguments: 'Dynamic arguments are not supported until Vue.js "2.6.0".', forbiddenVSlot: '`v-slot` are not supported until Vue.js "2.6.0".', // Vue.js 2.7.0+ forbiddenScriptSetup: '`