diff --git a/README.md b/README.md index dca1001f..9c29388f 100644 --- a/README.md +++ b/README.md @@ -240,6 +240,22 @@ import './polyfills'; import foo from 'foo' ``` +#### `importOrderImportAttributesKeyword` + +**type**: `'assert' | 'with' | 'with-legacy'` + +The import attributes/assertions syntax: +- `with`: `import "..." with { type: "json" }` +- `assert`: `import "..." assert { type: "json" }` +- `with-legacy`: `import "..." with type: "json"`. + +```json + "importOrderImportAttributesKeyword": 'with' +``` + +_Default behavior:_ When not specified, @babel/generator will try to match the style in the input code based on the AST shape. + + ### How does import sort work ? The plugin extracts the imports which are defined in `importOrder`. These imports are considered as _local imports_. diff --git a/package.json b/package.json index a085337c..bb0e5b48 100644 --- a/package.json +++ b/package.json @@ -76,5 +76,8 @@ "svelte": { "optional": true } + }, + "resolutions": { + "@types/babel__generator": "7.6.8" } } diff --git a/src/index.ts b/src/index.ts index f36a98b6..0afcba60 100644 --- a/src/index.ts +++ b/src/index.ts @@ -57,6 +57,12 @@ const options = { default: true, description: 'Should side effects be sorted?', }, + importOrderImportAttributesKeyword: { + type: 'string', + category: 'Global', + default: 'with', + description: 'Provide a keyword for import attributes', + } }; module.exports = { diff --git a/src/preprocessors/preprocessor.ts b/src/preprocessors/preprocessor.ts index bd0b4099..716212ec 100644 --- a/src/preprocessors/preprocessor.ts +++ b/src/preprocessors/preprocessor.ts @@ -17,6 +17,7 @@ export function preprocessor(code: string, options: PrettierOptions) { importOrderGroupNamespaceSpecifiers, importOrderSortSpecifiers, importOrderSideEffects, + importOrderImportAttributesKeyword, } = options; const parserOptions: ParserOptions = { @@ -46,5 +47,7 @@ export function preprocessor(code: string, options: PrettierOptions) { importOrderSideEffects, }); - return getCodeFromAst(allImports, directives, code, interpreter); + return getCodeFromAst(allImports, directives, code, interpreter, { + importOrderImportAttributesKeyword, + }); } diff --git a/src/utils/get-code-from-ast.ts b/src/utils/get-code-from-ast.ts index 8e8fd1dc..740afaf7 100644 --- a/src/utils/get-code-from-ast.ts +++ b/src/utils/get-code-from-ast.ts @@ -4,6 +4,7 @@ import { Directive, InterpreterDirective, Statement, file } from '@babel/types'; import { newLineCharacters } from '../constants'; import { getAllCommentsFromNodes } from './get-all-comments-from-nodes'; import { removeNodesFromOriginalCode } from './remove-nodes-from-original-code'; +import { PrettierOptions } from '../types'; /** * This function generate a code string from the passed nodes. @@ -15,6 +16,7 @@ export const getCodeFromAst = ( directives: Directive[], originalCode: string, interpreter?: InterpreterDirective | null, + options?: Pick ) => { const allCommentsFromImports = getAllCommentsFromNodes(nodes); @@ -49,7 +51,7 @@ export const getCodeFromAst = ( }, }); - const { code } = generate(newAST); + const { code } = generate(newAST, { importAttributesKeyword: options?.importOrderImportAttributesKeyword }); return ( code.replace( diff --git a/tests/ImportsWithAttributesKeyword/__snapshots__/ppsi.spec.js.snap b/tests/ImportsWithAttributesKeyword/__snapshots__/ppsi.spec.js.snap new file mode 100644 index 00000000..7972df24 --- /dev/null +++ b/tests/ImportsWithAttributesKeyword/__snapshots__/ppsi.spec.js.snap @@ -0,0 +1,34 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`imports-with-attributes-keyword.ts - typescript-verify: imports-with-attributes-keyword.ts 1`] = ` +// I am top level comment in this file. +import thirdParty0 from "third-party0"; +import something3 from "@core/something3"; +import thirdDisco0 from "third-disco0"; +import otherthing3 from "@core/otherthing3"; +import { a } from "b" with { type: "json" }; + +import anotherSameLevelRelativePath3 from "./anotherSameLevelRelativePath3"; +import something0 from "@core/something0"; + +import { b } from "r" with { type: "json" }; + + +function add(a,b) { + return a + b; +}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// I am top level comment in this file. +import { a } from "b" with { type: "json" }; +import { b } from "r" with { type: "json" }; +import thirdDisco0 from "third-disco0"; +import thirdParty0 from "third-party0"; +import otherthing3 from "@core/otherthing3"; +import something0 from "@core/something0"; +import something3 from "@core/something3"; +import anotherSameLevelRelativePath3 from "./anotherSameLevelRelativePath3"; + +function add(a, b) { + return a + b; +} + +`; diff --git a/tests/ImportsWithAttributesKeyword/imports-with-attributes-keyword.ts b/tests/ImportsWithAttributesKeyword/imports-with-attributes-keyword.ts new file mode 100644 index 00000000..afc468d7 --- /dev/null +++ b/tests/ImportsWithAttributesKeyword/imports-with-attributes-keyword.ts @@ -0,0 +1,16 @@ +// I am top level comment in this file. +import thirdParty0 from "third-party0"; +import something3 from "@core/something3"; +import thirdDisco0 from "third-disco0"; +import otherthing3 from "@core/otherthing3"; +import { a } from "b" with { type: "json" }; + +import anotherSameLevelRelativePath3 from "./anotherSameLevelRelativePath3"; +import something0 from "@core/something0"; + +import { b } from "r" with { type: "json" }; + + +function add(a,b) { + return a + b; +} \ No newline at end of file diff --git a/tests/ImportsWithAttributesKeyword/ppsi.spec.js b/tests/ImportsWithAttributesKeyword/ppsi.spec.js new file mode 100644 index 00000000..243d5ae3 --- /dev/null +++ b/tests/ImportsWithAttributesKeyword/ppsi.spec.js @@ -0,0 +1,7 @@ +run_spec(__dirname, ["typescript"], { + importOrder: ['^@core/(.*)$', '^@server/(.*)', '^@ui/(.*)$', '^[./]'], + importOrderSeparation: false, + importOrderSideEffects: false, + importOrderParserPlugins: ['typescript'], + importOrderImportAttributesKeyword: 'with', +}); diff --git a/types/index.d.ts b/types/index.d.ts index 4c5f02f3..46bc56ee 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -92,6 +92,19 @@ used to order imports within each match group. * @default ["typescript", "jsx"] */ importOrderParserPlugins?: ImportOrderParserPlugin[]; + + + /** + * The import attributes/assertions syntax to use. "with" for import "..." with { type: "json" }, + * "assert" for import "..." assert { type: "json" }, and "with-legacy" for import "..." with type: "json". + * + * ``` + * "importOrderImportAttributesKeyword": 'with', + * ``` + * + * _Default behavior:_ When not specified, @babel/generator will try to match the style in the input code based on the AST shape. + */ + importOrderImportAttributesKeyword?: 'assert' | 'with' | 'with-legacy'; } export type PrettierConfig = PluginConfig & Config; diff --git a/yarn.lock b/yarn.lock index c8c3fa2f..6d0d1548 100644 --- a/yarn.lock +++ b/yarn.lock @@ -91,7 +91,12 @@ "@babel/helper-validator-identifier" "^7.25.9" "@babel/traverse" "^7.25.9" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.25.9", "@babel/helper-plugin-utils@^7.8.0": +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0": + version "7.16.7" + resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz" + integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== + +"@babel/helper-plugin-utils@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz#9cbdd63a9443a2c92a725cca7ebca12cc8dd9f46" integrity sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw== @@ -570,7 +575,7 @@ "@types/babel__template" "*" "@types/babel__traverse" "*" -"@types/babel__generator@*": +"@types/babel__generator@*", "@types/babel__generator@7.6.8": version "7.6.8" resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==