eslint-plugin-vue-setup-order 1.0.1 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/index.cjs +20 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# eslint-plugin-vue-setup-order
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/eslint-plugin-vue-setup-order)
|
|
4
|
+
[](https://www.npmjs.com/package/eslint-plugin-vue-setup-order)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
3
7
|
ESLint plugin to enforce a consistent order of statements within the Vue 3 `<script setup>` block.
|
|
4
8
|
|
|
5
9
|
## Installation
|
package/dist/index.cjs
CHANGED
|
@@ -283,6 +283,8 @@ var rule = {
|
|
|
283
283
|
},
|
|
284
284
|
create(context) {
|
|
285
285
|
const sourceCode = context.sourceCode ?? context.getSourceCode();
|
|
286
|
+
const filename = context.getFilename();
|
|
287
|
+
const isVue = filename.endsWith(".vue");
|
|
286
288
|
const options = context.options[0] || {};
|
|
287
289
|
const groupBlankLines = false !== options.groupBlankLines;
|
|
288
290
|
const orderConfig = { ...DEFAULT_ORDER };
|
|
@@ -302,7 +304,25 @@ var rule = {
|
|
|
302
304
|
return {
|
|
303
305
|
Program(node) {
|
|
304
306
|
const statements = [];
|
|
307
|
+
let scriptSetupRange;
|
|
308
|
+
if (isVue) {
|
|
309
|
+
const parserServices = sourceCode.parserServices;
|
|
310
|
+
if (parserServices?.getDocumentFragment) {
|
|
311
|
+
const df = parserServices.getDocumentFragment();
|
|
312
|
+
const scriptSetup = df.children.find(
|
|
313
|
+
(n) => n.type === "VElement" && n.name === "script" && n.startTag.attributes.some((attr) => !attr.directive && attr.key.name === "setup")
|
|
314
|
+
);
|
|
315
|
+
if (scriptSetup) {
|
|
316
|
+
scriptSetupRange = scriptSetup.range;
|
|
317
|
+
} else {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
305
322
|
for (const statement of node.body) {
|
|
323
|
+
if (isVue && scriptSetupRange && (statement.range[0] < scriptSetupRange[0] || statement.range[1] > scriptSetupRange[1])) {
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
306
326
|
const analyzed = analyzeStatement(statement, sourceCode, orderConfig);
|
|
307
327
|
if (analyzed) {
|
|
308
328
|
statements.push(analyzed);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/utils/constants.ts","../src/utils/analyze.ts","../src/utils/source-code.ts","../src/rules/order.ts"],"sourcesContent":["import orderRule from './rules/order';\n\nconst plugin = {\n meta: {\n name: 'eslint-plugin-vue-setup-order',\n version: '1.0.0',\n },\n rules: {\n order: orderRule,\n },\n configs: {\n recommended: {\n plugins: ['vue-setup-order'],\n rules: {\n 'vue-setup-order/order': 'error',\n },\n },\n // Flat config format for ESLint 9+\n flat: {\n recommended: {\n plugins: {\n get 'vue-setup-order'() {\n return plugin;\n },\n },\n rules: {\n 'vue-setup-order/order': 'error',\n },\n },\n },\n },\n};\n\nexport default plugin;\n","import type { OrderConfig } from '../types';\n\nexport const CATEGORY_IMPORT = 0;\nexport const CATEGORY_TYPES = 1;\nexport const CATEGORY_DEFINE = 2;\nexport const CATEGORY_COMPOSABLE = 3;\nexport const CATEGORY_REACTIVE = 4;\nexport const CATEGORY_COMPUTED = 5;\nexport const CATEGORY_WATCH = 6;\nexport const CATEGORY_LIFECYCLE = 7;\nexport const CATEGORY_FUNCTION = 8;\nexport const CATEGORY_PROVIDE = 9;\nexport const CATEGORY_UNKNOWN = 99;\n\nexport const DEFAULT_ORDER: OrderConfig = {\n // Imports\n import: CATEGORY_IMPORT,\n\n // Types\n types: CATEGORY_TYPES,\n\n // Define macros\n defineOptions: CATEGORY_DEFINE,\n defineProps: CATEGORY_DEFINE,\n defineEmits: CATEGORY_DEFINE,\n defineSlots: CATEGORY_DEFINE,\n defineExpose: CATEGORY_DEFINE,\n defineModel: CATEGORY_DEFINE,\n withDefaults: CATEGORY_DEFINE,\n\n // Composables\n composable: CATEGORY_COMPOSABLE,\n\n // Reactive state\n ref: CATEGORY_REACTIVE,\n reactive: CATEGORY_REACTIVE,\n shallowRef: CATEGORY_REACTIVE,\n shallowReactive: CATEGORY_REACTIVE,\n toRef: CATEGORY_REACTIVE,\n toRefs: CATEGORY_REACTIVE,\n customRef: CATEGORY_REACTIVE,\n readonly: CATEGORY_REACTIVE,\n shallowReadonly: CATEGORY_REACTIVE,\n\n // Computed\n computed: CATEGORY_COMPUTED,\n\n // Watchers\n watch: CATEGORY_WATCH,\n watchEffect: CATEGORY_WATCH,\n watchPostEffect: CATEGORY_WATCH,\n watchSyncEffect: CATEGORY_WATCH,\n\n // Lifecycle hooks\n onBeforeMount: CATEGORY_LIFECYCLE,\n onMounted: CATEGORY_LIFECYCLE,\n onBeforeUpdate: CATEGORY_LIFECYCLE,\n onUpdated: CATEGORY_LIFECYCLE,\n onBeforeUnmount: CATEGORY_LIFECYCLE,\n onUnmounted: CATEGORY_LIFECYCLE,\n onActivated: CATEGORY_LIFECYCLE,\n onDeactivated: CATEGORY_LIFECYCLE,\n onErrorCaptured: CATEGORY_LIFECYCLE,\n onRenderTracked: CATEGORY_LIFECYCLE,\n onRenderTriggered: CATEGORY_LIFECYCLE,\n onServerPrefetch: CATEGORY_LIFECYCLE,\n\n // Functions\n function: CATEGORY_FUNCTION,\n\n // Provide\n provide: CATEGORY_PROVIDE,\n\n // Unknown\n unknown: CATEGORY_UNKNOWN,\n};\n\nexport const ORDER_NAMES: Record<number, string> = {\n [CATEGORY_IMPORT]: 'imports',\n [CATEGORY_TYPES]: 'type declarations',\n [CATEGORY_DEFINE]: 'define macros',\n [CATEGORY_COMPOSABLE]: 'composables',\n [CATEGORY_REACTIVE]: 'reactive state',\n [CATEGORY_COMPUTED]: 'computed properties',\n [CATEGORY_WATCH]: 'watchers',\n [CATEGORY_LIFECYCLE]: 'lifecycle hooks',\n [CATEGORY_FUNCTION]: 'functions',\n [CATEGORY_PROVIDE]: 'provide',\n [CATEGORY_UNKNOWN]: 'other',\n};\n\nexport const COMPOSABLE_PATTERN = /^use[A-Z]/;\n","import type { Rule } from 'eslint';\nimport type { Expression, ModuleDeclaration, Statement, Super } from 'estree';\nimport type { AnalyzedStatement, OrderConfig } from '../types';\nimport {\n CATEGORY_FUNCTION,\n CATEGORY_REACTIVE,\n CATEGORY_TYPES,\n CATEGORY_UNKNOWN,\n COMPOSABLE_PATTERN,\n} from './constants';\n\n/**\n * Retrieves the name of the callee from the provided node (Expression or Super).\n *\n * @param {Expression | Super | null | undefined} node - The node representing a callee, which can be an Expression or Super. May be null or undefined.\n * @param {Rule.RuleContext['sourceCode']} sourceCode - The source code object used to extract the callee name in case it's a MemberExpression.\n * @return {string | null} The name of the callee as a string if resolved, or null if the node is null, undefined, or not resolvable.\n */\nexport function getCalleeName(\n node: Expression | Super | null | undefined,\n sourceCode: Rule.RuleContext['sourceCode'],\n): string | null {\n if (!node) return null;\n\n if (node.type === 'Identifier') {\n return node.name;\n }\n\n if (node.type === 'MemberExpression') {\n return sourceCode.getText(node);\n }\n\n return null;\n}\n\n/**\n * Determines if the provided name is composable based on a predefined pattern.\n *\n * @param {string | null} name - The name to be tested against the composable pattern. Can be null.\n * @return {boolean} Returns true if the name matches the composable pattern and is not null; otherwise, returns false.\n */\nexport function isComposable(name: string | null): boolean {\n return name !== null && COMPOSABLE_PATTERN.test(name);\n}\n\n/**\n * Analyzes a given statement or module declaration to categorize, name, and assign an order based on the specified configuration.\n *\n * @param {Statement | ModuleDeclaration} statement - The statement or module declaration to be analyzed.\n * @param {Rule.RuleContext['sourceCode']} sourceCode - The source code context to extract details about the statement.\n * @param {OrderConfig} orderConfig - Configuration object that defines ordering and categorization rules.\n * @return {AnalyzedStatement | null} An object containing analysis details of the statement, or null for certain export declarations.\n */\nexport function analyzeStatement(\n statement: Statement | ModuleDeclaration,\n sourceCode: Rule.RuleContext['sourceCode'],\n orderConfig: OrderConfig,\n): AnalyzedStatement | null {\n const result: AnalyzedStatement = {\n node: statement as Statement,\n order: orderConfig.unknown ?? CATEGORY_UNKNOWN,\n name: 'unknown',\n category: 'unknown',\n };\n\n if (statement.type === 'ImportDeclaration') {\n result.order = orderConfig.import;\n result.name = 'import';\n result.category = 'import';\n return result;\n }\n\n const statementType = (statement as { type: string }).type;\n if (\n statementType === 'TSTypeAliasDeclaration' ||\n statementType === 'TSInterfaceDeclaration' ||\n statementType === 'TSEnumDeclaration'\n ) {\n result.order = orderConfig.types ?? CATEGORY_TYPES;\n result.name =\n statementType === 'TSTypeAliasDeclaration'\n ? 'type'\n : statementType === 'TSInterfaceDeclaration'\n ? 'interface'\n : 'enum';\n result.category = 'types';\n return result;\n }\n\n if (\n statement.type === 'ExportNamedDeclaration' ||\n statement.type === 'ExportDefaultDeclaration' ||\n statement.type === 'ExportAllDeclaration'\n ) {\n return null;\n }\n\n if (statement.type === 'VariableDeclaration') {\n const declaration = statement.declarations[0];\n const init = declaration?.init;\n\n if (!init) {\n result.order = orderConfig.ref ?? CATEGORY_REACTIVE;\n result.name = 'variable';\n result.category = 'reactive';\n return result;\n }\n\n if (init.type === 'CallExpression') {\n const calleeName = getCalleeName(init.callee, sourceCode);\n\n if (calleeName) {\n if (isComposable(calleeName)) {\n result.order = orderConfig.composable;\n result.name = calleeName;\n result.category = 'composable';\n return result;\n }\n\n if (orderConfig[calleeName] !== undefined) {\n result.order = orderConfig[calleeName];\n result.name = calleeName;\n result.category = calleeName;\n return result;\n }\n }\n\n result.order = orderConfig.ref ?? CATEGORY_REACTIVE;\n result.name = calleeName || 'variable';\n result.category = 'reactive';\n return result;\n }\n\n if (init.type === 'ArrowFunctionExpression' || init.type === 'FunctionExpression') {\n result.order = orderConfig.function ?? CATEGORY_FUNCTION;\n result.name = declaration.id?.type === 'Identifier' ? declaration.id.name : 'arrow function';\n result.category = 'function';\n return result;\n }\n\n result.order = orderConfig.ref ?? CATEGORY_REACTIVE;\n result.name = 'variable';\n result.category = 'reactive';\n return result;\n }\n\n if (statement.type === 'FunctionDeclaration') {\n result.order = orderConfig.function ?? CATEGORY_FUNCTION;\n result.name = statement.id?.name || 'function';\n result.category = 'function';\n return result;\n }\n\n if (statement.type === 'ExpressionStatement') {\n const expr = statement.expression;\n\n if (expr.type === 'CallExpression') {\n const calleeName = getCalleeName(expr.callee, sourceCode);\n\n if (calleeName && orderConfig[calleeName] !== undefined) {\n result.order = orderConfig[calleeName];\n result.name = calleeName;\n result.category = calleeName;\n return result;\n }\n\n result.order = orderConfig.unknown ?? CATEGORY_UNKNOWN;\n result.name = calleeName || 'call';\n result.category = 'unknown';\n return result;\n }\n\n result.order = orderConfig.unknown ?? CATEGORY_UNKNOWN;\n result.name = 'expression';\n result.category = 'unknown';\n return result;\n }\n\n return result;\n}\n","import type { Rule } from 'eslint';\nimport type { Statement } from 'estree';\n\n/**\n * Retrieves the combined text of a given AST node and its preceding comments from the source code.\n *\n * @param {Statement} node - The AST node whose text and preceding comments are to be retrieved.\n * @param {Rule.RuleContext['sourceCode']} sourceCode - The source code object containing the text and comments.\n * @return {string} The concatenated text of the node and its preceding comments.\n */\nexport function getNodeTextWithComments(node: Statement, sourceCode: Rule.RuleContext['sourceCode']): string {\n const comments = sourceCode.getCommentsBefore(node);\n let start = node.range![0];\n\n if (comments.length > 0) {\n start = comments[0].range![0];\n }\n\n return sourceCode.text.slice(start, node.range![1]);\n}\n\n/**\n * Determines the full range of a given statement node, including its preceding comments\n * and any trailing newlines immediately following the node.\n *\n * @param {Statement} node - The statement node for which to calculate the full range.\n * @param {Rule.RuleContext['sourceCode']} sourceCode - The source code object used to retrieve comments and text.\n * @return {[number, number]} The start and end positions of the full range in the source code.\n */\nexport function getFullRange(node: Statement, sourceCode: Rule.RuleContext['sourceCode']): [number, number] {\n const comments = sourceCode.getCommentsBefore(node);\n let start = node.range![0];\n\n if (comments.length > 0) {\n start = comments[0].range![0];\n }\n\n let end = node.range![1];\n const textAfter = sourceCode.text.slice(end, end + 2);\n\n if (textAfter.startsWith('\\r\\n')) {\n end += 2;\n } else if (textAfter.startsWith('\\n')) {\n end += 1;\n }\n\n return [start, end];\n}\n\n/**\n * Generates a sorted string representation of code statements, optionally adding blank lines between different categories.\n *\n * @param {Array<{ node: Statement, order: number }>} statements - An array of objects containing a statement node and its corresponding order.\n * @param {Rule.RuleContext['sourceCode']} sourceCode - The source code object used to extract the textual representation of the statement nodes.\n * @param {boolean} [addBlankLines=true] - A flag indicating whether to add blank lines between statements of differing orders.\n * @return {string} A sorted and formatted code string based on the given statements and options.\n */\nexport function generateSortedCode(\n statements: Array<{ node: Statement; order: number }>,\n sourceCode: Rule.RuleContext['sourceCode'],\n addBlankLines: boolean = true,\n): string {\n const parts: string[] = [];\n let lastOrder = -1;\n\n for (const statement of statements) {\n const text = getNodeTextWithComments(statement.node, sourceCode).trim();\n\n if (addBlankLines && lastOrder !== -1 && statement.order !== lastOrder) {\n parts.push('');\n }\n\n parts.push(text);\n lastOrder = statement.order;\n }\n\n return parts.join('\\n');\n}\n","import type { Rule } from 'eslint';\nimport type { Program } from 'estree';\nimport type { AnalyzedStatement, OrderConfig, PluginOptions } from '../types';\nimport { analyzeStatement } from '../utils/analyze';\nimport { DEFAULT_ORDER, ORDER_NAMES } from '../utils/constants';\nimport { generateSortedCode, getFullRange } from '../utils/source-code';\n\n/**\n * Represents an ESLint rule module designed to enforce a consistent order of statements\n * in the `<script setup>` block of Vue 3 components.\n *\n * The rule provides configuration options for defining custom ordering of statement categories\n * and for including blank lines between different categories. The rule reports and optionally\n * fixes statement order violations.\n */\nconst rule: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Enforce consistent order of statements in Vue 3 <script setup>',\n category: 'Stylistic Issues',\n recommended: true,\n url: 'https://github.com/d2a8k3u/eslint-plugin-vue-setup-order#readme',\n },\n fixable: 'code',\n schema: [\n {\n type: 'object',\n properties: {\n order: {\n type: 'array',\n items: { type: 'string' },\n description: 'Custom order of categories',\n },\n groupBlankLines: {\n type: 'boolean',\n default: true,\n description: 'Add blank lines between different categories',\n },\n },\n additionalProperties: false,\n },\n ],\n messages: {\n wrongOrder: \"'{{current}}' ({{currentCategory}}) should come before '{{previous}}' ({{previousCategory}})\",\n },\n },\n\n create(context: Rule.RuleContext) {\n const sourceCode = context.sourceCode ?? context.getSourceCode();\n const options: PluginOptions = context.options[0] || {};\n const groupBlankLines = false !== options.groupBlankLines;\n const orderConfig: OrderConfig = { ...DEFAULT_ORDER };\n\n if (options.order && Array.isArray(options.order)) {\n options.order.forEach((category, index) => {\n const originalOrder = DEFAULT_ORDER[category];\n if (originalOrder !== undefined) {\n Object.keys(DEFAULT_ORDER).forEach((key) => {\n if (DEFAULT_ORDER[key] === originalOrder) {\n orderConfig[key] = index;\n }\n });\n }\n orderConfig[category] = index;\n });\n }\n\n return {\n Program(node: Program) {\n const statements: AnalyzedStatement[] = [];\n\n for (const statement of node.body) {\n const analyzed = analyzeStatement(statement, sourceCode, orderConfig);\n if (analyzed) {\n statements.push(analyzed);\n }\n }\n\n if (statements.length < 2) return;\n\n let firstError: {\n index: number;\n current: AnalyzedStatement;\n previous: AnalyzedStatement;\n } | null = null;\n\n for (let i = 1; i < statements.length; i++) {\n const prev = statements[i - 1];\n const curr = statements[i];\n\n if (curr.order < prev.order) {\n firstError = { index: i, current: curr, previous: prev };\n break;\n }\n }\n\n if (!firstError) return;\n\n context.report({\n node: firstError.current.node,\n messageId: 'wrongOrder',\n data: {\n current: firstError.current.name,\n currentCategory: ORDER_NAMES[firstError.current.order] || 'unknown',\n previous: firstError.previous.name,\n previousCategory: ORDER_NAMES[firstError.previous.order] || 'unknown',\n },\n fix(fixer) {\n const sorted = [...statements].sort((a, b) => {\n if (a.order !== b.order) {\n return a.order - b.order;\n }\n\n return statements.indexOf(a) - statements.indexOf(b);\n });\n\n const newCode = generateSortedCode(sorted, sourceCode, groupBlankLines);\n const firstRange = getFullRange(statements[0].node, sourceCode);\n const lastRange = getFullRange(statements[statements.length - 1].node, sourceCode);\n\n return fixer.replaceTextRange([firstRange[0], lastRange[1]], newCode + '\\n');\n },\n });\n },\n };\n },\n};\n\nexport default rule;\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/utils/constants.ts","../src/utils/analyze.ts","../src/utils/source-code.ts","../src/rules/order.ts"],"sourcesContent":["import orderRule from './rules/order';\n\nconst plugin = {\n meta: {\n name: 'eslint-plugin-vue-setup-order',\n version: '1.0.0',\n },\n rules: {\n order: orderRule,\n },\n configs: {\n recommended: {\n plugins: ['vue-setup-order'],\n rules: {\n 'vue-setup-order/order': 'error',\n },\n },\n // Flat config format for ESLint 9+\n flat: {\n recommended: {\n plugins: {\n get 'vue-setup-order'() {\n return plugin;\n },\n },\n rules: {\n 'vue-setup-order/order': 'error',\n },\n },\n },\n },\n};\n\nexport default plugin;\n","import type { OrderConfig } from '../types';\n\nexport const CATEGORY_IMPORT = 0;\nexport const CATEGORY_TYPES = 1;\nexport const CATEGORY_DEFINE = 2;\nexport const CATEGORY_COMPOSABLE = 3;\nexport const CATEGORY_REACTIVE = 4;\nexport const CATEGORY_COMPUTED = 5;\nexport const CATEGORY_WATCH = 6;\nexport const CATEGORY_LIFECYCLE = 7;\nexport const CATEGORY_FUNCTION = 8;\nexport const CATEGORY_PROVIDE = 9;\nexport const CATEGORY_UNKNOWN = 99;\n\nexport const DEFAULT_ORDER: OrderConfig = {\n // Imports\n import: CATEGORY_IMPORT,\n\n // Types\n types: CATEGORY_TYPES,\n\n // Define macros\n defineOptions: CATEGORY_DEFINE,\n defineProps: CATEGORY_DEFINE,\n defineEmits: CATEGORY_DEFINE,\n defineSlots: CATEGORY_DEFINE,\n defineExpose: CATEGORY_DEFINE,\n defineModel: CATEGORY_DEFINE,\n withDefaults: CATEGORY_DEFINE,\n\n // Composables\n composable: CATEGORY_COMPOSABLE,\n\n // Reactive state\n ref: CATEGORY_REACTIVE,\n reactive: CATEGORY_REACTIVE,\n shallowRef: CATEGORY_REACTIVE,\n shallowReactive: CATEGORY_REACTIVE,\n toRef: CATEGORY_REACTIVE,\n toRefs: CATEGORY_REACTIVE,\n customRef: CATEGORY_REACTIVE,\n readonly: CATEGORY_REACTIVE,\n shallowReadonly: CATEGORY_REACTIVE,\n\n // Computed\n computed: CATEGORY_COMPUTED,\n\n // Watchers\n watch: CATEGORY_WATCH,\n watchEffect: CATEGORY_WATCH,\n watchPostEffect: CATEGORY_WATCH,\n watchSyncEffect: CATEGORY_WATCH,\n\n // Lifecycle hooks\n onBeforeMount: CATEGORY_LIFECYCLE,\n onMounted: CATEGORY_LIFECYCLE,\n onBeforeUpdate: CATEGORY_LIFECYCLE,\n onUpdated: CATEGORY_LIFECYCLE,\n onBeforeUnmount: CATEGORY_LIFECYCLE,\n onUnmounted: CATEGORY_LIFECYCLE,\n onActivated: CATEGORY_LIFECYCLE,\n onDeactivated: CATEGORY_LIFECYCLE,\n onErrorCaptured: CATEGORY_LIFECYCLE,\n onRenderTracked: CATEGORY_LIFECYCLE,\n onRenderTriggered: CATEGORY_LIFECYCLE,\n onServerPrefetch: CATEGORY_LIFECYCLE,\n\n // Functions\n function: CATEGORY_FUNCTION,\n\n // Provide\n provide: CATEGORY_PROVIDE,\n\n // Unknown\n unknown: CATEGORY_UNKNOWN,\n};\n\nexport const ORDER_NAMES: Record<number, string> = {\n [CATEGORY_IMPORT]: 'imports',\n [CATEGORY_TYPES]: 'type declarations',\n [CATEGORY_DEFINE]: 'define macros',\n [CATEGORY_COMPOSABLE]: 'composables',\n [CATEGORY_REACTIVE]: 'reactive state',\n [CATEGORY_COMPUTED]: 'computed properties',\n [CATEGORY_WATCH]: 'watchers',\n [CATEGORY_LIFECYCLE]: 'lifecycle hooks',\n [CATEGORY_FUNCTION]: 'functions',\n [CATEGORY_PROVIDE]: 'provide',\n [CATEGORY_UNKNOWN]: 'other',\n};\n\nexport const COMPOSABLE_PATTERN = /^use[A-Z]/;\n","import type { Rule } from 'eslint';\nimport type { Expression, ModuleDeclaration, Statement, Super } from 'estree';\nimport type { AnalyzedStatement, OrderConfig } from '../types';\nimport {\n CATEGORY_FUNCTION,\n CATEGORY_REACTIVE,\n CATEGORY_TYPES,\n CATEGORY_UNKNOWN,\n COMPOSABLE_PATTERN,\n} from './constants';\n\n/**\n * Retrieves the name of the callee from the provided node (Expression or Super).\n *\n * @param {Expression | Super | null | undefined} node - The node representing a callee, which can be an Expression or Super. May be null or undefined.\n * @param {Rule.RuleContext['sourceCode']} sourceCode - The source code object used to extract the callee name in case it's a MemberExpression.\n * @return {string | null} The name of the callee as a string if resolved, or null if the node is null, undefined, or not resolvable.\n */\nexport function getCalleeName(\n node: Expression | Super | null | undefined,\n sourceCode: Rule.RuleContext['sourceCode'],\n): string | null {\n if (!node) return null;\n\n if (node.type === 'Identifier') {\n return node.name;\n }\n\n if (node.type === 'MemberExpression') {\n return sourceCode.getText(node);\n }\n\n return null;\n}\n\n/**\n * Determines if the provided name is composable based on a predefined pattern.\n *\n * @param {string | null} name - The name to be tested against the composable pattern. Can be null.\n * @return {boolean} Returns true if the name matches the composable pattern and is not null; otherwise, returns false.\n */\nexport function isComposable(name: string | null): boolean {\n return name !== null && COMPOSABLE_PATTERN.test(name);\n}\n\n/**\n * Analyzes a given statement or module declaration to categorize, name, and assign an order based on the specified configuration.\n *\n * @param {Statement | ModuleDeclaration} statement - The statement or module declaration to be analyzed.\n * @param {Rule.RuleContext['sourceCode']} sourceCode - The source code context to extract details about the statement.\n * @param {OrderConfig} orderConfig - Configuration object that defines ordering and categorization rules.\n * @return {AnalyzedStatement | null} An object containing analysis details of the statement, or null for certain export declarations.\n */\nexport function analyzeStatement(\n statement: Statement | ModuleDeclaration,\n sourceCode: Rule.RuleContext['sourceCode'],\n orderConfig: OrderConfig,\n): AnalyzedStatement | null {\n const result: AnalyzedStatement = {\n node: statement as Statement,\n order: orderConfig.unknown ?? CATEGORY_UNKNOWN,\n name: 'unknown',\n category: 'unknown',\n };\n\n if (statement.type === 'ImportDeclaration') {\n result.order = orderConfig.import;\n result.name = 'import';\n result.category = 'import';\n return result;\n }\n\n const statementType = (statement as { type: string }).type;\n if (\n statementType === 'TSTypeAliasDeclaration' ||\n statementType === 'TSInterfaceDeclaration' ||\n statementType === 'TSEnumDeclaration'\n ) {\n result.order = orderConfig.types ?? CATEGORY_TYPES;\n result.name =\n statementType === 'TSTypeAliasDeclaration'\n ? 'type'\n : statementType === 'TSInterfaceDeclaration'\n ? 'interface'\n : 'enum';\n result.category = 'types';\n return result;\n }\n\n if (\n statement.type === 'ExportNamedDeclaration' ||\n statement.type === 'ExportDefaultDeclaration' ||\n statement.type === 'ExportAllDeclaration'\n ) {\n return null;\n }\n\n if (statement.type === 'VariableDeclaration') {\n const declaration = statement.declarations[0];\n const init = declaration?.init;\n\n if (!init) {\n result.order = orderConfig.ref ?? CATEGORY_REACTIVE;\n result.name = 'variable';\n result.category = 'reactive';\n return result;\n }\n\n if (init.type === 'CallExpression') {\n const calleeName = getCalleeName(init.callee, sourceCode);\n\n if (calleeName) {\n if (isComposable(calleeName)) {\n result.order = orderConfig.composable;\n result.name = calleeName;\n result.category = 'composable';\n return result;\n }\n\n if (orderConfig[calleeName] !== undefined) {\n result.order = orderConfig[calleeName];\n result.name = calleeName;\n result.category = calleeName;\n return result;\n }\n }\n\n result.order = orderConfig.ref ?? CATEGORY_REACTIVE;\n result.name = calleeName || 'variable';\n result.category = 'reactive';\n return result;\n }\n\n if (init.type === 'ArrowFunctionExpression' || init.type === 'FunctionExpression') {\n result.order = orderConfig.function ?? CATEGORY_FUNCTION;\n result.name = declaration.id?.type === 'Identifier' ? declaration.id.name : 'arrow function';\n result.category = 'function';\n return result;\n }\n\n result.order = orderConfig.ref ?? CATEGORY_REACTIVE;\n result.name = 'variable';\n result.category = 'reactive';\n return result;\n }\n\n if (statement.type === 'FunctionDeclaration') {\n result.order = orderConfig.function ?? CATEGORY_FUNCTION;\n result.name = statement.id?.name || 'function';\n result.category = 'function';\n return result;\n }\n\n if (statement.type === 'ExpressionStatement') {\n const expr = statement.expression;\n\n if (expr.type === 'CallExpression') {\n const calleeName = getCalleeName(expr.callee, sourceCode);\n\n if (calleeName && orderConfig[calleeName] !== undefined) {\n result.order = orderConfig[calleeName];\n result.name = calleeName;\n result.category = calleeName;\n return result;\n }\n\n result.order = orderConfig.unknown ?? CATEGORY_UNKNOWN;\n result.name = calleeName || 'call';\n result.category = 'unknown';\n return result;\n }\n\n result.order = orderConfig.unknown ?? CATEGORY_UNKNOWN;\n result.name = 'expression';\n result.category = 'unknown';\n return result;\n }\n\n return result;\n}\n","import type { Rule } from 'eslint';\nimport type { Statement } from 'estree';\n\n/**\n * Retrieves the combined text of a given AST node and its preceding comments from the source code.\n *\n * @param {Statement} node - The AST node whose text and preceding comments are to be retrieved.\n * @param {Rule.RuleContext['sourceCode']} sourceCode - The source code object containing the text and comments.\n * @return {string} The concatenated text of the node and its preceding comments.\n */\nexport function getNodeTextWithComments(node: Statement, sourceCode: Rule.RuleContext['sourceCode']): string {\n const comments = sourceCode.getCommentsBefore(node);\n let start = node.range![0];\n\n if (comments.length > 0) {\n start = comments[0].range![0];\n }\n\n return sourceCode.text.slice(start, node.range![1]);\n}\n\n/**\n * Determines the full range of a given statement node, including its preceding comments\n * and any trailing newlines immediately following the node.\n *\n * @param {Statement} node - The statement node for which to calculate the full range.\n * @param {Rule.RuleContext['sourceCode']} sourceCode - The source code object used to retrieve comments and text.\n * @return {[number, number]} The start and end positions of the full range in the source code.\n */\nexport function getFullRange(node: Statement, sourceCode: Rule.RuleContext['sourceCode']): [number, number] {\n const comments = sourceCode.getCommentsBefore(node);\n let start = node.range![0];\n\n if (comments.length > 0) {\n start = comments[0].range![0];\n }\n\n let end = node.range![1];\n const textAfter = sourceCode.text.slice(end, end + 2);\n\n if (textAfter.startsWith('\\r\\n')) {\n end += 2;\n } else if (textAfter.startsWith('\\n')) {\n end += 1;\n }\n\n return [start, end];\n}\n\n/**\n * Generates a sorted string representation of code statements, optionally adding blank lines between different categories.\n *\n * @param {Array<{ node: Statement, order: number }>} statements - An array of objects containing a statement node and its corresponding order.\n * @param {Rule.RuleContext['sourceCode']} sourceCode - The source code object used to extract the textual representation of the statement nodes.\n * @param {boolean} [addBlankLines=true] - A flag indicating whether to add blank lines between statements of differing orders.\n * @return {string} A sorted and formatted code string based on the given statements and options.\n */\nexport function generateSortedCode(\n statements: Array<{ node: Statement; order: number }>,\n sourceCode: Rule.RuleContext['sourceCode'],\n addBlankLines: boolean = true,\n): string {\n const parts: string[] = [];\n let lastOrder = -1;\n\n for (const statement of statements) {\n const text = getNodeTextWithComments(statement.node, sourceCode).trim();\n\n if (addBlankLines && lastOrder !== -1 && statement.order !== lastOrder) {\n parts.push('');\n }\n\n parts.push(text);\n lastOrder = statement.order;\n }\n\n return parts.join('\\n');\n}\n","import type { Rule } from 'eslint';\nimport type { Program } from 'estree';\nimport type { AST } from 'vue-eslint-parser';\nimport type { AnalyzedStatement, OrderConfig, PluginOptions } from '../types';\nimport { analyzeStatement } from '../utils/analyze';\nimport { DEFAULT_ORDER, ORDER_NAMES } from '../utils/constants';\nimport { generateSortedCode, getFullRange } from '../utils/source-code';\n\n/**\n * Represents an ESLint rule module designed to enforce a consistent order of statements\n * in the `<script setup>` block of Vue 3 components.\n *\n * The rule provides configuration options for defining custom ordering of statement categories\n * and for including blank lines between different categories. The rule reports and optionally\n * fixes statement order violations.\n */\nconst rule: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Enforce consistent order of statements in Vue 3 <script setup>',\n category: 'Stylistic Issues',\n recommended: true,\n url: 'https://github.com/d2a8k3u/eslint-plugin-vue-setup-order#readme',\n },\n fixable: 'code',\n schema: [\n {\n type: 'object',\n properties: {\n order: {\n type: 'array',\n items: { type: 'string' },\n description: 'Custom order of categories',\n },\n groupBlankLines: {\n type: 'boolean',\n default: true,\n description: 'Add blank lines between different categories',\n },\n },\n additionalProperties: false,\n },\n ],\n messages: {\n wrongOrder: \"'{{current}}' ({{currentCategory}}) should come before '{{previous}}' ({{previousCategory}})\",\n },\n },\n\n create(context: Rule.RuleContext) {\n const sourceCode = context.sourceCode ?? context.getSourceCode();\n const filename = context.getFilename();\n const isVue = filename.endsWith('.vue');\n const options: PluginOptions = context.options[0] || {};\n const groupBlankLines = false !== options.groupBlankLines;\n const orderConfig: OrderConfig = { ...DEFAULT_ORDER };\n\n if (options.order && Array.isArray(options.order)) {\n options.order.forEach((category, index) => {\n const originalOrder = DEFAULT_ORDER[category];\n if (originalOrder !== undefined) {\n Object.keys(DEFAULT_ORDER).forEach((key) => {\n if (DEFAULT_ORDER[key] === originalOrder) {\n orderConfig[key] = index;\n }\n });\n }\n orderConfig[category] = index;\n });\n }\n\n return {\n Program(node: Program) {\n const statements: AnalyzedStatement[] = [];\n let scriptSetupRange: [number, number] | undefined;\n\n if (isVue) {\n const parserServices = sourceCode.parserServices as\n | {\n getDocumentFragment?: () => AST.VDocumentFragment;\n }\n | undefined;\n\n if (parserServices?.getDocumentFragment) {\n const df = parserServices.getDocumentFragment();\n const scriptSetup = df.children.find(\n (n): n is AST.VElement =>\n n.type === 'VElement' &&\n n.name === 'script' &&\n n.startTag.attributes.some((attr) => !attr.directive && attr.key.name === 'setup'),\n );\n\n if (scriptSetup) {\n scriptSetupRange = scriptSetup.range as [number, number];\n } else {\n return;\n }\n }\n }\n\n for (const statement of node.body) {\n if (\n isVue &&\n scriptSetupRange &&\n (statement.range![0] < scriptSetupRange[0] || statement.range![1] > scriptSetupRange[1])\n ) {\n continue;\n }\n\n const analyzed = analyzeStatement(statement, sourceCode, orderConfig);\n if (analyzed) {\n statements.push(analyzed);\n }\n }\n\n if (statements.length < 2) return;\n\n let firstError: {\n index: number;\n current: AnalyzedStatement;\n previous: AnalyzedStatement;\n } | null = null;\n\n for (let i = 1; i < statements.length; i++) {\n const prev = statements[i - 1];\n const curr = statements[i];\n\n if (curr.order < prev.order) {\n firstError = { index: i, current: curr, previous: prev };\n break;\n }\n }\n\n if (!firstError) return;\n\n context.report({\n node: firstError.current.node,\n messageId: 'wrongOrder',\n data: {\n current: firstError.current.name,\n currentCategory: ORDER_NAMES[firstError.current.order] || 'unknown',\n previous: firstError.previous.name,\n previousCategory: ORDER_NAMES[firstError.previous.order] || 'unknown',\n },\n fix(fixer) {\n const sorted = [...statements].sort((a, b) => {\n if (a.order !== b.order) {\n return a.order - b.order;\n }\n\n return statements.indexOf(a) - statements.indexOf(b);\n });\n\n const newCode = generateSortedCode(sorted, sourceCode, groupBlankLines);\n const firstRange = getFullRange(statements[0].node, sourceCode);\n const lastRange = getFullRange(statements[statements.length - 1].node, sourceCode);\n\n return fixer.replaceTextRange([firstRange[0], lastRange[1]], newCode + '\\n');\n },\n });\n },\n };\n },\n};\n\nexport default rule;\n"],"mappings":"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","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -257,6 +257,8 @@ var rule = {
|
|
|
257
257
|
},
|
|
258
258
|
create(context) {
|
|
259
259
|
const sourceCode = context.sourceCode ?? context.getSourceCode();
|
|
260
|
+
const filename = context.getFilename();
|
|
261
|
+
const isVue = filename.endsWith(".vue");
|
|
260
262
|
const options = context.options[0] || {};
|
|
261
263
|
const groupBlankLines = false !== options.groupBlankLines;
|
|
262
264
|
const orderConfig = { ...DEFAULT_ORDER };
|
|
@@ -276,7 +278,25 @@ var rule = {
|
|
|
276
278
|
return {
|
|
277
279
|
Program(node) {
|
|
278
280
|
const statements = [];
|
|
281
|
+
let scriptSetupRange;
|
|
282
|
+
if (isVue) {
|
|
283
|
+
const parserServices = sourceCode.parserServices;
|
|
284
|
+
if (parserServices?.getDocumentFragment) {
|
|
285
|
+
const df = parserServices.getDocumentFragment();
|
|
286
|
+
const scriptSetup = df.children.find(
|
|
287
|
+
(n) => n.type === "VElement" && n.name === "script" && n.startTag.attributes.some((attr) => !attr.directive && attr.key.name === "setup")
|
|
288
|
+
);
|
|
289
|
+
if (scriptSetup) {
|
|
290
|
+
scriptSetupRange = scriptSetup.range;
|
|
291
|
+
} else {
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
279
296
|
for (const statement of node.body) {
|
|
297
|
+
if (isVue && scriptSetupRange && (statement.range[0] < scriptSetupRange[0] || statement.range[1] > scriptSetupRange[1])) {
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
280
300
|
const analyzed = analyzeStatement(statement, sourceCode, orderConfig);
|
|
281
301
|
if (analyzed) {
|
|
282
302
|
statements.push(analyzed);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/constants.ts","../src/utils/analyze.ts","../src/utils/source-code.ts","../src/rules/order.ts","../src/index.ts"],"sourcesContent":["import type { OrderConfig } from '../types';\n\nexport const CATEGORY_IMPORT = 0;\nexport const CATEGORY_TYPES = 1;\nexport const CATEGORY_DEFINE = 2;\nexport const CATEGORY_COMPOSABLE = 3;\nexport const CATEGORY_REACTIVE = 4;\nexport const CATEGORY_COMPUTED = 5;\nexport const CATEGORY_WATCH = 6;\nexport const CATEGORY_LIFECYCLE = 7;\nexport const CATEGORY_FUNCTION = 8;\nexport const CATEGORY_PROVIDE = 9;\nexport const CATEGORY_UNKNOWN = 99;\n\nexport const DEFAULT_ORDER: OrderConfig = {\n // Imports\n import: CATEGORY_IMPORT,\n\n // Types\n types: CATEGORY_TYPES,\n\n // Define macros\n defineOptions: CATEGORY_DEFINE,\n defineProps: CATEGORY_DEFINE,\n defineEmits: CATEGORY_DEFINE,\n defineSlots: CATEGORY_DEFINE,\n defineExpose: CATEGORY_DEFINE,\n defineModel: CATEGORY_DEFINE,\n withDefaults: CATEGORY_DEFINE,\n\n // Composables\n composable: CATEGORY_COMPOSABLE,\n\n // Reactive state\n ref: CATEGORY_REACTIVE,\n reactive: CATEGORY_REACTIVE,\n shallowRef: CATEGORY_REACTIVE,\n shallowReactive: CATEGORY_REACTIVE,\n toRef: CATEGORY_REACTIVE,\n toRefs: CATEGORY_REACTIVE,\n customRef: CATEGORY_REACTIVE,\n readonly: CATEGORY_REACTIVE,\n shallowReadonly: CATEGORY_REACTIVE,\n\n // Computed\n computed: CATEGORY_COMPUTED,\n\n // Watchers\n watch: CATEGORY_WATCH,\n watchEffect: CATEGORY_WATCH,\n watchPostEffect: CATEGORY_WATCH,\n watchSyncEffect: CATEGORY_WATCH,\n\n // Lifecycle hooks\n onBeforeMount: CATEGORY_LIFECYCLE,\n onMounted: CATEGORY_LIFECYCLE,\n onBeforeUpdate: CATEGORY_LIFECYCLE,\n onUpdated: CATEGORY_LIFECYCLE,\n onBeforeUnmount: CATEGORY_LIFECYCLE,\n onUnmounted: CATEGORY_LIFECYCLE,\n onActivated: CATEGORY_LIFECYCLE,\n onDeactivated: CATEGORY_LIFECYCLE,\n onErrorCaptured: CATEGORY_LIFECYCLE,\n onRenderTracked: CATEGORY_LIFECYCLE,\n onRenderTriggered: CATEGORY_LIFECYCLE,\n onServerPrefetch: CATEGORY_LIFECYCLE,\n\n // Functions\n function: CATEGORY_FUNCTION,\n\n // Provide\n provide: CATEGORY_PROVIDE,\n\n // Unknown\n unknown: CATEGORY_UNKNOWN,\n};\n\nexport const ORDER_NAMES: Record<number, string> = {\n [CATEGORY_IMPORT]: 'imports',\n [CATEGORY_TYPES]: 'type declarations',\n [CATEGORY_DEFINE]: 'define macros',\n [CATEGORY_COMPOSABLE]: 'composables',\n [CATEGORY_REACTIVE]: 'reactive state',\n [CATEGORY_COMPUTED]: 'computed properties',\n [CATEGORY_WATCH]: 'watchers',\n [CATEGORY_LIFECYCLE]: 'lifecycle hooks',\n [CATEGORY_FUNCTION]: 'functions',\n [CATEGORY_PROVIDE]: 'provide',\n [CATEGORY_UNKNOWN]: 'other',\n};\n\nexport const COMPOSABLE_PATTERN = /^use[A-Z]/;\n","import type { Rule } from 'eslint';\nimport type { Expression, ModuleDeclaration, Statement, Super } from 'estree';\nimport type { AnalyzedStatement, OrderConfig } from '../types';\nimport {\n CATEGORY_FUNCTION,\n CATEGORY_REACTIVE,\n CATEGORY_TYPES,\n CATEGORY_UNKNOWN,\n COMPOSABLE_PATTERN,\n} from './constants';\n\n/**\n * Retrieves the name of the callee from the provided node (Expression or Super).\n *\n * @param {Expression | Super | null | undefined} node - The node representing a callee, which can be an Expression or Super. May be null or undefined.\n * @param {Rule.RuleContext['sourceCode']} sourceCode - The source code object used to extract the callee name in case it's a MemberExpression.\n * @return {string | null} The name of the callee as a string if resolved, or null if the node is null, undefined, or not resolvable.\n */\nexport function getCalleeName(\n node: Expression | Super | null | undefined,\n sourceCode: Rule.RuleContext['sourceCode'],\n): string | null {\n if (!node) return null;\n\n if (node.type === 'Identifier') {\n return node.name;\n }\n\n if (node.type === 'MemberExpression') {\n return sourceCode.getText(node);\n }\n\n return null;\n}\n\n/**\n * Determines if the provided name is composable based on a predefined pattern.\n *\n * @param {string | null} name - The name to be tested against the composable pattern. Can be null.\n * @return {boolean} Returns true if the name matches the composable pattern and is not null; otherwise, returns false.\n */\nexport function isComposable(name: string | null): boolean {\n return name !== null && COMPOSABLE_PATTERN.test(name);\n}\n\n/**\n * Analyzes a given statement or module declaration to categorize, name, and assign an order based on the specified configuration.\n *\n * @param {Statement | ModuleDeclaration} statement - The statement or module declaration to be analyzed.\n * @param {Rule.RuleContext['sourceCode']} sourceCode - The source code context to extract details about the statement.\n * @param {OrderConfig} orderConfig - Configuration object that defines ordering and categorization rules.\n * @return {AnalyzedStatement | null} An object containing analysis details of the statement, or null for certain export declarations.\n */\nexport function analyzeStatement(\n statement: Statement | ModuleDeclaration,\n sourceCode: Rule.RuleContext['sourceCode'],\n orderConfig: OrderConfig,\n): AnalyzedStatement | null {\n const result: AnalyzedStatement = {\n node: statement as Statement,\n order: orderConfig.unknown ?? CATEGORY_UNKNOWN,\n name: 'unknown',\n category: 'unknown',\n };\n\n if (statement.type === 'ImportDeclaration') {\n result.order = orderConfig.import;\n result.name = 'import';\n result.category = 'import';\n return result;\n }\n\n const statementType = (statement as { type: string }).type;\n if (\n statementType === 'TSTypeAliasDeclaration' ||\n statementType === 'TSInterfaceDeclaration' ||\n statementType === 'TSEnumDeclaration'\n ) {\n result.order = orderConfig.types ?? CATEGORY_TYPES;\n result.name =\n statementType === 'TSTypeAliasDeclaration'\n ? 'type'\n : statementType === 'TSInterfaceDeclaration'\n ? 'interface'\n : 'enum';\n result.category = 'types';\n return result;\n }\n\n if (\n statement.type === 'ExportNamedDeclaration' ||\n statement.type === 'ExportDefaultDeclaration' ||\n statement.type === 'ExportAllDeclaration'\n ) {\n return null;\n }\n\n if (statement.type === 'VariableDeclaration') {\n const declaration = statement.declarations[0];\n const init = declaration?.init;\n\n if (!init) {\n result.order = orderConfig.ref ?? CATEGORY_REACTIVE;\n result.name = 'variable';\n result.category = 'reactive';\n return result;\n }\n\n if (init.type === 'CallExpression') {\n const calleeName = getCalleeName(init.callee, sourceCode);\n\n if (calleeName) {\n if (isComposable(calleeName)) {\n result.order = orderConfig.composable;\n result.name = calleeName;\n result.category = 'composable';\n return result;\n }\n\n if (orderConfig[calleeName] !== undefined) {\n result.order = orderConfig[calleeName];\n result.name = calleeName;\n result.category = calleeName;\n return result;\n }\n }\n\n result.order = orderConfig.ref ?? CATEGORY_REACTIVE;\n result.name = calleeName || 'variable';\n result.category = 'reactive';\n return result;\n }\n\n if (init.type === 'ArrowFunctionExpression' || init.type === 'FunctionExpression') {\n result.order = orderConfig.function ?? CATEGORY_FUNCTION;\n result.name = declaration.id?.type === 'Identifier' ? declaration.id.name : 'arrow function';\n result.category = 'function';\n return result;\n }\n\n result.order = orderConfig.ref ?? CATEGORY_REACTIVE;\n result.name = 'variable';\n result.category = 'reactive';\n return result;\n }\n\n if (statement.type === 'FunctionDeclaration') {\n result.order = orderConfig.function ?? CATEGORY_FUNCTION;\n result.name = statement.id?.name || 'function';\n result.category = 'function';\n return result;\n }\n\n if (statement.type === 'ExpressionStatement') {\n const expr = statement.expression;\n\n if (expr.type === 'CallExpression') {\n const calleeName = getCalleeName(expr.callee, sourceCode);\n\n if (calleeName && orderConfig[calleeName] !== undefined) {\n result.order = orderConfig[calleeName];\n result.name = calleeName;\n result.category = calleeName;\n return result;\n }\n\n result.order = orderConfig.unknown ?? CATEGORY_UNKNOWN;\n result.name = calleeName || 'call';\n result.category = 'unknown';\n return result;\n }\n\n result.order = orderConfig.unknown ?? CATEGORY_UNKNOWN;\n result.name = 'expression';\n result.category = 'unknown';\n return result;\n }\n\n return result;\n}\n","import type { Rule } from 'eslint';\nimport type { Statement } from 'estree';\n\n/**\n * Retrieves the combined text of a given AST node and its preceding comments from the source code.\n *\n * @param {Statement} node - The AST node whose text and preceding comments are to be retrieved.\n * @param {Rule.RuleContext['sourceCode']} sourceCode - The source code object containing the text and comments.\n * @return {string} The concatenated text of the node and its preceding comments.\n */\nexport function getNodeTextWithComments(node: Statement, sourceCode: Rule.RuleContext['sourceCode']): string {\n const comments = sourceCode.getCommentsBefore(node);\n let start = node.range![0];\n\n if (comments.length > 0) {\n start = comments[0].range![0];\n }\n\n return sourceCode.text.slice(start, node.range![1]);\n}\n\n/**\n * Determines the full range of a given statement node, including its preceding comments\n * and any trailing newlines immediately following the node.\n *\n * @param {Statement} node - The statement node for which to calculate the full range.\n * @param {Rule.RuleContext['sourceCode']} sourceCode - The source code object used to retrieve comments and text.\n * @return {[number, number]} The start and end positions of the full range in the source code.\n */\nexport function getFullRange(node: Statement, sourceCode: Rule.RuleContext['sourceCode']): [number, number] {\n const comments = sourceCode.getCommentsBefore(node);\n let start = node.range![0];\n\n if (comments.length > 0) {\n start = comments[0].range![0];\n }\n\n let end = node.range![1];\n const textAfter = sourceCode.text.slice(end, end + 2);\n\n if (textAfter.startsWith('\\r\\n')) {\n end += 2;\n } else if (textAfter.startsWith('\\n')) {\n end += 1;\n }\n\n return [start, end];\n}\n\n/**\n * Generates a sorted string representation of code statements, optionally adding blank lines between different categories.\n *\n * @param {Array<{ node: Statement, order: number }>} statements - An array of objects containing a statement node and its corresponding order.\n * @param {Rule.RuleContext['sourceCode']} sourceCode - The source code object used to extract the textual representation of the statement nodes.\n * @param {boolean} [addBlankLines=true] - A flag indicating whether to add blank lines between statements of differing orders.\n * @return {string} A sorted and formatted code string based on the given statements and options.\n */\nexport function generateSortedCode(\n statements: Array<{ node: Statement; order: number }>,\n sourceCode: Rule.RuleContext['sourceCode'],\n addBlankLines: boolean = true,\n): string {\n const parts: string[] = [];\n let lastOrder = -1;\n\n for (const statement of statements) {\n const text = getNodeTextWithComments(statement.node, sourceCode).trim();\n\n if (addBlankLines && lastOrder !== -1 && statement.order !== lastOrder) {\n parts.push('');\n }\n\n parts.push(text);\n lastOrder = statement.order;\n }\n\n return parts.join('\\n');\n}\n","import type { Rule } from 'eslint';\nimport type { Program } from 'estree';\nimport type { AnalyzedStatement, OrderConfig, PluginOptions } from '../types';\nimport { analyzeStatement } from '../utils/analyze';\nimport { DEFAULT_ORDER, ORDER_NAMES } from '../utils/constants';\nimport { generateSortedCode, getFullRange } from '../utils/source-code';\n\n/**\n * Represents an ESLint rule module designed to enforce a consistent order of statements\n * in the `<script setup>` block of Vue 3 components.\n *\n * The rule provides configuration options for defining custom ordering of statement categories\n * and for including blank lines between different categories. The rule reports and optionally\n * fixes statement order violations.\n */\nconst rule: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Enforce consistent order of statements in Vue 3 <script setup>',\n category: 'Stylistic Issues',\n recommended: true,\n url: 'https://github.com/d2a8k3u/eslint-plugin-vue-setup-order#readme',\n },\n fixable: 'code',\n schema: [\n {\n type: 'object',\n properties: {\n order: {\n type: 'array',\n items: { type: 'string' },\n description: 'Custom order of categories',\n },\n groupBlankLines: {\n type: 'boolean',\n default: true,\n description: 'Add blank lines between different categories',\n },\n },\n additionalProperties: false,\n },\n ],\n messages: {\n wrongOrder: \"'{{current}}' ({{currentCategory}}) should come before '{{previous}}' ({{previousCategory}})\",\n },\n },\n\n create(context: Rule.RuleContext) {\n const sourceCode = context.sourceCode ?? context.getSourceCode();\n const options: PluginOptions = context.options[0] || {};\n const groupBlankLines = false !== options.groupBlankLines;\n const orderConfig: OrderConfig = { ...DEFAULT_ORDER };\n\n if (options.order && Array.isArray(options.order)) {\n options.order.forEach((category, index) => {\n const originalOrder = DEFAULT_ORDER[category];\n if (originalOrder !== undefined) {\n Object.keys(DEFAULT_ORDER).forEach((key) => {\n if (DEFAULT_ORDER[key] === originalOrder) {\n orderConfig[key] = index;\n }\n });\n }\n orderConfig[category] = index;\n });\n }\n\n return {\n Program(node: Program) {\n const statements: AnalyzedStatement[] = [];\n\n for (const statement of node.body) {\n const analyzed = analyzeStatement(statement, sourceCode, orderConfig);\n if (analyzed) {\n statements.push(analyzed);\n }\n }\n\n if (statements.length < 2) return;\n\n let firstError: {\n index: number;\n current: AnalyzedStatement;\n previous: AnalyzedStatement;\n } | null = null;\n\n for (let i = 1; i < statements.length; i++) {\n const prev = statements[i - 1];\n const curr = statements[i];\n\n if (curr.order < prev.order) {\n firstError = { index: i, current: curr, previous: prev };\n break;\n }\n }\n\n if (!firstError) return;\n\n context.report({\n node: firstError.current.node,\n messageId: 'wrongOrder',\n data: {\n current: firstError.current.name,\n currentCategory: ORDER_NAMES[firstError.current.order] || 'unknown',\n previous: firstError.previous.name,\n previousCategory: ORDER_NAMES[firstError.previous.order] || 'unknown',\n },\n fix(fixer) {\n const sorted = [...statements].sort((a, b) => {\n if (a.order !== b.order) {\n return a.order - b.order;\n }\n\n return statements.indexOf(a) - statements.indexOf(b);\n });\n\n const newCode = generateSortedCode(sorted, sourceCode, groupBlankLines);\n const firstRange = getFullRange(statements[0].node, sourceCode);\n const lastRange = getFullRange(statements[statements.length - 1].node, sourceCode);\n\n return fixer.replaceTextRange([firstRange[0], lastRange[1]], newCode + '\\n');\n },\n });\n },\n };\n },\n};\n\nexport default rule;\n","import orderRule from './rules/order';\n\nconst plugin = {\n meta: {\n name: 'eslint-plugin-vue-setup-order',\n version: '1.0.0',\n },\n rules: {\n order: orderRule,\n },\n configs: {\n recommended: {\n plugins: ['vue-setup-order'],\n rules: {\n 'vue-setup-order/order': 'error',\n },\n },\n // Flat config format for ESLint 9+\n flat: {\n recommended: {\n plugins: {\n get 'vue-setup-order'() {\n return plugin;\n },\n },\n rules: {\n 'vue-setup-order/order': 'error',\n },\n },\n },\n },\n};\n\nexport default plugin;\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/constants.ts","../src/utils/analyze.ts","../src/utils/source-code.ts","../src/rules/order.ts","../src/index.ts"],"sourcesContent":["import type { OrderConfig } from '../types';\n\nexport const CATEGORY_IMPORT = 0;\nexport const CATEGORY_TYPES = 1;\nexport const CATEGORY_DEFINE = 2;\nexport const CATEGORY_COMPOSABLE = 3;\nexport const CATEGORY_REACTIVE = 4;\nexport const CATEGORY_COMPUTED = 5;\nexport const CATEGORY_WATCH = 6;\nexport const CATEGORY_LIFECYCLE = 7;\nexport const CATEGORY_FUNCTION = 8;\nexport const CATEGORY_PROVIDE = 9;\nexport const CATEGORY_UNKNOWN = 99;\n\nexport const DEFAULT_ORDER: OrderConfig = {\n // Imports\n import: CATEGORY_IMPORT,\n\n // Types\n types: CATEGORY_TYPES,\n\n // Define macros\n defineOptions: CATEGORY_DEFINE,\n defineProps: CATEGORY_DEFINE,\n defineEmits: CATEGORY_DEFINE,\n defineSlots: CATEGORY_DEFINE,\n defineExpose: CATEGORY_DEFINE,\n defineModel: CATEGORY_DEFINE,\n withDefaults: CATEGORY_DEFINE,\n\n // Composables\n composable: CATEGORY_COMPOSABLE,\n\n // Reactive state\n ref: CATEGORY_REACTIVE,\n reactive: CATEGORY_REACTIVE,\n shallowRef: CATEGORY_REACTIVE,\n shallowReactive: CATEGORY_REACTIVE,\n toRef: CATEGORY_REACTIVE,\n toRefs: CATEGORY_REACTIVE,\n customRef: CATEGORY_REACTIVE,\n readonly: CATEGORY_REACTIVE,\n shallowReadonly: CATEGORY_REACTIVE,\n\n // Computed\n computed: CATEGORY_COMPUTED,\n\n // Watchers\n watch: CATEGORY_WATCH,\n watchEffect: CATEGORY_WATCH,\n watchPostEffect: CATEGORY_WATCH,\n watchSyncEffect: CATEGORY_WATCH,\n\n // Lifecycle hooks\n onBeforeMount: CATEGORY_LIFECYCLE,\n onMounted: CATEGORY_LIFECYCLE,\n onBeforeUpdate: CATEGORY_LIFECYCLE,\n onUpdated: CATEGORY_LIFECYCLE,\n onBeforeUnmount: CATEGORY_LIFECYCLE,\n onUnmounted: CATEGORY_LIFECYCLE,\n onActivated: CATEGORY_LIFECYCLE,\n onDeactivated: CATEGORY_LIFECYCLE,\n onErrorCaptured: CATEGORY_LIFECYCLE,\n onRenderTracked: CATEGORY_LIFECYCLE,\n onRenderTriggered: CATEGORY_LIFECYCLE,\n onServerPrefetch: CATEGORY_LIFECYCLE,\n\n // Functions\n function: CATEGORY_FUNCTION,\n\n // Provide\n provide: CATEGORY_PROVIDE,\n\n // Unknown\n unknown: CATEGORY_UNKNOWN,\n};\n\nexport const ORDER_NAMES: Record<number, string> = {\n [CATEGORY_IMPORT]: 'imports',\n [CATEGORY_TYPES]: 'type declarations',\n [CATEGORY_DEFINE]: 'define macros',\n [CATEGORY_COMPOSABLE]: 'composables',\n [CATEGORY_REACTIVE]: 'reactive state',\n [CATEGORY_COMPUTED]: 'computed properties',\n [CATEGORY_WATCH]: 'watchers',\n [CATEGORY_LIFECYCLE]: 'lifecycle hooks',\n [CATEGORY_FUNCTION]: 'functions',\n [CATEGORY_PROVIDE]: 'provide',\n [CATEGORY_UNKNOWN]: 'other',\n};\n\nexport const COMPOSABLE_PATTERN = /^use[A-Z]/;\n","import type { Rule } from 'eslint';\nimport type { Expression, ModuleDeclaration, Statement, Super } from 'estree';\nimport type { AnalyzedStatement, OrderConfig } from '../types';\nimport {\n CATEGORY_FUNCTION,\n CATEGORY_REACTIVE,\n CATEGORY_TYPES,\n CATEGORY_UNKNOWN,\n COMPOSABLE_PATTERN,\n} from './constants';\n\n/**\n * Retrieves the name of the callee from the provided node (Expression or Super).\n *\n * @param {Expression | Super | null | undefined} node - The node representing a callee, which can be an Expression or Super. May be null or undefined.\n * @param {Rule.RuleContext['sourceCode']} sourceCode - The source code object used to extract the callee name in case it's a MemberExpression.\n * @return {string | null} The name of the callee as a string if resolved, or null if the node is null, undefined, or not resolvable.\n */\nexport function getCalleeName(\n node: Expression | Super | null | undefined,\n sourceCode: Rule.RuleContext['sourceCode'],\n): string | null {\n if (!node) return null;\n\n if (node.type === 'Identifier') {\n return node.name;\n }\n\n if (node.type === 'MemberExpression') {\n return sourceCode.getText(node);\n }\n\n return null;\n}\n\n/**\n * Determines if the provided name is composable based on a predefined pattern.\n *\n * @param {string | null} name - The name to be tested against the composable pattern. Can be null.\n * @return {boolean} Returns true if the name matches the composable pattern and is not null; otherwise, returns false.\n */\nexport function isComposable(name: string | null): boolean {\n return name !== null && COMPOSABLE_PATTERN.test(name);\n}\n\n/**\n * Analyzes a given statement or module declaration to categorize, name, and assign an order based on the specified configuration.\n *\n * @param {Statement | ModuleDeclaration} statement - The statement or module declaration to be analyzed.\n * @param {Rule.RuleContext['sourceCode']} sourceCode - The source code context to extract details about the statement.\n * @param {OrderConfig} orderConfig - Configuration object that defines ordering and categorization rules.\n * @return {AnalyzedStatement | null} An object containing analysis details of the statement, or null for certain export declarations.\n */\nexport function analyzeStatement(\n statement: Statement | ModuleDeclaration,\n sourceCode: Rule.RuleContext['sourceCode'],\n orderConfig: OrderConfig,\n): AnalyzedStatement | null {\n const result: AnalyzedStatement = {\n node: statement as Statement,\n order: orderConfig.unknown ?? CATEGORY_UNKNOWN,\n name: 'unknown',\n category: 'unknown',\n };\n\n if (statement.type === 'ImportDeclaration') {\n result.order = orderConfig.import;\n result.name = 'import';\n result.category = 'import';\n return result;\n }\n\n const statementType = (statement as { type: string }).type;\n if (\n statementType === 'TSTypeAliasDeclaration' ||\n statementType === 'TSInterfaceDeclaration' ||\n statementType === 'TSEnumDeclaration'\n ) {\n result.order = orderConfig.types ?? CATEGORY_TYPES;\n result.name =\n statementType === 'TSTypeAliasDeclaration'\n ? 'type'\n : statementType === 'TSInterfaceDeclaration'\n ? 'interface'\n : 'enum';\n result.category = 'types';\n return result;\n }\n\n if (\n statement.type === 'ExportNamedDeclaration' ||\n statement.type === 'ExportDefaultDeclaration' ||\n statement.type === 'ExportAllDeclaration'\n ) {\n return null;\n }\n\n if (statement.type === 'VariableDeclaration') {\n const declaration = statement.declarations[0];\n const init = declaration?.init;\n\n if (!init) {\n result.order = orderConfig.ref ?? CATEGORY_REACTIVE;\n result.name = 'variable';\n result.category = 'reactive';\n return result;\n }\n\n if (init.type === 'CallExpression') {\n const calleeName = getCalleeName(init.callee, sourceCode);\n\n if (calleeName) {\n if (isComposable(calleeName)) {\n result.order = orderConfig.composable;\n result.name = calleeName;\n result.category = 'composable';\n return result;\n }\n\n if (orderConfig[calleeName] !== undefined) {\n result.order = orderConfig[calleeName];\n result.name = calleeName;\n result.category = calleeName;\n return result;\n }\n }\n\n result.order = orderConfig.ref ?? CATEGORY_REACTIVE;\n result.name = calleeName || 'variable';\n result.category = 'reactive';\n return result;\n }\n\n if (init.type === 'ArrowFunctionExpression' || init.type === 'FunctionExpression') {\n result.order = orderConfig.function ?? CATEGORY_FUNCTION;\n result.name = declaration.id?.type === 'Identifier' ? declaration.id.name : 'arrow function';\n result.category = 'function';\n return result;\n }\n\n result.order = orderConfig.ref ?? CATEGORY_REACTIVE;\n result.name = 'variable';\n result.category = 'reactive';\n return result;\n }\n\n if (statement.type === 'FunctionDeclaration') {\n result.order = orderConfig.function ?? CATEGORY_FUNCTION;\n result.name = statement.id?.name || 'function';\n result.category = 'function';\n return result;\n }\n\n if (statement.type === 'ExpressionStatement') {\n const expr = statement.expression;\n\n if (expr.type === 'CallExpression') {\n const calleeName = getCalleeName(expr.callee, sourceCode);\n\n if (calleeName && orderConfig[calleeName] !== undefined) {\n result.order = orderConfig[calleeName];\n result.name = calleeName;\n result.category = calleeName;\n return result;\n }\n\n result.order = orderConfig.unknown ?? CATEGORY_UNKNOWN;\n result.name = calleeName || 'call';\n result.category = 'unknown';\n return result;\n }\n\n result.order = orderConfig.unknown ?? CATEGORY_UNKNOWN;\n result.name = 'expression';\n result.category = 'unknown';\n return result;\n }\n\n return result;\n}\n","import type { Rule } from 'eslint';\nimport type { Statement } from 'estree';\n\n/**\n * Retrieves the combined text of a given AST node and its preceding comments from the source code.\n *\n * @param {Statement} node - The AST node whose text and preceding comments are to be retrieved.\n * @param {Rule.RuleContext['sourceCode']} sourceCode - The source code object containing the text and comments.\n * @return {string} The concatenated text of the node and its preceding comments.\n */\nexport function getNodeTextWithComments(node: Statement, sourceCode: Rule.RuleContext['sourceCode']): string {\n const comments = sourceCode.getCommentsBefore(node);\n let start = node.range![0];\n\n if (comments.length > 0) {\n start = comments[0].range![0];\n }\n\n return sourceCode.text.slice(start, node.range![1]);\n}\n\n/**\n * Determines the full range of a given statement node, including its preceding comments\n * and any trailing newlines immediately following the node.\n *\n * @param {Statement} node - The statement node for which to calculate the full range.\n * @param {Rule.RuleContext['sourceCode']} sourceCode - The source code object used to retrieve comments and text.\n * @return {[number, number]} The start and end positions of the full range in the source code.\n */\nexport function getFullRange(node: Statement, sourceCode: Rule.RuleContext['sourceCode']): [number, number] {\n const comments = sourceCode.getCommentsBefore(node);\n let start = node.range![0];\n\n if (comments.length > 0) {\n start = comments[0].range![0];\n }\n\n let end = node.range![1];\n const textAfter = sourceCode.text.slice(end, end + 2);\n\n if (textAfter.startsWith('\\r\\n')) {\n end += 2;\n } else if (textAfter.startsWith('\\n')) {\n end += 1;\n }\n\n return [start, end];\n}\n\n/**\n * Generates a sorted string representation of code statements, optionally adding blank lines between different categories.\n *\n * @param {Array<{ node: Statement, order: number }>} statements - An array of objects containing a statement node and its corresponding order.\n * @param {Rule.RuleContext['sourceCode']} sourceCode - The source code object used to extract the textual representation of the statement nodes.\n * @param {boolean} [addBlankLines=true] - A flag indicating whether to add blank lines between statements of differing orders.\n * @return {string} A sorted and formatted code string based on the given statements and options.\n */\nexport function generateSortedCode(\n statements: Array<{ node: Statement; order: number }>,\n sourceCode: Rule.RuleContext['sourceCode'],\n addBlankLines: boolean = true,\n): string {\n const parts: string[] = [];\n let lastOrder = -1;\n\n for (const statement of statements) {\n const text = getNodeTextWithComments(statement.node, sourceCode).trim();\n\n if (addBlankLines && lastOrder !== -1 && statement.order !== lastOrder) {\n parts.push('');\n }\n\n parts.push(text);\n lastOrder = statement.order;\n }\n\n return parts.join('\\n');\n}\n","import type { Rule } from 'eslint';\nimport type { Program } from 'estree';\nimport type { AST } from 'vue-eslint-parser';\nimport type { AnalyzedStatement, OrderConfig, PluginOptions } from '../types';\nimport { analyzeStatement } from '../utils/analyze';\nimport { DEFAULT_ORDER, ORDER_NAMES } from '../utils/constants';\nimport { generateSortedCode, getFullRange } from '../utils/source-code';\n\n/**\n * Represents an ESLint rule module designed to enforce a consistent order of statements\n * in the `<script setup>` block of Vue 3 components.\n *\n * The rule provides configuration options for defining custom ordering of statement categories\n * and for including blank lines between different categories. The rule reports and optionally\n * fixes statement order violations.\n */\nconst rule: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Enforce consistent order of statements in Vue 3 <script setup>',\n category: 'Stylistic Issues',\n recommended: true,\n url: 'https://github.com/d2a8k3u/eslint-plugin-vue-setup-order#readme',\n },\n fixable: 'code',\n schema: [\n {\n type: 'object',\n properties: {\n order: {\n type: 'array',\n items: { type: 'string' },\n description: 'Custom order of categories',\n },\n groupBlankLines: {\n type: 'boolean',\n default: true,\n description: 'Add blank lines between different categories',\n },\n },\n additionalProperties: false,\n },\n ],\n messages: {\n wrongOrder: \"'{{current}}' ({{currentCategory}}) should come before '{{previous}}' ({{previousCategory}})\",\n },\n },\n\n create(context: Rule.RuleContext) {\n const sourceCode = context.sourceCode ?? context.getSourceCode();\n const filename = context.getFilename();\n const isVue = filename.endsWith('.vue');\n const options: PluginOptions = context.options[0] || {};\n const groupBlankLines = false !== options.groupBlankLines;\n const orderConfig: OrderConfig = { ...DEFAULT_ORDER };\n\n if (options.order && Array.isArray(options.order)) {\n options.order.forEach((category, index) => {\n const originalOrder = DEFAULT_ORDER[category];\n if (originalOrder !== undefined) {\n Object.keys(DEFAULT_ORDER).forEach((key) => {\n if (DEFAULT_ORDER[key] === originalOrder) {\n orderConfig[key] = index;\n }\n });\n }\n orderConfig[category] = index;\n });\n }\n\n return {\n Program(node: Program) {\n const statements: AnalyzedStatement[] = [];\n let scriptSetupRange: [number, number] | undefined;\n\n if (isVue) {\n const parserServices = sourceCode.parserServices as\n | {\n getDocumentFragment?: () => AST.VDocumentFragment;\n }\n | undefined;\n\n if (parserServices?.getDocumentFragment) {\n const df = parserServices.getDocumentFragment();\n const scriptSetup = df.children.find(\n (n): n is AST.VElement =>\n n.type === 'VElement' &&\n n.name === 'script' &&\n n.startTag.attributes.some((attr) => !attr.directive && attr.key.name === 'setup'),\n );\n\n if (scriptSetup) {\n scriptSetupRange = scriptSetup.range as [number, number];\n } else {\n return;\n }\n }\n }\n\n for (const statement of node.body) {\n if (\n isVue &&\n scriptSetupRange &&\n (statement.range![0] < scriptSetupRange[0] || statement.range![1] > scriptSetupRange[1])\n ) {\n continue;\n }\n\n const analyzed = analyzeStatement(statement, sourceCode, orderConfig);\n if (analyzed) {\n statements.push(analyzed);\n }\n }\n\n if (statements.length < 2) return;\n\n let firstError: {\n index: number;\n current: AnalyzedStatement;\n previous: AnalyzedStatement;\n } | null = null;\n\n for (let i = 1; i < statements.length; i++) {\n const prev = statements[i - 1];\n const curr = statements[i];\n\n if (curr.order < prev.order) {\n firstError = { index: i, current: curr, previous: prev };\n break;\n }\n }\n\n if (!firstError) return;\n\n context.report({\n node: firstError.current.node,\n messageId: 'wrongOrder',\n data: {\n current: firstError.current.name,\n currentCategory: ORDER_NAMES[firstError.current.order] || 'unknown',\n previous: firstError.previous.name,\n previousCategory: ORDER_NAMES[firstError.previous.order] || 'unknown',\n },\n fix(fixer) {\n const sorted = [...statements].sort((a, b) => {\n if (a.order !== b.order) {\n return a.order - b.order;\n }\n\n return statements.indexOf(a) - statements.indexOf(b);\n });\n\n const newCode = generateSortedCode(sorted, sourceCode, groupBlankLines);\n const firstRange = getFullRange(statements[0].node, sourceCode);\n const lastRange = getFullRange(statements[statements.length - 1].node, sourceCode);\n\n return fixer.replaceTextRange([firstRange[0], lastRange[1]], newCode + '\\n');\n },\n });\n },\n };\n },\n};\n\nexport default rule;\n","import orderRule from './rules/order';\n\nconst plugin = {\n meta: {\n name: 'eslint-plugin-vue-setup-order',\n version: '1.0.0',\n },\n rules: {\n order: orderRule,\n },\n configs: {\n recommended: {\n plugins: ['vue-setup-order'],\n rules: {\n 'vue-setup-order/order': 'error',\n },\n },\n // Flat config format for ESLint 9+\n flat: {\n recommended: {\n plugins: {\n get 'vue-setup-order'() {\n return plugin;\n },\n },\n rules: {\n 'vue-setup-order/order': 'error',\n },\n },\n },\n },\n};\n\nexport default plugin;\n"],"mappings":";AAEO,IAAM,kBAAkB;AACxB,IAAM,iBAAiB;AACvB,IAAM,kBAAkB;AACxB,IAAM,sBAAsB;AAC5B,IAAM,oBAAoB;AAC1B,IAAM,oBAAoB;AAC1B,IAAM,iBAAiB;AACvB,IAAM,qBAAqB;AAC3B,IAAM,oBAAoB;AAC1B,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AAEzB,IAAM,gBAA6B;AAAA;AAAA,EAExC,QAAQ;AAAA;AAAA,EAGR,OAAO;AAAA;AAAA,EAGP,eAAe;AAAA,EACf,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,cAAc;AAAA,EACd,aAAa;AAAA,EACb,cAAc;AAAA;AAAA,EAGd,YAAY;AAAA;AAAA,EAGZ,KAAK;AAAA,EACL,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,iBAAiB;AAAA,EACjB,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,UAAU;AAAA,EACV,iBAAiB;AAAA;AAAA,EAGjB,UAAU;AAAA;AAAA,EAGV,OAAO;AAAA,EACP,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,iBAAiB;AAAA;AAAA,EAGjB,eAAe;AAAA,EACf,WAAW;AAAA,EACX,gBAAgB;AAAA,EAChB,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,aAAa;AAAA,EACb,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,kBAAkB;AAAA;AAAA,EAGlB,UAAU;AAAA;AAAA,EAGV,SAAS;AAAA;AAAA,EAGT,SAAS;AACX;AAEO,IAAM,cAAsC;AAAA,EACjD,CAAC,eAAe,GAAG;AAAA,EACnB,CAAC,cAAc,GAAG;AAAA,EAClB,CAAC,eAAe,GAAG;AAAA,EACnB,CAAC,mBAAmB,GAAG;AAAA,EACvB,CAAC,iBAAiB,GAAG;AAAA,EACrB,CAAC,iBAAiB,GAAG;AAAA,EACrB,CAAC,cAAc,GAAG;AAAA,EAClB,CAAC,kBAAkB,GAAG;AAAA,EACtB,CAAC,iBAAiB,GAAG;AAAA,EACrB,CAAC,gBAAgB,GAAG;AAAA,EACpB,CAAC,gBAAgB,GAAG;AACtB;AAEO,IAAM,qBAAqB;;;ACzE3B,SAAS,cACd,MACA,YACe;AACf,MAAI,CAAC,KAAM,QAAO;AAElB,MAAI,KAAK,SAAS,cAAc;AAC9B,WAAO,KAAK;AAAA,EACd;AAEA,MAAI,KAAK,SAAS,oBAAoB;AACpC,WAAO,WAAW,QAAQ,IAAI;AAAA,EAChC;AAEA,SAAO;AACT;AAQO,SAAS,aAAa,MAA8B;AACzD,SAAO,SAAS,QAAQ,mBAAmB,KAAK,IAAI;AACtD;AAUO,SAAS,iBACd,WACA,YACA,aAC0B;AAC1B,QAAM,SAA4B;AAAA,IAChC,MAAM;AAAA,IACN,OAAO,YAAY,WAAW;AAAA,IAC9B,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AAEA,MAAI,UAAU,SAAS,qBAAqB;AAC1C,WAAO,QAAQ,YAAY;AAC3B,WAAO,OAAO;AACd,WAAO,WAAW;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,gBAAiB,UAA+B;AACtD,MACE,kBAAkB,4BAClB,kBAAkB,4BAClB,kBAAkB,qBAClB;AACA,WAAO,QAAQ,YAAY,SAAS;AACpC,WAAO,OACL,kBAAkB,2BACd,SACA,kBAAkB,2BAChB,cACA;AACR,WAAO,WAAW;AAClB,WAAO;AAAA,EACT;AAEA,MACE,UAAU,SAAS,4BACnB,UAAU,SAAS,8BACnB,UAAU,SAAS,wBACnB;AACA,WAAO;AAAA,EACT;AAEA,MAAI,UAAU,SAAS,uBAAuB;AAC5C,UAAM,cAAc,UAAU,aAAa,CAAC;AAC5C,UAAM,OAAO,aAAa;AAE1B,QAAI,CAAC,MAAM;AACT,aAAO,QAAQ,YAAY,OAAO;AAClC,aAAO,OAAO;AACd,aAAO,WAAW;AAClB,aAAO;AAAA,IACT;AAEA,QAAI,KAAK,SAAS,kBAAkB;AAClC,YAAM,aAAa,cAAc,KAAK,QAAQ,UAAU;AAExD,UAAI,YAAY;AACd,YAAI,aAAa,UAAU,GAAG;AAC5B,iBAAO,QAAQ,YAAY;AAC3B,iBAAO,OAAO;AACd,iBAAO,WAAW;AAClB,iBAAO;AAAA,QACT;AAEA,YAAI,YAAY,UAAU,MAAM,QAAW;AACzC,iBAAO,QAAQ,YAAY,UAAU;AACrC,iBAAO,OAAO;AACd,iBAAO,WAAW;AAClB,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,aAAO,QAAQ,YAAY,OAAO;AAClC,aAAO,OAAO,cAAc;AAC5B,aAAO,WAAW;AAClB,aAAO;AAAA,IACT;AAEA,QAAI,KAAK,SAAS,6BAA6B,KAAK,SAAS,sBAAsB;AACjF,aAAO,QAAQ,YAAY,YAAY;AACvC,aAAO,OAAO,YAAY,IAAI,SAAS,eAAe,YAAY,GAAG,OAAO;AAC5E,aAAO,WAAW;AAClB,aAAO;AAAA,IACT;AAEA,WAAO,QAAQ,YAAY,OAAO;AAClC,WAAO,OAAO;AACd,WAAO,WAAW;AAClB,WAAO;AAAA,EACT;AAEA,MAAI,UAAU,SAAS,uBAAuB;AAC5C,WAAO,QAAQ,YAAY,YAAY;AACvC,WAAO,OAAO,UAAU,IAAI,QAAQ;AACpC,WAAO,WAAW;AAClB,WAAO;AAAA,EACT;AAEA,MAAI,UAAU,SAAS,uBAAuB;AAC5C,UAAM,OAAO,UAAU;AAEvB,QAAI,KAAK,SAAS,kBAAkB;AAClC,YAAM,aAAa,cAAc,KAAK,QAAQ,UAAU;AAExD,UAAI,cAAc,YAAY,UAAU,MAAM,QAAW;AACvD,eAAO,QAAQ,YAAY,UAAU;AACrC,eAAO,OAAO;AACd,eAAO,WAAW;AAClB,eAAO;AAAA,MACT;AAEA,aAAO,QAAQ,YAAY,WAAW;AACtC,aAAO,OAAO,cAAc;AAC5B,aAAO,WAAW;AAClB,aAAO;AAAA,IACT;AAEA,WAAO,QAAQ,YAAY,WAAW;AACtC,WAAO,OAAO;AACd,WAAO,WAAW;AAClB,WAAO;AAAA,EACT;AAEA,SAAO;AACT;;;ACzKO,SAAS,wBAAwB,MAAiB,YAAoD;AAC3G,QAAM,WAAW,WAAW,kBAAkB,IAAI;AAClD,MAAI,QAAQ,KAAK,MAAO,CAAC;AAEzB,MAAI,SAAS,SAAS,GAAG;AACvB,YAAQ,SAAS,CAAC,EAAE,MAAO,CAAC;AAAA,EAC9B;AAEA,SAAO,WAAW,KAAK,MAAM,OAAO,KAAK,MAAO,CAAC,CAAC;AACpD;AAUO,SAAS,aAAa,MAAiB,YAA8D;AAC1G,QAAM,WAAW,WAAW,kBAAkB,IAAI;AAClD,MAAI,QAAQ,KAAK,MAAO,CAAC;AAEzB,MAAI,SAAS,SAAS,GAAG;AACvB,YAAQ,SAAS,CAAC,EAAE,MAAO,CAAC;AAAA,EAC9B;AAEA,MAAI,MAAM,KAAK,MAAO,CAAC;AACvB,QAAM,YAAY,WAAW,KAAK,MAAM,KAAK,MAAM,CAAC;AAEpD,MAAI,UAAU,WAAW,MAAM,GAAG;AAChC,WAAO;AAAA,EACT,WAAW,UAAU,WAAW,IAAI,GAAG;AACrC,WAAO;AAAA,EACT;AAEA,SAAO,CAAC,OAAO,GAAG;AACpB;AAUO,SAAS,mBACd,YACA,YACA,gBAAyB,MACjB;AACR,QAAM,QAAkB,CAAC;AACzB,MAAI,YAAY;AAEhB,aAAW,aAAa,YAAY;AAClC,UAAM,OAAO,wBAAwB,UAAU,MAAM,UAAU,EAAE,KAAK;AAEtE,QAAI,iBAAiB,cAAc,MAAM,UAAU,UAAU,WAAW;AACtE,YAAM,KAAK,EAAE;AAAA,IACf;AAEA,UAAM,KAAK,IAAI;AACf,gBAAY,UAAU;AAAA,EACxB;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;;;AC7DA,IAAM,OAAwB;AAAA,EAC5B,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,aAAa;AAAA,MACb,UAAU;AAAA,MACV,aAAa;AAAA,MACb,KAAK;AAAA,IACP;AAAA,IACA,SAAS;AAAA,IACT,QAAQ;AAAA,MACN;AAAA,QACE,MAAM;AAAA,QACN,YAAY;AAAA,UACV,OAAO;AAAA,YACL,MAAM;AAAA,YACN,OAAO,EAAE,MAAM,SAAS;AAAA,YACxB,aAAa;AAAA,UACf;AAAA,UACA,iBAAiB;AAAA,YACf,MAAM;AAAA,YACN,SAAS;AAAA,YACT,aAAa;AAAA,UACf;AAAA,QACF;AAAA,QACA,sBAAsB;AAAA,MACxB;AAAA,IACF;AAAA,IACA,UAAU;AAAA,MACR,YAAY;AAAA,IACd;AAAA,EACF;AAAA,EAEA,OAAO,SAA2B;AAChC,UAAM,aAAa,QAAQ,cAAc,QAAQ,cAAc;AAC/D,UAAM,WAAW,QAAQ,YAAY;AACrC,UAAM,QAAQ,SAAS,SAAS,MAAM;AACtC,UAAM,UAAyB,QAAQ,QAAQ,CAAC,KAAK,CAAC;AACtD,UAAM,kBAAkB,UAAU,QAAQ;AAC1C,UAAM,cAA2B,EAAE,GAAG,cAAc;AAEpD,QAAI,QAAQ,SAAS,MAAM,QAAQ,QAAQ,KAAK,GAAG;AACjD,cAAQ,MAAM,QAAQ,CAAC,UAAU,UAAU;AACzC,cAAM,gBAAgB,cAAc,QAAQ;AAC5C,YAAI,kBAAkB,QAAW;AAC/B,iBAAO,KAAK,aAAa,EAAE,QAAQ,CAAC,QAAQ;AAC1C,gBAAI,cAAc,GAAG,MAAM,eAAe;AACxC,0BAAY,GAAG,IAAI;AAAA,YACrB;AAAA,UACF,CAAC;AAAA,QACH;AACA,oBAAY,QAAQ,IAAI;AAAA,MAC1B,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL,QAAQ,MAAe;AACrB,cAAM,aAAkC,CAAC;AACzC,YAAI;AAEJ,YAAI,OAAO;AACT,gBAAM,iBAAiB,WAAW;AAMlC,cAAI,gBAAgB,qBAAqB;AACvC,kBAAM,KAAK,eAAe,oBAAoB;AAC9C,kBAAM,cAAc,GAAG,SAAS;AAAA,cAC9B,CAAC,MACC,EAAE,SAAS,cACX,EAAE,SAAS,YACX,EAAE,SAAS,WAAW,KAAK,CAAC,SAAS,CAAC,KAAK,aAAa,KAAK,IAAI,SAAS,OAAO;AAAA,YACrF;AAEA,gBAAI,aAAa;AACf,iCAAmB,YAAY;AAAA,YACjC,OAAO;AACL;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,mBAAW,aAAa,KAAK,MAAM;AACjC,cACE,SACA,qBACC,UAAU,MAAO,CAAC,IAAI,iBAAiB,CAAC,KAAK,UAAU,MAAO,CAAC,IAAI,iBAAiB,CAAC,IACtF;AACA;AAAA,UACF;AAEA,gBAAM,WAAW,iBAAiB,WAAW,YAAY,WAAW;AACpE,cAAI,UAAU;AACZ,uBAAW,KAAK,QAAQ;AAAA,UAC1B;AAAA,QACF;AAEA,YAAI,WAAW,SAAS,EAAG;AAE3B,YAAI,aAIO;AAEX,iBAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;AAC1C,gBAAM,OAAO,WAAW,IAAI,CAAC;AAC7B,gBAAM,OAAO,WAAW,CAAC;AAEzB,cAAI,KAAK,QAAQ,KAAK,OAAO;AAC3B,yBAAa,EAAE,OAAO,GAAG,SAAS,MAAM,UAAU,KAAK;AACvD;AAAA,UACF;AAAA,QACF;AAEA,YAAI,CAAC,WAAY;AAEjB,gBAAQ,OAAO;AAAA,UACb,MAAM,WAAW,QAAQ;AAAA,UACzB,WAAW;AAAA,UACX,MAAM;AAAA,YACJ,SAAS,WAAW,QAAQ;AAAA,YAC5B,iBAAiB,YAAY,WAAW,QAAQ,KAAK,KAAK;AAAA,YAC1D,UAAU,WAAW,SAAS;AAAA,YAC9B,kBAAkB,YAAY,WAAW,SAAS,KAAK,KAAK;AAAA,UAC9D;AAAA,UACA,IAAI,OAAO;AACT,kBAAM,SAAS,CAAC,GAAG,UAAU,EAAE,KAAK,CAAC,GAAG,MAAM;AAC5C,kBAAI,EAAE,UAAU,EAAE,OAAO;AACvB,uBAAO,EAAE,QAAQ,EAAE;AAAA,cACrB;AAEA,qBAAO,WAAW,QAAQ,CAAC,IAAI,WAAW,QAAQ,CAAC;AAAA,YACrD,CAAC;AAED,kBAAM,UAAU,mBAAmB,QAAQ,YAAY,eAAe;AACtE,kBAAM,aAAa,aAAa,WAAW,CAAC,EAAE,MAAM,UAAU;AAC9D,kBAAM,YAAY,aAAa,WAAW,WAAW,SAAS,CAAC,EAAE,MAAM,UAAU;AAEjF,mBAAO,MAAM,iBAAiB,CAAC,WAAW,CAAC,GAAG,UAAU,CAAC,CAAC,GAAG,UAAU,IAAI;AAAA,UAC7E;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,gBAAQ;;;ACnKf,IAAM,SAAS;AAAA,EACb,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,SAAS;AAAA,EACX;AAAA,EACA,OAAO;AAAA,IACL,OAAO;AAAA,EACT;AAAA,EACA,SAAS;AAAA,IACP,aAAa;AAAA,MACX,SAAS,CAAC,iBAAiB;AAAA,MAC3B,OAAO;AAAA,QACL,yBAAyB;AAAA,MAC3B;AAAA,IACF;AAAA;AAAA,IAEA,MAAM;AAAA,MACJ,aAAa;AAAA,QACX,SAAS;AAAA,UACP,IAAI,oBAAoB;AACtB,mBAAO;AAAA,UACT;AAAA,QACF;AAAA,QACA,OAAO;AAAA,UACL,yBAAyB;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,gBAAQ;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-vue-setup-order",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "ESLint plugin to enforce consistent order of statements in Vue 3 <script setup>",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"lint:fix": "eslint src tests --fix",
|
|
44
44
|
"prepublishOnly": "npm run build && npm run test:run",
|
|
45
45
|
"release": "npm run build && changeset publish",
|
|
46
|
-
"format": "prettier --write
|
|
47
|
-
"format:check": "prettier --check
|
|
46
|
+
"format": "prettier --write ./src",
|
|
47
|
+
"format:check": "prettier --check ./src",
|
|
48
48
|
"test": "vitest",
|
|
49
49
|
"test:coverage": "vitest run --coverage",
|
|
50
50
|
"test:run": "vitest run",
|
|
@@ -63,7 +63,8 @@
|
|
|
63
63
|
"prettier-plugin-organize-imports": "^4.1.0",
|
|
64
64
|
"tsup": "^8.0.1",
|
|
65
65
|
"typescript": "~5.3.3",
|
|
66
|
-
"vitest": "^4.0.16"
|
|
66
|
+
"vitest": "^4.0.16",
|
|
67
|
+
"vue-eslint-parser": "^10.2.0"
|
|
67
68
|
},
|
|
68
69
|
"peerDependencies": {
|
|
69
70
|
"eslint": ">=8.0.0"
|