Skip to content

Commit

Permalink
Add support for import attributes (#174)
Browse files Browse the repository at this point in the history
There are three styles of import assertions/attributes that have been
proposed over the years and made it to various stages of TC-39. Here's a
bit of
[history](https://github.com/tc39/proposal-import-attributes#history):

1) `import x from 'x' with type: "json"` - original proposal, made it to
stage 2
2) `import x from 'x' assert { type: 'json' };` - import "assertion",
got to stage 3, then found problems
3) `import x from 'x' with { type: 'json' };` - import "attribute",
current proposal, stage 3

Babel only supports these with the use of a parser plugin, either
`importAttributes` or `importAssertions`. Also, babel/generator has to
be told which style to generate. Upstream has a PR,
https://github.com/trivago/prettier-plugin-sort-imports/pull/273/files,
which adds another user-level option to control this. Instead, I've
taken the stance here that we should only generate the latest "import
attribute" style code. So, not only does this PR add support for import
attributes/assertions, this has the side-effect of converting deprecated
import assertions to import attributes. Maybe there's some reason
someone would want to stick with the old style, but I can't think of
one, and I personally would appreciate getting updated to the latest
format.
  • Loading branch information
IanVS authored Jun 25, 2024
1 parent 54cd979 commit 920639a
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 2 deletions.
25 changes: 25 additions & 0 deletions src/utils/__tests__/get-code-from-ast.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,28 @@ import z from "z";
`,
);
});

test('handles import attributes and assertions, converting to attributes when necessary', async () => {
const code = `import z from 'z';
import g from 'g' with { type: 'json' };
import c from 'c' assert { type: 'json' };
`;
const importNodes = getImportNodes(code, {
plugins: [['importAttributes', { deprecatedAssertSyntax: true }]],
});
const sortedNodes = getSortedNodes(importNodes, {
importOrder: defaultImportOrder,
importOrderCombineTypeAndValueImports: true,
});
const formatted = getCodeFromAst({
nodesToOutput: sortedNodes,
originalCode: code,
directives: [],
});
expect(await format(formatted, { parser: 'babel' })).toEqual(
`import c from "c" with { type: "json" };
import g from "g" with { type: "json" };
import z from "z";
`,
);
});
2 changes: 1 addition & 1 deletion src/utils/get-code-from-ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export const getCodeFromAst = ({
},
});

const { code } = generate(newAST);
const { code } = generate(newAST, { importAttributesKeyword: 'with' });

const replacedCode = code.replace(injectNewlinesRegex, newLineCharacters);

Expand Down
13 changes: 13 additions & 0 deletions tests/Babel/__snapshots__/ppsi.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`imports-with-assertions.ts - babel-verify > imports-with-assertions.ts 1`] = `
import z from 'z-assert' assert { type: 'json' };
import x from 'x-with' with { type: 'json' };
// import y from 'y-legacy' with type: "json" // <-- this format is from a very old proposal, and is not supported
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import x from "x-with" with { type: "json" };
import z from "z-assert" with { type: "json" };
// import y from 'y-legacy' with type: "json" // <-- this format is from a very old proposal, and is not supported
`;

exports[`imports-with-comments.js - babel-verify > imports-with-comments.js 1`] = `
// I am top level comment in this file.
Expand Down
4 changes: 4 additions & 0 deletions tests/Babel/imports-with-assertions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import z from 'z-assert' assert { type: 'json' };
import x from 'x-with' with { type: 'json' };

// import y from 'y-legacy' with type: "json" // <-- this format is from a very old proposal, and is not supported
1 change: 1 addition & 0 deletions tests/Babel/ppsi.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ import {run_spec} from '../../test-setup/run_spec';

run_spec(__dirname, ["babel"], {
importOrder: [ "<THIRD_PARTY_MODULES>", '^@core/(.*)$', '^@server/(.*)', '^@ui/(.*)$', '^[./]'],
importOrderParserPlugins : ['[\"importAttributes\", {\"deprecatedAssertSyntax\": true}]'],
});
13 changes: 13 additions & 0 deletions tests/Typescript/__snapshots__/ppsi.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,19 @@ export class AppComponent extends BaseComponent {
`;

exports[`imports-with-assertions.ts - typescript-verify > imports-with-assertions.ts 1`] = `
import z from 'z-assert' assert { type: 'json' };
import x from 'x-with' with { type: 'json' };
// import y from 'y-legacy' with type: "json" // <-- this format is from a very old proposal, and is not supported
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import x from "x-with" with { type: "json" };
import z from "z-assert" with { type: "json" };
// import y from 'y-legacy' with type: "json" // <-- this format is from a very old proposal, and is not supported
`;

exports[`imports-with-comments.ts - typescript-verify > imports-with-comments.ts 1`] = `
import z from 'z';
import { isEmpty } from "lodash-es";
Expand Down
4 changes: 4 additions & 0 deletions tests/Typescript/imports-with-assertions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import z from 'z-assert' assert { type: 'json' };
import x from 'x-with' with { type: 'json' };

// import y from 'y-legacy' with type: "json" // <-- this format is from a very old proposal, and is not supported
2 changes: 1 addition & 1 deletion tests/Typescript/ppsi.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ import {run_spec} from '../../test-setup/run_spec';

run_spec(__dirname, ["typescript"], {
importOrder: ['^@core/(.*)$', '^@server/(.*)', '^@ui/(.*)$', '^[./]'],
importOrderParserPlugins : ['typescript', 'jsx', 'decorators-legacy', 'classProperties'],
importOrderParserPlugins : ['typescript', 'jsx', 'decorators-legacy', 'classProperties', '[\"importAttributes\", {\"deprecatedAssertSyntax\": true}]'],
});

0 comments on commit 920639a

Please sign in to comment.