JSPM

  • Created
  • Published
  • Downloads 1460
  • Score
    100M100P100Q111393F
  • License MIT

JavaScript and TypeScript Import/Export Formatter.

Package Exports

  • format-imports

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (format-imports) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

format-imports

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 editors (hopefully).

[1.0] Release Notes

Added

  • Publish APIs: formatSource, resolveConfigForFile, isFileExcludedByConfig and more.
  • Release CLI format-imports.

Table of contents

Features

  • Group and sort imports by custom rules, including sort by paths or names.
  • Remove duplicated and unused names with configurable 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', /// directives, shebang (#!) and comments.
  • Support Type-Only imports/exports.
  • Cross-platform consistency: Windows, MacOS and Linux (Ubuntu).

Install

npm i -D format-imports

CLI

Format Files

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 from STDIN.

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 are js, ts, jsx and tsx.

If it's not set but --output is provided, format-imports will try to infer code type from the output file extension.

Format a Directory

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

Check Files and Directories

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.

APIs

Extension Settings

All VS Code settings under "tsImportSorter" section and their default values:

// Configuration file name.
"tsImportSorter.configuration.configurationFileName": "import-sorter.json",

// When to auto format imports/exports. Valid values are 'off' or 'onSave'.
"tsImportSorter.configuration.autoFormat": "onSave",

// Whether to format exports as well.
"tsImportSorter.configuration.formatExports": true,

// Disable formatting for files matching regular expressions.
"tsImportSorter.configuration.exclude": ["node_modules"],

// Disable formatting for files matching glob patterns.
"tsImportSorter.configuration.excludeGlob": [],

// Sort import declarations by paths or first names. Valid values are 'paths' or 'names'.
"tsImportSorter.sortImportsBy": "paths",

// Grouping rules for path patterns for imports. {} is the fall-back group.
"tsImportSorter.configuration.groupRules": [
  "^react(-dom)?$",
  "^@angular/",
  "^vue$",
  {},
  "^[@]",
  "^[.]"
],

// Sorting rule for import paths. Valid values are 'none' or string array.
"tsImportSorter.configuration.sortRules.paths": ["_", "aA"],

// Sorting rule for imported/exported names. Valid values are 'none' or string array.
"tsImportSorter.configuration.sortRules.names": ["_", "aA"],

// By default all unused imports are removed. Keep some or all them around with this setting if you need.
"tsImportSorter.configuration.keepUnused": [],

// Max binding names per line before wrapping for imports. 0 for no limit.
"tsImportSorter.configuration.maxBindingNamesPerLine": 1,

// Max default and binding names per line before wrapping for imports. 0 for no limit.
"tsImportSorter.configuration.maxDefaultAndBindingNamesPerLine": 2,

// Max binding names per line before wrapping for exports. 0 for no limit.
"tsImportSorter.configuration.maxExportNamesPerLine": 0,

// Max names on wrapped lines. 0 for no limit.
"tsImportSorter.configuration.maxNamesPerWrappedLine": 1,

// Number of empty lines between groups (NOT sub-groups).
"tsImportSorter.configuration.emptyLinesBetweenGroups": 1,

// Number of empty lines after the last import declaration.
"tsImportSorter.configuration.emptyLinesAfterAllImports": 1,

// Whether to remove the last slash when normalizing paths.
"tsImportSorter.configuration.removeLastSlashInPath": false,

// Whether to remove the last 'index' when normalizing paths.
"tsImportSorter.configuration.removeLastIndexInPath": false,

// Whether to enable debug mode and print detailed logs to the output channel.
"tsImportSorter.configuration.development.enableDebug": false,

Configuration

JS/TS Import/Export Sorter reads configurations from the following sources (in precedence from high to low):

  • ESLint configuration if installed.
  • "importSorter" section in package.json
  • import-sorter.json (File name is configurable)
  • Prettier configuration if installed
  • .editorconfig
  • VS Code "editor" and "files" settings
  • VS Code "tsImportSorter" settings

Here are all configs in package.json under "importSorter" section and their default values:

{
  "importSorter": {
    // When to auto format imports/exports. Valid values are 'off' or 'onSave'.
    "autoFormat": "onSave",

    // Whether to format exports as well.
    "formatExports": true,

    // Disable formatting for files matching regular expressions.
    "exclude": ["node_modules"],

    // Disable formatting for files matching glob patterns.
    "excludeGlob": [],

    // Sort import declarations by paths or first names. Valid values are 'paths' or 'names'.
    "sortImportsBy": "paths",

    // Grouping rules for path patterns for imports. {} is the fall-back group.
    "groupRules": ["^react(-dom)?$", "^@angular/", "^vue$", {}, "^[@]", "^[.]"],

    "sortRules": {
      // Sorting rule for import paths. Valid values are 'none' or string array.
      "paths": ["_", "aA"],

      // Sorting rule for imported/exported names. Valid values are 'none' or string array.
      "names": ["_", "aA"]
    },

    // By default all unused imports are removed. Keep some or all them around with this setting if you need.
    "keepUnused": [],

    // Max line length before wrapping. 0 for no limit.
    "maxLineLength": 80,

    // Max binding names per line before wrapping for imports. 0 for no limit.
    "maxBindingNamesPerLine": 1,

    // Max default and binding names per line before wrapping for imports. 0 for no limit.
    "maxDefaultAndBindingNamesPerLine": 2,

    // Max binding names per line before wrapping for exports. 0 for no limit.
    "maxExportNamesPerLine": 0,

    // Max names on wrapped lines. 0 for no limit.
    "maxNamesPerWrappedLine": 1,

    // Number of empty lines between groups (NOT sub-groups).
    "emptyLinesBetweenGroups": 1,

    // Number of empty lines after the last import declaration.
    "emptyLinesAfterAllImports": 1,

    // Whether to remove the last slash when normalizing paths.
    "removeLastSlashInPath": false,

    // Whether to remove the last 'index' when normalizing paths.
    "removeLastIndexInPath": false,

    // Number of spaces to replace a TAB.
    "tabSize": 2,

    // Indent lines with tabs or spaces. Valid values are 'tab' or 'space'.
    "tabType": "space",

    // Use single or double quotes. Valid values are 'single' or 'double'.
    "quoteMark": "single",

    // When to add trailing a comma for the last name. Valid values are 'none' or 'multiLine'.
    "trailingComma": "multiLine",

    // Whether to add semicolons at the end of declarations.
    "hasSemicolon": true,

    // Whether to end files with a new line.
    "insertFinalNewline": true,

    // Whether to add spaces between brackets. true for '{ id }' and false for '{id}'.
    "bracketSpacing": true
  }
}

import-sorter.json has all configs above. Example:

{
  "maxLineLength": 100,
  "quoteMark": "double",
  "tabSize": 4,
  "insertFinalNewline": false
}

ESLint Compatibility

If installed, ESLint and plugins rules will be detected and consulted, so that the result code will comply to the lint rules.

Currently supported rules are:

If there are conflicts between user config and ESLint rules, the ESLint rules will win to avoid any lint errors.

For more info about how the conflicts are resolved, please check the ESLint Compatibility wiki.

Ignore files or declarations

There are a few ways to exclude files from inspection:

  1. Add path patterns to exclude or excludeGlob in user or workspace settings in VSCode.

    "tsImportSorter.configuration.exclude": ["regexPattern"],
    "tsImportSorter.configuration.excludeGlob": ["globPattern"],
  2. Add path patterns to package.json or import-sorter.json.

    • All path patterns are merged together instead of overwritten.
    • Use forward-slash (/) as path separator no matter in MacOS, *nix or Windows.
  3. Add the following comment at the beginning of the source file and keep at least one empty line from the next declaration:

// ts-import-sorter: disable

[Other code]

or

/* ts-import-sorter: disable */

[Other code]

Note:

  • Excluded paths and file disable-comments are ignored if the formatting is triggered manually, i.e. from Command Palette, editor context menu or shortcut.

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": false in the config.

Maximum names per line

Whether to wrap an import declaration is decided by maxBindingNamesPerLine and maxDefaultAndBindingNamesPerLine, as well as maxLineLength.

Whether to wrap an export declaration is decided by maxExportNamesPerLine, as well as maxLineLength.

maxBindingNamesPerLine

For a declaration importing only binding names, this value determines how many names are allowed before wrapping.

For example, if you set:

"maxBindingNamesPerLine": 2,

then

import { A } from 'a';    // No wrap as there is 1 name
import { B, C } from 'b'; // No wrap as there are 2 names

import {
  D,
  E,
  F,
} from 'c';   // Wrapped as there are more than 2 names

maxDefaultAndBindingNamesPerLine

For a declaration importing default and binding names, this value determines how many names are allowed before wrapping.

For example, if you set:

"maxDefaultAndBindingNamesPerLine": 2,

then

import A from 'a';        // No wrap as there is 1 name
import B, { C } from 'b'; // No wrap as there are 2 names
import D, {
  E,
  F,
} from 'c'; // Wrapped as there are more than 2 names

maxExportNamesPerLine

For export {} or export {} from 'x' declarations, this value determines how many names are allowed before wrapping.

For example, if you set:

"maxExportNamesPerLine": 2,

then

export { A };             // No wrap as there is 1 name
export { B, C } from 'b'; // No wrap as there are 2 names
export {
  D,
  E,
  F,
} from 'c'; // Wrapped as there are more than 2 names

maxNamesPerWrappedLine

If an import/export declaration is wrapped, this value decides how many names there are per line.

For example, if you set:

"maxNamesPerWrappedLine": 2,

then

import {
  A, B,
  C, D,
  E,
} from 'a'; // There are 2 names at most per wrapped line

export {
  A, B,
  C, D,
  E,
}; // There are 2 names at most per wrapped line

Grouping Rules

JS/TS Import/Export Sorter can put 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.

Sorting Rules

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 specifying "none" in sortRules, e.g.:

"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 or names to null 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.

Unused Imports Removal

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) and h (Stencil) to keepUnused 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": [".*"]

Contribution

This is a community supported project so your contribution will be well appreciated. Please refer to CONTRIBUTING.md for more information.

Thanks

The initiative came from import-sorter.

License

MIT