Skip to content

Grouping Rules

Zhao DAI edited this page Sep 2, 2022 · 7 revisions

Grouping Rules

You can sort imports into different groups separated by empty lines (configurable), based on the rules defined in groupRules.

Table of Content

Types of Imports

Imports are classified to the following types:

  • scripts: Script imports, e.g. import 'some_scripts'.
  • multiple: Imports with multiple names, e.g. import A, {B, C} from 'a' or import A, * as B from 'a'.
  • single: Imports with single name, e.g. import A from 'a' or import {A} from 'a'.
  • namespace: Namespace imports, e.g. import * as A from 'a'.
  • named: All multiple, single and namespace combined.
  • all: All scripts and named combined.

Notes:

  • The classification is compatible with ESLint sort-imports intentionally, so the results can comply with its rules.

Grouping Rule

A grouping rule consists of the following fields:

flags

Can be any of the above import types, or an array of them, or undefined.

If flags is single type or an array of types, this group will accepts imports only of that type(s), subject to other conditions.

If flags is undefined, then it'll be inferred from the parent and sub-groups.

Notes:

  • Script imports will always be in front of other types of imports by default, unless explicitly defined in sub-groups.

regex

Can be any string or undefined.

This is the regular expression pattern to match import paths to determine if an import falls into this group.

It can be undefined if you don't want to repeat all patterns already defined in subGroups, i.e. imports matching one of subGroups will fall into this group automatically.

importType

Can be a boolean or undefined.

This value decides whether the group accepts import or import type declarations.

If it's true, the group accepts only import type declarations.

If it's false, the group accepts only import declarations.

If it's undefined, the group accepts both.

builtin

Can be a boolean or undefined.

This value decides whether the group accepts NodeJS builtin module imports.

If it's true, the group accepts only builtin module imports.

If it's false, the group accepts only non-builtin module imports.

If it's undefined, the group accepts both.

sortImportsBy

Can be "paths" or "names" or undefined.

This defines the way to sort import statements inside the group.

If it's undefined, this group will use its parent group's value, or the global sortImportsBy option.

If it's "paths", the import statements will be sorted by their paths, e.g.:

import B from "a";
import A from "b";

The sort.paths option will be used to compare the paths.

If it's "names", the import statements will be sorted by its first name, e.g.:

import A from "b";
import B from "a";

The sort.names option will be used to compare the names.

Notes:

  • Script imports will NOT be sorted regardless of sortImportsBy.

sort

Can be SortRules, "none" or undefined.

This defines the sorting rules for import paths and names within the group.

If it's "none", it equals to { "paths": "none", "names": "none" }, i.e. neither paths nor names will be sorted in this group.

If it's undefined, this group will inherit sorting rules from its parent group, or the global sortRules setting.

Notes:

  • Script imports will NOT be sorted regardless of sort or global sortRules.

subGroups

Can be an array of grouping rules or undefined.

This defines sub-groups as well as their sorting order. Please note there are NO blank lines between sub-groups.

It can be undefined if you don't need sub-groups.

You can define subGroups for script imports and that's the only way to re-order them. For example,

{
  "groupRules": [{"flags": "script", "subGroups": ["^b", "^a"]}]
}

Will produce:

import 'b'; // Sub-group "^b"
import 'a'; // Sub-group "^a"

Abbreviation

A grouping rule with only regex can be written as a string, e.g.:

"groupRules": ["abc"]

is equal to

"groupRules": [{ "regex": "abc" }]

A grouping rule with only subGroups can be written as an array, e.g.:

"groupRules": [["a", "b", "c"]]

is equal to

"groupRules": [{ "subGroups": ["a", "b", "c"] }]

Special Groups

Fall-back Group

When neither regex nor subGroups is defined, a group is a fall-back group. It exists even if you don't define it explicitly in your groupRules, and is at the end by default. E.g.

"groupRules": ["abc"]

is the same as

"groupRules": ["abc", {}]

When {} appears on top level, it accepts only named imports that don't match any other groups. E.g.

"groupRules": ["^a", {}, "^b"]

means that:

  • Named imports with path starting with 'a' belong to the first group.
  • Named imports with path starting with 'b' belong to the third group.
  • Any other named imports belong to the second group.

Fall-back Sub-group

If both regex and subGroups are defined in a group, it's possible that some imports match regex but none of the subGroups. In that case, a fall-back sub-group will be created. E.g.

"groupRules": [{ "regex": "^[ab]", "subGroups": ["^a"] }]

is equal to

"groupRules": [{ "regex": "^[ab]", "subGroups": ["^a", {}] }]

When {} appears in subGroups, it accepts imports falling into the parent group but none of the rest sub-groups. E.g.

"groupRules": [{ "regex": "^[abc]", "subGroups": ["^a", {}, "^b"] }]

means that:

  • Imports with path starting with 'a' are at the beginning.
  • Imports with path starting with 'b' are at the end.
  • Any other imports (within the group) are in the middle.

Customized Fall-back Group

There is a special case when regex is undefined and subGroups contains {}, e.g.:

"groupRules": [["^a", {}, "^b"]]

equals to

"groupRules": [{ "subGroups": ["^a", {}, "^b"] }]

It's still a top level fall-back group but the order of imports is adjusted by subGroups.

When there are multiple top level fall-back groups, the first one will win. Similarly, if there are multiple fall-back sub-groups within a group, the first one wins.

Fall-back Group for scripts

{ "flags": "scripts" }

This fall-back group accepts only script imports that don't fall into any other groups. It's at the beginning by default. E.g.:

"groupRules": [{ "flags": "scripts", "regex": "^a" }]

is the same as

"groupRules": [{ "flags": "scripts" }, { "flags": "scripts", "regex": "^a" }]

which means:

  • All script imports starting with a belong to the second group.
  • Any other script imports belong to the first group.

Also a fall-back sub-group is implicitly created in the following example and it's at the beginning:

"groupRules": [{ "flags": "scripts", "regex": "^[ab]", "subGroups": ["^a"] }]

is the same as

"groupRules": [{ "flags": "scripts", "regex": "^[ab]", "subGroups": [{}, "^a"] }]

Note: A sub-group inherits flags from its parent if flags is undefined.

Examples

Ex. 1: All in one group

"groupRules": []  // or null

Ex. 2: Custom groups

"groupRules": ["^a", "^b"]

Will produce:

import A from "axx"; // Group "^a"

import B from "bxx"; // Group "^b"

import X from "xxx"; // Fall-back group

Note:

  • Fall-back group is at the end by default.

Ex. 3: Reorder fall-back group

"groupRules": ["^a", {}, "^b"]

Will produce:

import A from "axx"; // Group "^a"

import X from "xxx"; // Fall-back group

import B from "bxx"; // Group "^b"

Ex. 4: Sub-groups

You can adjust the order of imports within a group via sub-groups.

"groupRules": [["^b", "^a"], "^c"]

Will produce:

// Group ["^b", "^a"]
import B from "bxx"; // Sub-group "^b"
import A from "axx"; // Sub-group "^a"

import C from "cxx"; // Group "^c"

import X from "xxx"; // Fall-back group

Ex. 5: Fall-back sub-group

"groupRules": [
  { "regex": "^[ab]", "subGroups":["^b"] },
]

Will produce:

// Group "^[ab]"
import B from "bxx"; // Sub-group "^b"
import A from "axx"; // Fall-back sub-group

import X from "xxx"; // Fall-back group

Note:

  • Fall-back sub-group is at the end of the parent group by default.
  • Fall-back group is at the end by default.

Ex. 6: Reorder fall-back sub-group

"groupRules": [
  { "regex": "^[abc]", "subGroups":["^a", {}, "^b"] },
]

Will produce:

// Group "^[abc]"
import A from "axx"; // Sub-group "^a"
import C from "cxx"; // Fall-back sub-group
import B from "bxx"; // Sub-group "^b"

import X from "xxx"; // Fall-back group

Note:

  • Fall-back group is at the end by default.

Ex. 7: Custom groups for scripts

"groupRules": [
  { "flags": "scripts", "regex": "^b" },
  { "flags": "scripts", "regex": "^a" }
]

Will produce:

import "xxx"; // Fall-back group

import "bxx"; // Group "^b"

import "axx"; // Group "^a"

Note: Fall-back group for scripts is at the beginning by default.

Ex. 8: Reorder fall-back group for scripts

"groupRules": [
  { "flags": "scripts", "regex": "^b" },
  { "flags": "scripts" },
  { "flags": "scripts", "regex": "^a" }
]

Will produce:

import "bxx"; // Group "^b"

import "xxx"; // Fall-back group

import "axx"; // Group "^a"

Ex. 9: Sub-groups for scripts

"groupRules": [
  { "flags": "scripts", "subGroups":["^b", "^a"] },
  { "flags": "scripts", "regex": "^c" }
]

Will produce:

// Group ["^b", "^a"]
import "bxx"; // Sub-group "^b"
import "axx"; // Sub-group "^a"

import "cxx"; // Group "^c"

Ex. 10: Fall-back sub-group for scripts

"groupRules": [
  { "flags": "scripts", "regex": "^[ab]", "subGroups":["^a"] },
]

Will produce:

import "xxx"; // Fall-back group for scripts

// Group "^[ab]"
import "bxx"; // Fall-back sub-group for scripts
import "axx"; // Sub-group "^a"

Notes:

  • Fall-back group for scripts is at the beginning by default.
  • Fall-back sub-group for scripts is at the beginning of the parent group by default.

Ex. 11: Group with custom sorting rules

"sortRules": { "name": ["az", "AZ"] },
"groupRules": [
  { "regex": "^a", "sort": { "names": ["AZ", "az"] } },
]

Will produce:

import { A, a } from "a"; // Group "^a" with sorting rule ["AZ", "az"] for names

import { b, B } from "b"; // Fall-back group with sorting rule ["az", "AZ"] for names