Skip to content

Commit

Permalink
feat: Add type as a sort group
Browse files Browse the repository at this point in the history
  • Loading branch information
mskelton committed Apr 16, 2023
1 parent dd02cc8 commit 6e98c60
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 4 deletions.
2 changes: 2 additions & 0 deletions docs/rules/exports.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ There are four built-in sort groups you can use:
source.
- Useful for differentiating between path aliases (e.g. `components/Hello`)
and dependencies (e.g. `react`).
1. `type`
- TypeScript type only imports (e.g. `export type { Foo } from 'foo'`)
1. `other`
- Catch all sort group for any exports which did not match other sort groups.

Expand Down
2 changes: 2 additions & 0 deletions docs/rules/imports.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ There are three built-in sort groups you can use:
- Imports which do not throw an error when calling `require.resolve`.
- Useful for differentiating between path aliases (e.g. `components/Hello`)
and dependencies (e.g. `react`)
1. `type`
- TypeScript type only imports (e.g. `import type { Foo } from 'foo'`)
1. `other`
- Catch all sort group for any imports which did not match other sort groups.

Expand Down
74 changes: 74 additions & 0 deletions src/__tests__/exports.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ createRuleTester({
},
}).run("sort/exports", rule, {
valid: [
// typeOrder
{
name: "typeOrder: keep",
code: dedent`
Expand Down Expand Up @@ -348,8 +349,38 @@ createRuleTester({
export { b } from 'b'
`,
},

// Sort groups
{
code: dedent`
const mark = ''
export default React
export { relA } from './a'
export { relB } from './b'
export { depA } from 'dependency-a'
export { depB } from 'dependency-b'
export type { A } from 'dependency-a'
export * from 'a'
export { b } from 'b'
export { mark }
`.trim(),
options: [
{
groups: [
{ type: "default", order: 10 },
{ type: "sourceless", order: 60 },
{ type: "type", order: 40 },
{ regex: "^\\.+\\/", order: 20 },
{ type: "dependency", order: 30 },
{ type: "other", order: 50 },
],
},
],
},
],
invalid: [
// typeOrder
{
name: "typeOrder: keep",
code: dedent`
Expand Down Expand Up @@ -400,5 +431,48 @@ createRuleTester({
options: [{ typeOrder: "first" }],
errors: [{ messageId: "unsorted" }],
},

// Sort groups
{
code: dedent`
const mark = ''
export type { A } from 'dependency-a'
export { depB } from 'dependency-b'
export { mark }
export default React
export { relB } from './b'
export * from 'a'
export { relA } from './a'
export { depA } from 'dependency-a'
export { b } from 'b'
`.trim(),
output: dedent`
const mark = ''
export * from 'a'
export { b } from 'b'
export { depA } from 'dependency-a'
export { depB } from 'dependency-b'
export { relA } from './a'
export { relB } from './b'
export type { A } from 'dependency-a'
export { mark }
export default React
`.trim(),
options: [
{
groups: [
{ type: "default", order: 60 },
{ type: "sourceless", order: 50 },
{ type: "type", order: 40 },
{ regex: "^\\.+\\/", order: 30 },
{ type: "dependency", order: 20 },
{ type: "other", order: 10 },
],
},
],
errors: [{ messageId: "unsorted" }],
},
],
})
68 changes: 68 additions & 0 deletions src/__tests__/imports.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,7 @@ createRuleTester({
},
}).run("sort/imports", rule, {
valid: [
// typeOrder
{
name: "typeOrder: keep",
code: dedent`
Expand Down Expand Up @@ -847,8 +848,40 @@ createRuleTester({
import { b } from 'b'
`,
},

// Sort groups
{
name: "Sort groups",
code: dedent`
import 'index.css'
import 'side-effect'
import a from "dependency-b"
import b from "dependency-c"
import type { A } from "dependency-a"
import c from "a.png"
import d from "b.jpg"
import e from "a"
import f from "b"
import g from "c"
import h from "../b"
import i from "./b"
`,
options: [
{
groups: [
{ type: "side-effect", order: 10 },
{ type: "type", order: 30 },
{ regex: "\\.(png|jpg)$", order: 40 },
{ regex: "^\\.+\\/", order: 60 },
{ type: "dependency", order: 20 },
{ type: "other", order: 50 },
],
},
],
},
],
invalid: [
// typeOrder
{
name: "typeOrder: keep",
code: dedent`
Expand Down Expand Up @@ -899,5 +932,40 @@ createRuleTester({
options: [{ typeOrder: "first" }],
errors: [{ messageId: "unsorted" }],
},

// Sort groups
{
name: "Sort groups",
code: dedent`
import c from "a.png"
import h from "../b"
import b from "dependency-c"
import type { A } from "dependency-a"
import d from "b.jpg"
import a from "dependency-b"
import i from "./b"
`,
output: dedent`
import a from "dependency-b"
import b from "dependency-c"
import type { A } from "dependency-a"
import c from "a.png"
import d from "b.jpg"
import h from "../b"
import i from "./b"
`,
errors: [{ messageId: "unsorted" }],
options: [
{
groups: [
{ type: "type", order: 30 },
{ regex: "\\.(png|jpg)$", order: 40 },
{ regex: "^\\.+\\/", order: 60 },
{ type: "dependency", order: 20 },
{ type: "other", order: 50 },
],
},
],
},
],
})
18 changes: 16 additions & 2 deletions src/rules/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,17 @@ import {

type Export = Exclude<ModuleDeclaration, ImportDeclaration>

const sortGroupsTypes = [
"default",
"sourceless",
"dependency",
"type",
"other",
] as const

interface SortGroup {
order: number
type?: "default" | "sourceless" | "dependency" | "other"
type?: (typeof sortGroupsTypes)[number]
regex?: string
}

Expand Down Expand Up @@ -46,6 +54,12 @@ function getSortGroup(sortGroups: SortGroup[], node: Export) {
if (!isDefaultExport && !node.source) return order
break

case "type": {
const { exportKind } = node as { exportKind?: string }
if (exportKind === "type") return order
break
}

case "dependency":
if (isResolved(source)) return order
break
Expand Down Expand Up @@ -127,7 +141,7 @@ export default {
type: "object",
properties: {
type: {
enum: ["default", "sourceless", "dependency", "other"],
enum: sortGroupsTypes,
},
regex: {
type: "string",
Expand Down
12 changes: 10 additions & 2 deletions src/rules/imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ import {
TypeOrder,
} from "../utils.js"

const sortGroupsTypes = ["side-effect", "dependency", "type", "other"] as const

interface SortGroup {
order: number
type?: "dependency" | "side-effect" | "other"
type?: (typeof sortGroupsTypes)[number]
regex?: string
}

Expand All @@ -44,6 +46,12 @@ function getSortGroup(sortGroups: SortGroup[], node: ImportDeclaration) {
if (!node.specifiers.length) return order
break

case "type": {
const { importKind } = node as { importKind?: string }
if (importKind === "type") return order
break
}

case "dependency":
if (isResolved(source)) return order
break
Expand Down Expand Up @@ -226,7 +234,7 @@ export default {
type: "object",
properties: {
type: {
enum: ["side-effect", "dependency", "other"],
enum: sortGroupsTypes,
},
regex: {
type: "string",
Expand Down

0 comments on commit 6e98c60

Please sign in to comment.