Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Sort By Specifier, Especially Within an Import Group #131

Open
tryforceful opened this issue Oct 2, 2023 · 3 comments
Open

Allow Sort By Specifier, Especially Within an Import Group #131

tryforceful opened this issue Oct 2, 2023 · 3 comments
Assignees
Labels
enhancement New feature or request

Comments

@tryforceful
Copy link

Is your feature request related to a problem?

Right now the grouping I have configured is like this:

importOrder: [
    '^vue$', // vue core
    '',
    '^@/logger$', // logger 
    '',
    '(.*)\.vue$', // components
    '',
    '^(@/composables/(.*)|@/store.*|vue-router|vue-i18n|@vueuse/.*)$', // composables
  ]

And it generates a sorted / grouped import set like this:

import { onMounted, ref } from 'vue';

import logger from '@/logger';

import Date from '@/components/atoms/inputs/Date.vue';
import Grape from '@/components/molecules/paginations/Grape.vue';
import Apple from '@/components/molecules/toolbars/Apple.vue';
import Fig from '@/components/organisms/drawers/Fig.vue';
import Cantaloupe from '@/components/organisms/headers/Cantaloupe.vue';
import Hawthorne from '@/components/organisms/headers/Hawthorne.vue';
import Banana from '@/components/organisms/tables/Banana.vue';
import Endive from '@/components/templates/Endive.vue';

import { useStore } from '@/store';
import { useRoute } from 'vue-router';

However, the Vue SFC components here are always going to have named, default imports. I would prefer to have them in natural sort order by specifier rather than by their import path, so that I can easily scan the list and see what is present or missing.

It doesn't matter to me what their relative path is to me in this case, because I have used the grouping feature to ensure that only Vue SFCs will be in this block. And even though there's nothing tightly restricting that the variable name I give the component would match the component file name, I don't see that as a blocker for this feature request.

Describe the solution you'd like

I'd like for the sorting to generate this order of imports instead:

import { onMounted, ref } from 'vue';

import logger from '@/logger';

import Apple from '@/components/molecules/toolbars/Apple.vue';
import Banana from '@/components/organisms/tables/Banana.vue';
import Cantaloupe from '@/components/organisms/headers/Cantaloupe.vue';
import Date from '@/components/atoms/inputs/Date.vue';
import Endive from '@/components/templates/Endive.vue';
import Fig from '@/components/organisms/drawers/Fig.vue';
import Grape from '@/components/molecules/paginations/Grape.vue';
import Hawthorne from '@/components/organisms/headers/Hawthorne.vue';

import { useStore } from '@/store';
import { useRoute } from 'vue-router';

Note that only the sort order of the components (the major block) have changed to be in natural sort order.

I feel that this could be accomplished with an alternative supported syntax for the importOrder key in eslintrc:

e.g.

importOrder: [
	...
    ['(.*)\.vue$', {sortBy: 'specifier', sort: 'naturalAsc'}], // 2nd options parameter
	...
  ]

or

importOrder: [
	...
    {regex: '(.*)\.vue$', sortBy: 'specifier', sort: 'naturalAsc'}, // provide options and the regex together
	...
  ]

This would allow you to sort a single grouping of imports in a different way, while allowing the others to be sorted as they are today (natural sort by import path).

Other Considerations

I've seen people ask in regards to sorting by specifier, "What if you have a destructured list of specifiers alongside named default imports?"

In the case I presented it is not an issue, but I can understand the code would need to have well defined behavior for all cases. I think it makes sense that all imports that involve only destructuring be sorted to the top:

import { Bar } from "@/components/molecules/paginations/Grape.vue";
import { Baz } from "@/components/organisms/headers/Hawthorne.vue";
import { Foo } from "@/components/organisms/drawers/Fig.vue";
import Apple from '@/components/molecules/toolbars/Apple.vue';
import Banana from '@/components/organisms/tables/Banana.vue';
import Cantaloupe from '@/components/organisms/headers/Cantaloupe.vue';
import Date from '@/components/atoms/inputs/Date.vue';
import Endive from '@/components/templates/Endive.vue';

I think they should be sorted naturally by their first variable name, but if that is too complex of a behavior, could we say that the sort behavior is "undefined" among destructured items (the first 3 lines above), but still have the proper natural sorting of the specifier (lines 4-8 above)?

@IanVS
Copy link
Owner

IanVS commented Oct 2, 2023

Hi @tryforceful, thanks for the suggestion. I can see how this would be useful for you, but I'm not 100% convinced that this is worth the extra complexity in the code and the additional options, but will leave this issue open to see how many 👍 votes it accumulates. Is this a common approach in the Vue community?

In the meantime, have you checked out https://github.com/apcomplete/prettier-plugin-sort-imports? It's based on the trivago plugin, so it doesn't treat side-effect imports safely like this plugin does, but it does look like it sorts based on specifiers, like you want. Maybe it will suit your needs, or maybe you can use it as a guide for forking and creating a version of this plugin.

@IanVS IanVS added the enhancement New feature or request label Oct 2, 2023
@tryforceful
Copy link
Author

Thank you for your quick reply! 🙏🏼 And for the recommendation of @apcomplete's fork.

I checked it out -- even though it does sort by specifier, unfortunately that fork is a bit stale and doesn't handle the latest TS in my repo (as const, satisfies, etc.). It also doesn't have support for types as a separate consideration 😢. Moreover I have some concerns about that fork being maintained in the future...

I also checked out using tools like eslint-plugin-perfectionist's sort-imports, but it sadly doesn't have the great level of customization that your Prettier plugin provides -- namely the ability to group and order by regex match.


I won't claim to speak for the entire Vue community but I think many would find use for this feature (those that care about sorting). In the older Options API you would have to list all your imported components like this:

import { defineComponent } from 'vue'

import Apple from '@/components/molecules/toolbars/Apple.vue';
import Banana from '@/components/organisms/tables/Banana.vue';
import Cantaloupe from '@/components/organisms/headers/Cantaloupe.vue';
import Date from '@/components/atoms/inputs/Date.vue';

export default defineComponent({
  components:{
    Apple,
    Banana,
    Cantaloupe,
    Date,
  },
  ...
});

There's no reason to not list the components in natural sort order in the defineComponent section, without their import path context. And having the import sort order not match the order in the components object key also seems like a misstep...


In the end I might just swallow the loss and use your plugin as-is, even if my requested feature doesn't get implemented, because the pros of the rest of your plugin outweigh the loss IMO. (Great job, and thank you!)

If I were to make a fork and add this functionality would you be willing to consider merging the PR?... Maybe let's see...?

@apcomplete
Copy link

FWIW your concerns are warranted. I forked that repo for a previous job and have no plans of continuing to update it. Honestly didn't know anyone but me was even using or looking at it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants