diff --git a/eslint.config.js b/eslint.config.js index 3b614a0df434252d290c8d01646714ac8da1d2d0..3576ce7dbb5ed244b78a4192ac0eb2cfa7ad5f9e 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,3 +1,17 @@ import antfu from '@antfu/eslint-config' +import enforceScriptSetupTag from './eslint_rules/enforce-script-setup-tag.js' -export default antfu() +export default antfu().append([ + { + rules: { + 'nextvs/enforce-script-setup-tag': 'error', + }, + plugins: { + nextvs: { + rules: { + 'enforce-script-setup-tag': enforceScriptSetupTag, + } + } + } + } +]) diff --git a/eslint_rules/enforce-script-setup-tag.js b/eslint_rules/enforce-script-setup-tag.js new file mode 100644 index 0000000000000000000000000000000000000000..3310f452c16b3fb63a5d036918c571a66a18a9d0 --- /dev/null +++ b/eslint_rules/enforce-script-setup-tag.js @@ -0,0 +1,43 @@ +export default { + meta: { + type: 'problem', + docs: { + description: 'Enforce <script> to have the \'setup\' attribute', + category: 'Best Practices', + recommended: false, + }, + fixable: 'code', + schema: [], + }, + create(context) { + return { + Program(_node) { + const sourceCode = context.getSourceCode() + const tokens = sourceCode.ast.tokens + const code = sourceCode.getText() + const file_name = context.getFilename() + if (!file_name.endsWith('.vue')) { + return + } + if (file_name.includes('node_modules')) { + return + } + + tokens.forEach((token) => { + if (token.type === 'Punctuator' && token.value === '<script>') { + const script_tag = code.slice(token.range[0], token.range[1]) + if (!/\bsetup\b/.test(script_tag)) { + context.report({ + node: token, + message: '<script> tags must have the \'setup\' attribute.', + fix(fixer) { + return fixer.replaceTextRange([token.range[0], token.range[0] + '<script'.length], '<script setup') + }, + }) + } + } + }) + }, + } + }, +}