This package contains CLI and APIs to format imports and exports for JavaScript and TypeScript code.
It's originally developed for a VSCode Plugin JS/TS Imports/Exports Sorter, then extracted to standalone CLI and lib for more use cases (e.g. CI/CD) and IDEs (e.g. IntelliJ).
- Change
resolveConfigForFile
to async function.
- Support Import Attributes.
- Support ArkTS (.ets files).
- Features
- Install
- CLI
- APIs
- Configuration Resolution
- Ignoring Files or Declarations
- Grouping Rules
- Sorting Rules
- Keeping Unused Imports
- Line Wrapping Style
- Monorepo Support
- Contribution
- License
- Group and sort imports by configurable rules, including sort by paths or names.
- Remove duplicated and unused names with exceptions.
- Ignore files or declarations by config or inline comments.
- Respect ESLint and eslint-plugin-import rules.
- Respect configs from Prettier and EditorConfig.
- Preserve
'use strict/client/server'
,///
directives, shebang (#!
) and comments. - Support Type-Only imports/exports, Type Modifier on names, Import Attributes and satisfies operator.
- Support NodeJS builtin modules.
- Cross-platform consistency: Windows, macOS and Linux (Ubuntu).
- Monorepo friendly.
- Support formatting
<script>
in Vue.js.
npm i -D format-imports
format-imports [options] [FILE1 FILE2 ...]
This command formats a number of given files.
If no files provided, it'll read the source from STDIN
and format it.
-
Options
-
-o, --output path::String
If not set, the results will be written back to input files, or
STDOUT
when reading fromSTDIN
.If set, the results will be written to that file. You can't specify output file when there are multiple input files.
When there is one input file and the output path is a directory, the result will be written to a new file under the output path with the same name as the input file.
-
--config path::String
If set,
format-imports
will read configurations from provided file, e.g.path/to/import-sorter.json
. The path can be either absolute or relative to the CWD (current work directory).When formatting a source file,
format-imports
will try to resolve configurations specific to that source file, and then merge it with the configurations from--config
option. Source file specific configurations will have higher precedence. -
-f, --force
Format all supported files, and ignore exclude patterns/globs and file-disable comments from no matter
--config
option or source file specific configurations. -
-d, --dry-run
Test-run the command without modifying or creating any files. Useful when you're not sure what will happen and want to be cautious.
-
-e, --extension js|ts|jsx|tsx
Default to
ts
.When reading from
STDIN
, you can specify source code type via this option. Supported types arejs
,ts
,jsx
andtsx
.If it's not set but
--output
is provided,format-imports
will try to infer code type from the output file extension. -
-l, --log
Show debug logs in STDOUT.
-
format-imports [options] DIRECTORY
This command formats all supported files under a directory.
-
Options
-
-o, --output path::String
If not set, the results will be written back to input files.
If set, the results will be written to new files under the output directory, with the same file structure as the input directory.
If the output directory doesn't exist, it'll be created.
-
--config path::String
See above.
-
--no-recursive
If not set,
format-imports
will search for supported source files recursively under the input directory.Otherwise, the search will be non-recursive.
-
-f, --force
See above.
-
-d, --dry-run
See above.
-
-l, --log
See above.
-
format-imports --check [options] FILE1/DIR1 [FILE2/DIR2 ...]
-
Options
-
-c, --check
If set,
format-imports
will check if provided files/directories are formatted. No changes will be made to any of the files.A non-zero code will be returned if any file fails to match the format, or any other error happens.
-
--config path::String
See above.
-
--no-recursive
See above.
-
-f, --force
Check all supported files, and ignore exclude patterns/globs and file-disable comments from no matter
--config
option or source file specific configurations. -
-l, --log
See above.
-
Example:
import fs from 'fs';
import {
formatSourceFromFile,
isFileExcludedByConfig,
resolveConfigForFile,
} from 'format-imports';
const fileName = '/path/to/source/file.ts';
const config = await resolveConfigForFile(fileName)
// Skip if file is excluded.
if (isFileExcludedByConfig(fileName, config))
return;
const text = fs.readFileSync(fileName).toString();
// Use sync version of formatSourceFromFile()
const newText = formatSourceFromFile.sync(text, fileName, config);
if (newText === undefined)
console.log("Everything is sorted!");
else
console.log(newText);
Caveat:
- Sync version of
formatSourceFromFile
andformatSourceWithoutFile
don't support ESLint config.
Please refer to APIs Documentation for full details.
You might want to extend Configuration and add your own options when integrating the APIs. It's already supported and actually working in JS/TS Imports/Exports Sorter extension.
All you need to do is defining your extended config type and using it as normal:
import {
Configuration,
mergeConfig,
resolveConfigForFile,
} from 'format-imports';
interface MyConfig extends Configuration {
sayHello?: boolean; // Must be optional
}
const initialConfig: MyConfig = initMyConfig();
const extraConfig: MyConfig = loadExtraConfig();
// Merge extended configs
const baseConfig = mergeConfig(initialConfig, extraConfig)
// Resolve extended config for source file
const config = await resolveConfigForFile('/path/to/file.ts', baseConfig);
if (config.sayHello) {
console.log('Hello!');
}
// ...
Please note that the new options must be optional.
import-sorter.json:
{
"sayHello": true
// ...
}
You can even customize how options are merged between configs. Please refer to mergeConfig and DEFAULT_MERGER for more details.
This package provides config JSON schemas for import-sorter.json
and package.json
(under schemas/
):
It's recommended to update the schemas after you've extended your config, if you want the new options to be available in import-sorter.json
and package.json
. An example of how that works can be found in JS/TS Imports/Exports Sorter extension source code.
The following configuration sources will be checked and merged when formatting a file:
- ESLint configuration.
"importSorter"
section inpackage.json
import-sorter.json
(File name is configurable)- Prettier configuration
.editorconfig
It's ok if any or all of them are not found, in which case default values will be used in config.
All config fields you can set in import-sorter.json
or package.json
under "importSorter"
section can be found in Configuration.
If installed, ESLint and plugins rules will be detected and consulted, so that the result code will comply to the lint rules.
Currently, the supported rules are:
- sort-imports
- max-len
- indent
- eol-last
- semi
- comma-dangle
- object-curly-spacing
- import/newline-after-import
- import/no-useless-path-segments
If there are conflicts between user config and ESLint rules, the ESLint rules will win to avoid any lint errors.
Note: You can ignore some or all ESLint rules via ignoreESLintRules.
For more info about how the conflicts are resolved, please check the ESLint Compatibility wiki.
There are a few ways to exclude files from inspection:
-
Add exclude or excludeGlob patterns to Configuration, or via
package.json
orimport-sorter.json
. E.g.:"exclude": ["regexPattern"], "excludeGlob": ["globPattern"],
- mergeConfig will merge all path patterns instead of overwrite.
- Use forward-slash (
/
) as path separator no matter in MacOS, Linux or Windows, because isFileExcludedByConfig will normalize the file name before matching.
-
Add the following comment at the beginning of the source file and add at least one empty line after:
// ts-import-sorter: disable
[Other code]
or
/* ts-import-sorter: disable */
[Other code]
Note:
- Excluded paths and file-disable comments are ignored if force flag is set.
To exclude a specific import
or export
declaration from formatting, please add the following as its leading or trailing comments:
// ts-import-sorter: disable
import Excluded from 'import/sorter';
or
export { Excluded } from 'import/sorter'; /* ts-import-sorter: disable */
To disable formatting for all exports, just set formatExports to false
.
You can sorts imports into different groups separated by empty lines (configurable), based on the rules defined in groupRules.
A grouping rule defines:
- Types of imports to apply.
- Path pattern to match.
- How to sort imports, by paths or first names, inside the group.
- Sorting Rules for paths and names within the group.
- Sub-groups to further adjust the order.
Notes:
- There are NO blank lines between sub-groups.
- Use emptyLinesBetweenGroups to change empty lines between groups.
- A group can have its own sortImportsBy regardless of the global option, and sub groups will respect it.
For example, "groupRules": ["^react$", {}, "^[.]"]
defines 3 groups (and their order):
"^react$"
: matches any named imports from exact path"react"
.{}
: is the fall-back group, i.e. any imports that don't match any other groups will fall into this group."^[.]"
: matches any named imports from paths starting with"."
.
The following is an example of the results:
import React from 'react';
import { TextDocument } from 'vscode';
import MyInput from './MyInput';
Notes:
- By default, script imports are in the first group if you don't explicitly define rules for them.
- Script imports will NOT be sorted within a (sub) group, though sub groups may change their order.
- Exports will NOT be grouped. Grouping Rules are only for imports.
For a complete guide, please refer to the Wiki.
You can customize sorting rules for all imports and exports, or imports within a group, on:
- How to compare import paths;
- How to compare imported/exported names;
Note:
- Exports will NOT be sorted based on paths. Only names within an export are sorted.
- Script imports will NOT be sorted.
You can decide:
- Whether to compare letters case-sensitively or -insensitively;
- The rank among lower-case letters, upper-case letters and
'_'
;
Here is an example:
"sortRules": {
"paths": ["_", "aA"],
"names": ["_", "aA"]
}
The above ["_", "aA"]
means:
- Strings are compared case-insensitively, and lower-case goes first in case of a tie.
[
,\
,]
,^
,_
and`
(backtick) are in front of letters ([a-zA-Z]
).
A sorted array might be ['_', 'a', 'A', 'b', 'B']
.
You can also disable sorting by assigning "none"
to sortRules
or its members, e.g.:
"sortRules": "none"
or
"sortRules": {
"paths": "none",
"names": "none"
}
If you set paths
to "none"
, import declarations will not be sorted.
If you set names
to "none"
, names will not be sorted within an import or export declaration.
Note:
- Setting
paths
ornames
tonull
doesn't disable sorting but uses the fall-back sorting rules, i.e.["AZ", "_", "az"]
.
For more details and how to construct your own rules, please read the Wiki.
By default all unused imports are removed. In some cases you might want to keep the import even if it's unused. For example to keep import tw from 'twin.macro'
you can do the following:
"keepUnused": ["twin.macro"]
This is equivalent to a more verbose version:
"keepUnused": [{ "path": "twin.macro" }]
Another example is import styled, { css } from 'styled-components'
and if you want to keep css
import while styled
is removed if unused, you can achieve that with the following configuration:
"keepUnused": [
{ "path": "styled-components", "names": ["css"] }
]
Both path
and names
are converted to regular expressions so you can get really wild here.
Note:
- You DON'T need to add
React
(React) andh
(Stencil) tokeepUnused
as they are handled already. - By default, keepUnused array is empty, i.e. DON'T keep any unused imports.
- To keep ALL unused imports you can simply set:
"keepUnused": [".*"]
You can determine when and how an import/export declaration is wrapped, e.g. how many binding names are allowed before wrapping.
There is also a preset style compatible with Prettier, that could be useful when, e.g., you are using prettier --check
in your CI/CD process.
For details please refer to the Wiki.
When reading config from import-sorter.json
or package.json
, Format-Imports will automatically look for them in the directory of the file to be formatted, and in successive parent directories all the way up to the root directory of the filesystem (unless "root": true
is specified).
Multiple import-sorter.json
or package.json
files can be useful when you want different configurations for different sub projects of your monorepo, while common settings are kept in the root import-sorter.json
or package.json
. When there is a conflict, the sub project (more localized) config will take precedence.
This is an open source project so your contribution will be well appreciated. Please refer to CONTRIBUTING.md for more information.
MIT © Zhao DAI daidodo@gmail.com