From 2ae6bc6c344f22e4f42517a81a6fead52d7b648a Mon Sep 17 00:00:00 2001 From: Jun Shindo <46585162+jay-es@users.noreply.github.com> Date: Tue, 19 Jul 2022 22:35:51 +0900 Subject: [PATCH] add `sortSpreads` option (#7) * add sortSpreads option * 0.3.0 --- README.md | 40 +++++++++++++++++++++++++ package-lock.json | 4 +-- package.json | 2 +- src/rules/vue-sort-components.ts | 22 ++++++++++++-- tests/rules/vue-sort-components.spec.ts | 36 ++++++++++++++++++++-- 5 files changed, 95 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 82ee2fb..04df751 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,11 @@ export default defineComponent({ components: { Foo, Bar, Baz }, }); +// spreads must be grouped at the top +export default defineComponent({ + components: { Bar, Baz, Foo, ...others }, +}); + // not only in Vue-specific context const myObject = { components: { Foo, Bar, Baz }, @@ -76,8 +81,43 @@ export default defineComponent({ components: { Bar, Baz, Foo }, }); +// spreads must be grouped at the top +export default defineComponent({ + components: { ...others, Bar, Baz, Foo }, +}); + // not only in Vue-specific context const myObject = { components: { Bar, Baz, Foo }, }; ``` + +### Options + +This rule accepts a configuration object: + +```js +{ + "@jay-es/vue-sort-components/vue-sort-components": ["error", { sortSpreads: false }] +} +``` + +- `sortSpreads` - if `true`, enforce spread properties to be sorted. Default is `false`. + +#### sortSpreads + +Examples of **incorrect** code for the `{ sortSpreads: true }` option: + +```js +export default defineComponent({ + components: { ...others2, ...others1, Bar, Baz }, +}); +``` + +Examples of **correct** code for the `{ sortSpreads: true }` option: + +```js +export default defineComponent({ + components: { ...others1, ...others2, Bar, Baz }, +}); +``` diff --git a/package-lock.json b/package-lock.json index 47d36b3..103daa8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@jay-es/eslint-plugin-vue-sort-components", - "version": "0.2.0", + "version": "0.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@jay-es/eslint-plugin-vue-sort-components", - "version": "0.2.0", + "version": "0.3.0", "license": "MIT", "dependencies": { "natural-compare": "^1.4.0" diff --git a/package.json b/package.json index a7c1302..3111083 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@jay-es/eslint-plugin-vue-sort-components", - "version": "0.2.0", + "version": "0.3.0", "description": "A plugin for ESLint to keep order of component names", "main": "lib/index.js", "files": [ diff --git a/src/rules/vue-sort-components.ts b/src/rules/vue-sort-components.ts index 0a280bb..9b6fd62 100644 --- a/src/rules/vue-sort-components.ts +++ b/src/rules/vue-sort-components.ts @@ -10,14 +10,17 @@ const getArgName = (arg: Expression): string => const compareNodes = ( a: Property | SpreadElement, - b: Property | SpreadElement + b: Property | SpreadElement, + sortSpreads: boolean ): -1 | 0 | 1 => { if (a.type === "Property" && b.type === "Property") { return naturalCompare(getKeyName(a), getKeyName(b)); } if (a.type === "SpreadElement" && b.type === "SpreadElement") { - return naturalCompare(getArgName(a.argument), getArgName(b.argument)); + return sortSpreads + ? naturalCompare(getArgName(a.argument), getArgName(b.argument)) + : 0; } return a.type === "SpreadElement" ? -1 : 1; @@ -27,11 +30,22 @@ export const sortComponentsRule: Rule.RuleModule = { meta: { type: "layout", fixable: "code", + schema: [ + { + type: "object", + properties: { + sortSpreads: { type: "boolean" }, + }, + additionalProperties: false, + }, + ], messages: { sortComponents: "Component names must be sorted.", }, }, create(context) { + const sortSpreads: boolean = context.options[0]?.sortSpreads ?? false; + return { Property(node) { const { value } = node; @@ -43,7 +57,9 @@ export const sortComponentsRule: Rule.RuleModule = { } const { properties } = value; - const sorted = [...properties].sort(compareNodes); + const sorted = [...properties].sort((a, b) => + compareNodes(a, b, sortSpreads) + ); const sameOrder = properties.every((v, i) => v === sorted[i]); if (sameOrder) { diff --git a/tests/rules/vue-sort-components.spec.ts b/tests/rules/vue-sort-components.spec.ts index 12c85fc..3358c63 100644 --- a/tests/rules/vue-sort-components.spec.ts +++ b/tests/rules/vue-sort-components.spec.ts @@ -30,7 +30,20 @@ ruleTester.run("vue-sort-components", sortComponentsRule, { code: "const obj = { components: { ...others, bar, baz, foo } }", parserOptions: { ecmaVersion: 2018 }, }, - // not components + + // options.sortSpreads + { + code: "const obj = { components: { ...others2, ...others1, bar, baz, foo } }", + parserOptions: { ecmaVersion: 2018 }, + }, + { + options: [{ sortSpreads: true }], + code: "const obj = { components: { ...others1, ...others2, bar, baz, foo } }", + parserOptions: { ecmaVersion: 2018 }, + }, + + // not applied + // non-component { code: "const obj = { nested: { foo, bar } }", parserOptions: { ecmaVersion: 6 }, @@ -65,8 +78,25 @@ ruleTester.run("vue-sort-components", sortComponentsRule, { }, // spread { - code: "const obj = { components: { bar, ...others, foo, ...others2 } }", - output: "const obj = { components: { ...others, ...others2, bar, foo } }", + code: "const obj = { components: { bar, ...others, foo } }", + output: "const obj = { components: { ...others, bar, foo } }", + parserOptions: { ecmaVersion: 2018 }, + errors: [{ messageId: "sortComponents" }], + }, + + // options.sortSpreads + { + code: "const obj = { components: { bar, ...others2, foo, ...others1 } }", + output: + "const obj = { components: { ...others2, ...others1, bar, foo } }", + parserOptions: { ecmaVersion: 2018 }, + errors: [{ messageId: "sortComponents" }], + }, + { + options: [{ sortSpreads: true }], + code: "const obj = { components: { bar, ...others2, foo, ...others1 } }", + output: + "const obj = { components: { ...others1, ...others2, bar, foo } }", parserOptions: { ecmaVersion: 2018 }, errors: [{ messageId: "sortComponents" }], },