Skip to content

Commit a2aff34

Browse files
committed
feat: implement natural order comparison for duplicate exports and imports
1 parent 0d73639 commit a2aff34

File tree

5 files changed

+18
-4
lines changed

5 files changed

+18
-4
lines changed

packages/tsl-module/src/rules/no-duplicate-exports.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { type AST, defineRule } from "tsl";
22
import ts from "typescript";
33

4+
import { naturalCompare } from "../utils";
5+
46
export const messages = {
57
noDuplicateExports: (p: { source: string }) => `Duplicate export from module ${p.source}.`,
68
} as const;
@@ -75,7 +77,7 @@ function buildSuggestions(a: ReExportDeclaration, b: ReExportDeclaration) {
7577
&& ts.isNamedExports(b.exportClause): {
7678
const aElements = a.exportClause.elements.map((el) => el.getText());
7779
const bElements = b.exportClause.elements.map((el) => el.getText());
78-
const parts = Array.from(new Set([...aElements, ...bElements])).sort();
80+
const parts = Array.from(new Set([...aElements, ...bElements])).toSorted(naturalCompare);
7981
return [
8082
{
8183
message: "Merge duplicate exports",

packages/tsl-module/src/rules/no-duplicate-imports.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ test("no-duplicate-import", () => {
8181
{
8282
message: "Merge duplicate imports",
8383
output: tsx`
84-
import foo, { type bar, baz, type qux, quux } from 'module';\n
84+
import foo, { baz, quux, type bar, type qux } from 'module';\n
8585
import foo3, { corge } from 'module';
8686
`,
8787
},
@@ -94,7 +94,7 @@ test("no-duplicate-import", () => {
9494
{
9595
message: "Merge duplicate imports",
9696
output: tsx`
97-
import foo, { type bar, baz, corge } from 'module';
97+
import foo, { baz, corge, type bar } from 'module';
9898
import foo2, { type qux, quux } from 'module';\n
9999
`,
100100
},

packages/tsl-module/src/rules/no-duplicate-imports.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { unit } from "@let/eff";
22
import { P, match } from "ts-pattern";
33
import { type AST, defineRule } from "tsl";
44
import ts from "typescript";
5+
import { naturalCompare } from "../utils";
56

67
export const messages = {
78
noDuplicateImports: (p: { source: string }) => `Duplicate import from module ${p.source}.`,
@@ -135,7 +136,8 @@ function buildMergedImport(a: ImportInfo, b: ImportInfo): string {
135136
parts.push(`* as ${b.namespaceImport}`);
136137
}
137138
// Named imports
138-
const namedImports = Array.from(new Set([...a.namedImports, ...b.namedImports]));
139+
const namedImports = Array.from(new Set([...a.namedImports, ...b.namedImports])).toSorted(naturalCompare);
140+
// Construct named imports part
139141
if (namedImports.length > 0) {
140142
parts.push(`{ ${namedImports.join(", ")} }`);
141143
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./string";
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
* Compares two strings using natural order comparison.
3+
* @param a The first string to compare.
4+
* @param b The second string to compare.
5+
* @returns A negative number if `a` comes before `b`, a positive number if `a` comes after `b`, or `0` if they are equivalent.
6+
*/
7+
export function naturalCompare(a: string, b: string): number {
8+
return a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" });
9+
}

0 commit comments

Comments
 (0)