eslint-plugin-simple-import-sort
Advanced tools
Comparing version 3.1.1 to 4.0.0-beta.1
@@ -0,1 +1,27 @@ | ||
### Version 4.0.0-beta.1 (2019-06-15) | ||
- Changed: Sorting is now more human – it is case insensitive (matching the | ||
default behavior of TSLint, as well as many IDEs) and numbers are sorted by | ||
their numeric values. This might cause some churn but feels a lot nicer. See | ||
[#7] for more discussion. | ||
- Improved: `from` paths ending with dots in various ways used to be treated | ||
specially. This has now been simplified, which gives a more consistent | ||
sorting. Now, `"."` and `".."` are treated as `"./"` and `"../"` – and those | ||
are the only special cases for “dotty” paths. For example, you might see | ||
`import x from "."` now sorting before `import y from "./y"`. | ||
- Fixed: `".x"` is no longer considered to be a relative import. Only `from` | ||
paths equal to `"."` or `".."`, or that start with `"./"` or `"../"` are truly | ||
relative. This is a bit of an edge case, but if you do have “weird” imports | ||
starting with dots in unusual ways you might notice them jumping up to another | ||
group of imports. | ||
- Fixed: `import {} from "a"` is no longer considered a side-effect import. Only | ||
imports completely lacking the `{...} from` part are. Remove `{} from` if you | ||
relied on this from earlier versions. | ||
- Improved: Trailing spaces after imports are now preserved. Before, if you | ||
accidentally added some trailing spaces it would result in a “Run autofix to | ||
sort these imports!” error, but the autofix wouldn’t actually sort anything – | ||
it would only remove some spaces. That was a bit weird. Now, those spaces are | ||
preserved. It is up to other rules or [Prettier] to take care of trailing | ||
spaces. | ||
### Version 3.1.1 (2019-05-16) | ||
@@ -55,5 +81,7 @@ | ||
[@typescript-eslint/parser]: https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/parser | ||
[#7]: https://github.com/lydell/eslint-plugin-simple-import-sort/issues/7 | ||
[flow type imports]: https://flow.org/en/docs/types/modules/ | ||
[prettier]: https://prettier.io/ | ||
[sort-from]: README.md#why-sort-on-from | ||
[typescript]: https://www.typescriptlang.org/ | ||
<!-- prettier-ignore-end --> |
{ | ||
"name": "eslint-plugin-simple-import-sort", | ||
"version": "3.1.1", | ||
"version": "4.0.0-beta.1", | ||
"license": "MIT", | ||
@@ -38,3 +38,3 @@ "author": "Simon Lydell", | ||
"devDependencies": { | ||
"@typescript-eslint/parser": "1.9.0", | ||
"@typescript-eslint/parser": "1.10.2", | ||
"babel-eslint": "10.0.1", | ||
@@ -45,9 +45,9 @@ "cross-spawn": "6.0.5", | ||
"eslint-config-lydell": "14.0.0", | ||
"eslint-plugin-import": "2.17.2", | ||
"eslint-plugin-jest": "22.5.1", | ||
"eslint-plugin-import": "2.17.3", | ||
"eslint-plugin-jest": "22.6.4", | ||
"eslint-plugin-prettier": "3.1.0", | ||
"eslint-plugin-vue": "5.2.2", | ||
"jest": "24.8.0", | ||
"prettier": "1.17.1", | ||
"typescript": "3.4.5" | ||
"prettier": "1.18.2", | ||
"typescript": "3.5.2" | ||
}, | ||
@@ -54,0 +54,0 @@ "peerDependencies": { |
@@ -224,5 +224,21 @@ # eslint-plugin-simple-import-sort [![Build Status][travis-badge]][travis-link] | ||
Within each section, the imports are sorted alphabetically on the `from` string | ||
like [`array.sort()`][array-sort] works. Keep it simple! See also [“Why sort on | ||
`from`?”][sort-from]. | ||
(see also [“Why sort on `from`?”][sort-from]). Keep it simple! It helps looking | ||
at the code here: | ||
```js | ||
const collator = new Intl.Collator("en", { | ||
sensitivity: "base", | ||
numeric: true, | ||
}); | ||
function compare(a, b) { | ||
return collator.compare(a, b) || (a < b ? -1 : a > b ? 1 : 0); | ||
} | ||
``` | ||
In other words, the imports within groups are sorted alphabetically, | ||
case-insensitively and treating numbers like a human would, falling back to good | ||
old character code sorting in case of ties. See [Intl.Collator] for more | ||
information. | ||
Since “.” sorts before “/”, relative imports of files higher up in the directory | ||
@@ -232,6 +248,5 @@ structure come before closer ones – `"../../utils"` comes before `"../utils"`. | ||
shorter substrings sort before longer strings). For that reason there’s one | ||
addition to the alphabetical rule: sources ending with `.` or `./` are sorted | ||
_after_ other sources with the same prefix. Also, within the absolute imports | ||
group, imports starting with an ASCII letter or digit come first, separating | ||
them from those starting with symbols. | ||
addition to the alphabetical rule: `"."` and `".."` are treated as `"./"` and | ||
`"../"`. Also, within the absolute imports group, imports starting with an ASCII | ||
letter or digit come first, separating them from those starting with symbols. | ||
@@ -259,15 +274,15 @@ [webpack loader syntax] is stripped before sorting, so `"loader!a"` sorts before | ||
import b from "https://example.com/script.js"; | ||
import Error from "@/components/error.vue"; | ||
import c from "/"; | ||
import d from "/home/user/foo"; | ||
import Error from "@/components/error.vue" | ||
// Relative imports. | ||
import e from "../../utils"; | ||
import f from "../.."; | ||
import e from "../.."; | ||
import f from "../../Utils"; // Case insensitive. | ||
import type { B } from "../types"; | ||
import typeof C from "../types"; | ||
import g from "./constants"; | ||
import h from "./styles"; | ||
import i from "html-loader!./text.html"; | ||
import j from "."; | ||
import g from "."; | ||
import h from "./constants"; | ||
import i from "./styles"; | ||
import j from "html-loader!./text.html"; | ||
@@ -279,8 +294,13 @@ // Regardless of group, imported items are sorted like this: | ||
typeof y, | ||
// Numbers are sorted by their numeric value: | ||
img1, | ||
img2, | ||
img10, | ||
// Then everything else, alphabetically: | ||
k, | ||
l, | ||
L, // Case insensitive. | ||
m as anotherName, // Sorted by the original name “m”, not “anotherName”. | ||
m as tie, // But do use the \`as\` name in case of a tie. | ||
n, | ||
} from "."; | ||
} from "./x"; | ||
``` | ||
@@ -499,2 +519,4 @@ | ||
Note: `import {} from "wherever"` is _not_ treated as a side effect import. | ||
### The sorting autofix causes some odd whitespace! | ||
@@ -560,3 +582,2 @@ | ||
[@typescript-eslint/parser]: https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/parser | ||
[array-sort]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort | ||
[babel-eslint]: https://github.com/babel/babel-eslint | ||
@@ -578,2 +599,3 @@ [comment-handling]: #comment-and-whitespace-handling | ||
[import/order]: https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/order.md | ||
[intl.collator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Collator | ||
[jest]: https://jestjs.io/ | ||
@@ -580,0 +602,0 @@ [lines-around-comment]: https://eslint.org/docs/rules/lines-around-comment |
@@ -167,4 +167,4 @@ "use strict"; | ||
// Print the indentation before the the import or its first comment, if any, | ||
// to support indentation in `<script>` tags. | ||
// Print the indentation before the import or its first comment, if any, to | ||
// support indentation in `<script>` tags. | ||
const indentation = getIndentation( | ||
@@ -175,2 +175,12 @@ commentsBefore.length > 0 ? commentsBefore[0] : importNode, | ||
// Print spaces after the import or its last comment, if any, to avoid | ||
// producing a sort error just because you accidentally added a few trailing | ||
// spaces among the imports. | ||
const trailingSpaces = getTrailingSpaces( | ||
commentsAfter.length > 0 | ||
? commentsAfter[commentsAfter.length - 1] | ||
: importNode, | ||
sourceCode | ||
); | ||
const code = | ||
@@ -180,3 +190,4 @@ indentation + | ||
printSortedSpecifiers(importNode, sourceCode) + | ||
after; | ||
after + | ||
trailingSpaces; | ||
@@ -187,3 +198,3 @@ const all = [...commentsBefore, importNode, ...commentsAfter]; | ||
const { group, source } = getGroupAndSource(importNode); | ||
const { group, source } = getGroupAndSource(importNode, sourceCode); | ||
@@ -194,3 +205,3 @@ return { | ||
start: start - indentation.length, | ||
end, | ||
end: end + trailingSpaces.length, | ||
group, | ||
@@ -711,2 +722,16 @@ source, | ||
function getTrailingSpaces(node, sourceCode) { | ||
const tokenAfter = sourceCode.getTokenAfter(node, { | ||
includeComments: true, | ||
}); | ||
if (tokenAfter == null) { | ||
const text = sourceCode.text.slice(node.range[1]); | ||
const lines = text.split(NEWLINE); | ||
return lines[0]; | ||
} | ||
const text = sourceCode.text.slice(node.range[1], tokenAfter.range[0]); | ||
const lines = text.split(NEWLINE); | ||
return lines[0]; | ||
} | ||
function sortImportItems(items) { | ||
@@ -717,2 +742,5 @@ return items.slice().sort( | ||
compare(itemA.source.source, itemB.source.source) || | ||
// The `.source` has been slightly tweaked. To stay fully deterministic, | ||
// also sort on the original value. | ||
compare(itemA.source.originalSource, itemB.source.originalSource) || | ||
// Then put Flow type imports before regular ones. | ||
@@ -746,5 +774,9 @@ compare(itemA.source.importKind, itemB.source.importKind) || | ||
// `array.sort()` and `array.sort(compare)` are supposed to be equal. | ||
const collator = new Intl.Collator("en", { | ||
sensitivity: "base", | ||
numeric: true, | ||
}); | ||
function compare(a, b) { | ||
return a < b ? -1 : a > b ? 1 : 0; | ||
return collator.compare(a, b) || (a < b ? -1 : a > b ? 1 : 0); | ||
} | ||
@@ -764,4 +796,10 @@ | ||
// import "setup" | ||
function isSideEffectImport(importNode) { | ||
return importNode.specifiers.length === 0; | ||
// But not: import {} from "setup" | ||
// And not: import type {} from "setup" | ||
function isSideEffectImport(importNode, sourceCode) { | ||
return ( | ||
importNode.specifiers.length === 0 && | ||
!importNode.importKind && | ||
!isPunctuator(sourceCode.getFirstToken(importNode, { skip: 1 }), "{") | ||
); | ||
} | ||
@@ -786,5 +824,13 @@ | ||
// import a from "./" | ||
// import a from "." | ||
// import a from "./x" | ||
// import a from ".." | ||
// import a from "../x" | ||
function isRelativeImport(source) { | ||
return source[0] === "."; | ||
return ( | ||
source === "." || | ||
source === ".." || | ||
source.startsWith("./") || | ||
source.startsWith("../") | ||
); | ||
} | ||
@@ -821,3 +867,3 @@ | ||
// Loader syntax documentation: https://webpack.js.org/concepts/loaders/#inline | ||
function getGroupAndSource(importNode) { | ||
function getGroupAndSource(importNode, sourceCode) { | ||
const rawSource = importNode.source.value; | ||
@@ -829,3 +875,3 @@ const index = rawSource.lastIndexOf("!"); | ||
: [rawSource, ""]; | ||
const group = isSideEffectImport(importNode) | ||
const group = isSideEffectImport(importNode, sourceCode) | ||
? "sideEffect" | ||
@@ -843,10 +889,19 @@ : isPackageImport(source) | ||
group === "relative" | ||
? // This makes "." sort after "..", for instance. "\uffff" sorts | ||
// after anything else (as far as I know). | ||
source.replace(/\.\/?$/, "$&\uffff") | ||
? // Due to "." sorting before "/" by default, relative imports are | ||
// automatically sorted in a logical manner for us: Imports from files | ||
// further up come first, with deeper imports last. There’s one | ||
// exception, though: When the `from` part ends with one or two dots: | ||
// "." and "..". Those are supposed to sort just like "./", "../". So | ||
// add in the slash for them. (No special handling is done for cases | ||
// like "./a/.." because nobody writes that anyway.) | ||
source === "." || source === ".." | ||
? `${source}/` | ||
: source | ||
: group === "rest" | ||
? // This makes ASCII letters and digits sort before anything else | ||
// (except `\0` itself and the empty string). | ||
source.replace(/^[a-z\d]/i, "\0$&") | ||
? // This makes ASCII letters and digits sort first. When using | ||
// `Intl.Collator`, `\t` followed by a letter sorts first (while `\0` | ||
// followed by a letter comes a lot later!). | ||
source.replace(/^[a-z\d]/i, "\t$&") | ||
: source, | ||
originalSource: source, | ||
importKind: getImportKind(importNode), | ||
@@ -853,0 +908,0 @@ webpack, |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
55093
813
610
2