vue hello world项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 lines
3.7 KiB

3 years ago
/**
* @author Yosuke Ota
* See LICENSE file in root directory for full license.
*/
'use strict'
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const vue3ExportNames = new Set(require('../utils/vue3-export-names.json'))
// ------------------------------------------------------------------------------
// Helpers
// ------------------------------------------------------------------------------
const TARGET_AT_VUE_MODULES = new Set([
'@vue/runtime-dom',
'@vue/runtime-core',
'@vue/reactivity',
'@vue/shared'
])
// Modules with the names of a subset of vue.
const SUBSET_AT_VUE_MODULES = new Set(['@vue/runtime-dom', '@vue/runtime-core'])
/**
* @param {ImportDeclaration} node
*/
function* extractImportNames(node) {
for (const specifier of node.specifiers) {
if (specifier.type === 'ImportDefaultSpecifier') {
yield 'default'
} else if (specifier.type === 'ImportNamespaceSpecifier') {
yield null // all
} else if (specifier.type === 'ImportSpecifier') {
yield specifier.imported.name
}
}
}
// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------
module.exports = {
meta: {
type: 'suggestion',
docs: {
description: "enforce import from 'vue' instead of import from '@vue/*'",
// TODO We will change it in the next major version.
// categories: ['vue3-essential'],
categories: undefined,
url: 'https://eslint.vuejs.org/rules/prefer-import-from-vue.html'
},
fixable: 'code',
schema: [],
messages: {
importedAtVue: "Import from 'vue' instead of '{{source}}'."
}
},
/**
* @param {RuleContext} context
* @returns {RuleListener}
*/
create(context) {
/**
*
* @param {Literal & { value: string }} source
* @param { () => boolean } fixable
*/
function verifySource(source, fixable) {
if (!TARGET_AT_VUE_MODULES.has(source.value)) {
return
}
context.report({
node: source,
messageId: 'importedAtVue',
data: { source: source.value },
fix: fixable()
? (fixer) =>
fixer.replaceTextRange(
[source.range[0] + 1, source.range[1] - 1],
'vue'
)
: null
})
}
return {
ImportDeclaration(node) {
verifySource(node.source, () => {
if (SUBSET_AT_VUE_MODULES.has(node.source.value)) {
// If the module is a subset of 'vue', we can safely change it to 'vue'.
return true
}
for (const name of extractImportNames(node)) {
if (name == null) {
return false // import all
}
if (!vue3ExportNames.has(name)) {
// If there is a name that is not exported from 'vue', it will not be auto-fixed.
return false
}
}
return true
})
},
ExportNamedDeclaration(node) {
if (node.source) {
verifySource(node.source, () => {
for (const specifier of node.specifiers) {
if (!vue3ExportNames.has(specifier.local.name)) {
// If there is a name that is not exported from 'vue', it will not be auto-fixed.
return false
}
}
return true
})
}
},
ExportAllDeclaration(node) {
verifySource(
node.source,
// If we change it to `from 'vue'`, it will export more, so it will not be auto-fixed.
() => false
)
}
}
}
}