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

Update our Default Sort Order builtins, (thirdparty & absolute paths), relative paths #83

Merged
merged 2 commits into from
May 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 93 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ Since then more critical features & fixes have been added, and the options have
- [How does import sort work?](#how-does-import-sort-work)
- [Options](#options)
- [`importOrder`](#importorder)
- [1. Put specific dependencies at the top](#1-put-specific-dependencies-at-the-top)
- [2. Keep css modules at the bottom](#2-keep-css-modules-at-the-bottom)
- [3. Add spaces between import groups](#3-add-spaces-between-import-groups)
- [4. Group type imports separately from values](#4-group-type-imports-separately-from-values)
- [5. Group aliases with local imports](#5-group-aliases-with-local-imports)
- [`importOrderTypeScriptVersion`](#importordertypescriptversion)
- [`importOrderParserPlugins`](#importorderparserplugins)
- [Prevent imports from being sorted](#prevent-imports-from-being-sorted)
Expand Down Expand Up @@ -182,38 +187,111 @@ The _third party imports_ position (it's top by default) can be overridden using

**type**: `Array<string>`

A collection of Regular expressions in string format.
The main way to control the import order and formatting, `importOrder` is a collection of Regular expressions in string format, along with a few "special case" strings that you can use.

**default value**:

```js
[
// node.js built-ins are always first
'<THIRD_PARTY_MODULES>', // Non-relative imports
'^[.]', // relative imports
],
```

By default, this plugin sorts as documented on the line above, with Node.js built-in modules at the top, followed by non-relative imports, and lastly any relative import starting with a `.` character.

Here are some common ways to configure `importOrder`:

##### 1. Put specific dependencies at the top

Some styles call for putting the import of `react` at the top of your imports, which you could accomplish like this:

```json
"importOrder": ["^@core/(.*)$", "^@server/(.*)$", "^@ui/(.*)$", "^[./]"],
"importOrder": ["react", "<THIRD_PARTY_MODULES>", "^[.]"]
```

_Default:_ `[]`
e.g.:

```ts
import * as React from 'react';
import cn from 'classnames';
import MyApp from './MyApp';
```

By default, this plugin will not move any imports. To separate third party from relative imports, use `["^[./]"]`. This will become the default in the next major version.
##### 2. Keep css modules at the bottom

The plugin moves the third party imports to the top which are not part of the `importOrder` list.
To move the third party imports at desired place, you can use `<THIRD_PARTY_MODULES>` to assign third party imports to the appropriate position:
Imports of CSS files are often placed at the bottom of the list of imports, and can be accomplished like so:

```json
"importOrder": ["^@core/(.*)$", "<THIRD_PARTY_MODULES>", "^@server/(.*)$", "^@ui/(.*)$", "^[./]"],
"importOrder": ["<THIRD_PARTY_MODULES>", "^(?!.*[.]css$)[./].*$", ".css$",]
```

e.g.:

```ts
import * as React from 'react';
import MyApp from './MyApp';
import styles from './global.css';
```

If you would like to order type imports differently from value imports, you can use the special `<TYPES>` string. This example will place third party types at the top, followed by local types, then third party value imports, and lastly local value imports:
##### 3. Add spaces between import groups

If you want to group your imports into "chunks" with blank lines between, you can add empty strings like this:

```json
"importOrder": ["<TYPES>", "<TYPES>^[./]", "<THIRD_PARTY_MODULES>", "^[./]"],
"importOrder": ["", "<THIRD_PARTY_MODULES>", "", "^[.]",]
```

_Note:_ If you want to separate some groups from others, you can add an empty string to your `importOrder` array to signify newlines. For example:
(Note the empty string at the start, to add a blank line after node.js built-ins)

```js
e.g.:

```ts
import fs from 'fs';

import { debounce, reduce } from 'lodash';

import MyApp from './MyApp';
```

##### 4. Group type imports separately from values

If you're using Flow or TypeScript, you might want to separate out your type imports from imports of values. And to be especially fancy, you can even group 3rd party types together, and your own local type imports separately:

```json
"importOrder": ["<TYPES>", "<TYPES>^[.]", "<THIRD_PARTY_MODULES>", "^[.]",]
```

e.g.:

```ts
import type { Logger } from '@tanstack/react-query';
import type { Location } from 'history';
import type {Props} from './App';
import { QueryClient} from '@tanstack/react-query';
import { createBrowserHistory } from 'history';
import App from './App';
```

##### 5. Group aliases with local imports

If you define non-relative aliases to refer to local files without long chains of `"../../../"`, you can include those aliases in your `importOrder` to keep them grouped with your local code.

```json
"importOrder": [
"^react", // React will be placed at the top of third-party modules
"<THIRD_PARTY_MODULES>",
"", // use empty strings to separate groups with empty lines
"^[./]"
],
"^(@api|@assets|@ui)(/.*)$",
"^[.]"]
```

e.g.:

```ts
import { debounce, reduce } from 'lodash';
import { Users } from '@api';
import icon from '@assets/icon';
import App from './App';
```

#### `importOrderTypeScriptVersion`
Expand Down
14 changes: 12 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { parsers as flowParsers } from 'prettier/parser-flow';
import { parsers as htmlParsers } from 'prettier/parser-html';
import { parsers as typescriptParsers } from 'prettier/parser-typescript';

import { THIRD_PARTY_MODULES_SPECIAL_WORD } from './constants';
import { defaultPreprocessor } from './preprocessors/default';
import { vuePreprocessor } from './preprocessors/vue';
import type { PrettierOptions } from './types';
Expand All @@ -25,8 +26,17 @@ export const options: Record<
type: 'path',
category: 'Global',
array: true,
default: [{ value: [] }],
description: 'Provide an order to sort imports.',
default: [
{
value: [
// node.js built-ins are always first
THIRD_PARTY_MODULES_SPECIAL_WORD, // Everything not matching relative imports
'^[.]', // relative imports
Copy link
Owner

@IanVS IanVS May 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be ^[./]? That seems to be what we use in our tests, at least...

That would include absolute imports, which is a little odd…

Copy link
Collaborator Author

@fbartho fbartho May 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t think so?

  • ^[./] matches /foo/bar, ../foo/bar , ./foo/bar
  • ^[.] only matches ../foo/bar, ./foo/bar — and doesn’t match file-system absolute-path imports

This is exactly the confusion I was a little worried about.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t think file-system absolute-path imports are that common, but yeah

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[I see now that you edited your github comment after I had loaded the page, but before I replied, lol]

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, let's leave it the way you've got it. Absolute file system imports would be weird, and should probably deserve an explicit importOrder.

],
},
],
description:
'Provide an order to sort imports. [node.js built-ins are always first]',
},
importOrderParserPlugins: {
type: 'path',
Expand Down