feat: import grouping - #784
Conversation
…headers to file start
… redundant state)
…sit when actually implemented)
b231628 to
a8c550e
Compare
|
Huge thanks for working on this! 🙌 I've tried it out on one of our codebases which has 302 TypeScript files. It didn't want to change anything! 🎉 Here is my config: "plugins": [
"https://locousercontent.com/rhSXZADUEDZdBirieW5rdHdoHCfc0TyMUQoCGA4NGC4YKVm11ojTer5kN9R9XyYK/original.wasm"
],
"typescript": {
"module.importGroups": [
{ "match": "builtin" },
{ "match": "external" },
{ "match": "parent" },
{ "match": ["sibling", "index"] }
],
"module.typeImports": "interleave",
"module.builtinsRuntime": "node"
}And this is the Biome config that we used before: "organizeImports": {
"level": "on",
"options": {
"groups": [
[":NODE:", ":BUN:"],
":BLANK_LINE:",
[":URL:", ":PACKAGE_WITH_PROTOCOL:", ":PACKAGE:", ":ALIAS:"],
":BLANK_LINE:",
"../**",
":BLANK_LINE:",
"./**"
]
}
}( I built the WASM file from commit a8c550e, and the resulting SHA-384 hash is |
|
@dsherret if I had to pick one PR that I would love to get merged, it would be this one. 😅 thanks! |
perf: speed up import sorting
|
I hope to have that approved soon! Thanks for this, @todor-a. |
|
hey, @dsherret. i see you are updating this repo, saw the new site as well, looks awesome. i was wondering if we can go through with this pr? thanks a lot! |
Closes #493.
Transparency note: This PR was prepared with AI assistance (Claude).
Adds ESLint-
import/order-style import grouping to dprint-plugin-typescript: classify import declarations, reorder across the import block to match a user-declared group order, and insert exactly one blank line between groups.Configuration
Four new keys under
module.*:{ "module.importGroups": [ { "match": "builtin" }, { "match": "external" }, { "match": "parent" }, { "match": ["sibling", "index"] } ], "module.typeImports": "separate", // or "interleave" "module.builtinsRuntime": "node" // or "deno" | "bun" | "none" }Empty
module.importGroups(default) disables the feature; output is byte-identical to the previous release.matchformsbuiltin | external | parent | sibling | index | type | unknown{ "pattern": "<glob>" }matched against the literal import sourceFirst-match-wins across the list.
Built-in categories per runtime
builtinmatchnode(default)node:*prefix or hardcoded Node 22 LTS core listdenonode:*prefix onlybunnode:*,bun:*, or Node core listnoneWhat works
@app/**, etc.)unknowncatch-all (implicit at end, or explicit anywhere)"separate"(default, own category) or"interleave"import "./polyfill") act as barriers — preserve position; imports either side grouped independently// @ts-check, etc.) pinned to file startmodule.sortImportDeclarationsfor within-group orderimportDeclaration.sortNamedImportsfor specifier sortformat_twice: truein the existing spec harness)Tests
16 new spec files under
tests/specs/declarations/import/ImportGroups_*.txtcovering: basic reorder, sort variants, type-imports both modes, all four runtimes, pattern matchers + first-match-wins, side-effect barriers, header comments, multi-chunk barriers, import attributes (with { type: "json" }),.d.tsfiles + nesteddeclare module, knob interactions, implicit/explicitunknown.Plus unit tests covering classifier, partition, resolved-config compile, and diagnostics.
Full suite: 666 specs pass (660 pre-existing untouched + 16 new files / 14 sub-tests), 61 lib tests pass. Feature-off output byte-identical to baseline.
Known limitations (documented in README)
// dprint-ignoreon an import currently reorders like any other; barrier handling is a follow-up.require(...), dynamicimport(), TSimport = require()not reordered.declare module "..."bodies not classified.ESLint
import/ordermigrationgroupsmodule.importGroups(strings; nested arrays merge)pathGroups{ "pattern": "..." }entries placed positionallynewlines-between: "always"newlines-between: "never"/"ignore"module.importGroupsalphabetize.order: "asc"module.sortImportDeclarationsalphabetize.order: "desc"