123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- 'use strict'
- const utils = require('../utils')
- const regexp = require('../utils/regexp')
- function buildMatcher(str) {
- if (regexp.isRegExp(str)) {
- const re = regexp.toRegExp(str)
- return (s) => {
- re.lastIndex = 0
- return re.test(s)
- }
- }
- return (s) => s === str
- }
- function parseOption(option) {
- if (typeof option === 'string' || Array.isArray(option)) {
- return parseOption({
- name: option
- })
- }
-
-
- const steps = []
- for (const name of Array.isArray(option.name) ? option.name : [option.name]) {
- if (name === '*') {
- steps.push({ wildcard: true })
- } else {
- steps.push({ test: buildMatcher(name) })
- }
- }
- const message = option.message
- return {
- test: buildTester(0),
- message
- }
-
- function buildTester(index) {
- const step = steps[index]
- const next = index + 1
- const needNext = steps.length > next
- return (node) => {
-
- let keyName
- if (step.wildcard) {
- keyName = '*'
- } else {
- if (node.type !== 'Property') {
- return null
- }
- const name = utils.getStaticPropertyName(node)
- if (!name || !step.test(name)) {
- return null
- }
- keyName = name
- }
- return {
- next: needNext ? buildTester(next) : undefined,
- wildcard: step.wildcard,
- keyName
- }
- }
- }
- }
- module.exports = {
- meta: {
- type: 'suggestion',
- docs: {
- description: 'disallow specific component option',
- categories: undefined,
- url: 'https://eslint.vuejs.org/rules/no-restricted-component-options.html'
- },
- fixable: null,
- schema: {
- type: 'array',
- items: {
- oneOf: [
- { type: 'string' },
- {
- type: 'array',
- items: {
- type: 'string'
- }
- },
- {
- type: 'object',
- properties: {
- name: {
- anyOf: [
- { type: 'string' },
- {
- type: 'array',
- items: {
- type: 'string'
- }
- }
- ]
- },
- message: { type: 'string', minLength: 1 }
- },
- required: ['name'],
- additionalProperties: false
- }
- ]
- },
- uniqueItems: true,
- minItems: 0
- },
- messages: {
-
- restrictedOption: '{{message}}'
- }
- },
-
- create(context) {
- if (!context.options || context.options.length === 0) {
- return {}
- }
-
- const options = context.options.map(parseOption)
- return utils.defineVueVisitor(context, {
- onVueObjectEnter(node) {
- for (const option of options) {
- verify(node, option.test, option.message)
- }
- }
- })
-
- function verify(node, test, customMessage, path = []) {
- for (const prop of node.properties) {
- const result = test(prop)
- if (!result) {
- continue
- }
- if (result.next) {
- if (
- prop.type !== 'Property' ||
- prop.value.type !== 'ObjectExpression'
- ) {
- continue
- }
- verify(prop.value, result.next, customMessage, [
- ...path,
- result.keyName
- ])
- } else {
- const message =
- customMessage || defaultMessage([...path, result.keyName])
- context.report({
- node: prop.type === 'Property' ? prop.key : prop,
- messageId: 'restrictedOption',
- data: { message }
- })
- }
- }
- }
-
- function defaultMessage(path) {
- return `Using \`${path.join('.')}\` is not allowed.`
- }
- }
- }
|