diff --git a/changelog_unreleased/javascript/15757.md b/changelog_unreleased/javascript/15757.md new file mode 100644 index 000000000000..f7bab6bb14c0 --- /dev/null +++ b/changelog_unreleased/javascript/15757.md @@ -0,0 +1,16 @@ +#### Keep empty import attributes and assertions (#15757 by @fisker) + + +```js +// Input +import foo from "foo" with {}; +import bar from "bar" assert {}; + +// Prettier stable +import foo from "foo"; +import bar from "bar"; + +// Prettier main +import foo from "foo" with {}; +import bar from "bar" assert {}; +``` diff --git a/src/language-js/print/module.js b/src/language-js/print/module.js index 2b3de04325e4..65d37cf4e701 100644 --- a/src/language-js/print/module.js +++ b/src/language-js/print/module.js @@ -249,6 +249,24 @@ function shouldPrintSpecifiers(node, options) { return text.trimEnd().endsWith("from"); } +function shouldPrintAttributes(node, options) { + if (!node.source) { + return false; + } + + if (isNonEmptyArray(node.attributes) || isNonEmptyArray(node.assertions)) { + return true; + } + + const text = getTextWithoutComments( + options, + locEnd(node.source), + locEnd(node), + ).trimStart(); + + return text.startsWith("with") || text.startsWith("assert"); +} + function getTextWithoutComments(options, start, end) { let text = options.originalText.slice(start, end); @@ -282,15 +300,20 @@ function getImportAttributesOrAssertionsKeyword(node, options) { if ( // Babel parser add this property to indicate the keyword is `assert` node.extra?.deprecatedAssertSyntax || - !isNonEmptyArray(node.attributes) + (isNonEmptyArray(node.assertions) && !isNonEmptyArray(node.attributes)) ) { return "assert"; } + if (!isNonEmptyArray(node.assertions) && isNonEmptyArray(node.attributes)) { + return "with"; + } + + const firstAttribute = node.attributes?.[0] ?? node.assertions?.[0]; const textBetweenSourceAndAttributes = getTextWithoutComments( options, locEnd(node.source), - locStart(node.attributes[0]), + firstAttribute ? locStart(firstAttribute) : locEnd(node), ); if (textBetweenSourceAndAttributes.trimStart().startsWith("assert")) { @@ -307,24 +330,33 @@ function getImportAttributesOrAssertionsKeyword(node, options) { function printImportAttributes(path, options, print) { const { node } = path; + if (!shouldPrintAttributes(node, options)) { + return ""; + } + + const keyword = getImportAttributesOrAssertionsKeyword(node, options); + /** @type{Doc[]} */ + const parts = [` ${keyword} {`]; + const property = isNonEmptyArray(node.attributes) ? "attributes" : isNonEmptyArray(node.assertions) ? "assertions" : undefined; + if (property) { + if (options.bracketSpacing) { + parts.push(" "); + } - if (!property) { - return ""; + parts.push(join(", ", path.map(print, property))); + + if (options.bracketSpacing) { + parts.push(" "); + } } + parts.push("}"); - const keyword = getImportAttributesOrAssertionsKeyword(node, options); - return [ - ` ${keyword} {`, - options.bracketSpacing ? " " : "", - join(", ", path.map(print, property)), - options.bracketSpacing ? " " : "", - "}", - ]; + return parts; } function printModuleSpecifier(path, options, print) { diff --git a/tests/format/js/import-assertions/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/import-assertions/__snapshots__/jsfmt.spec.js.snap index cd510baf08f7..d966610d212b 100644 --- a/tests/format/js/import-assertions/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/js/import-assertions/__snapshots__/jsfmt.spec.js.snap @@ -86,12 +86,12 @@ import * as bar from "bar.json" assert { } import * as baz from "baz.json" assert { /* comment */ } =====================================output===================================== export * as foo from "foo.json"; -export * as bar from "bar.json"; -export * as baz from "baz.json" /* comment */; +export * as bar from "bar.json" assert {}; +export * as baz from "baz.json" /* comment */ assert {}; import * as foo from "foo.json"; -import * as bar from "bar.json"; -import * as baz from "baz.json" /* comment */; +import * as bar from "bar.json" assert {}; +import * as baz from "baz.json" /* comment */ assert {}; ================================================================================ `; diff --git a/tests/format/js/import-assertions/bracket-spacing/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/import-assertions/bracket-spacing/__snapshots__/jsfmt.spec.js.snap index 884bb803b97e..1908fac6b88f 100644 --- a/tests/format/js/import-assertions/bracket-spacing/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/js/import-assertions/bracket-spacing/__snapshots__/jsfmt.spec.js.snap @@ -69,7 +69,7 @@ printWidth: 80 =====================================input====================================== export * as bar from "bar.json" assert { } =====================================output===================================== -export * as bar from "bar.json"; +export * as bar from "bar.json" assert {}; ================================================================================ `; diff --git a/tests/format/js/import-attributes/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/import-attributes/__snapshots__/jsfmt.spec.js.snap index f08aa12769c1..db49f25eca14 100644 --- a/tests/format/js/import-attributes/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/js/import-attributes/__snapshots__/jsfmt.spec.js.snap @@ -87,12 +87,12 @@ import * as baz from "baz.json" with { /* comment */ } =====================================output===================================== export * as foo from "foo.json"; -export * as bar from "bar.json"; -export * as baz from "baz.json" /* comment */; +export * as bar from "bar.json" with {}; +export * as baz from "baz.json" /* comment */ with {}; import * as foo from "foo.json"; -import * as bar from "bar.json"; -import * as baz from "baz.json" /* comment */; +import * as bar from "bar.json" with {}; +import * as baz from "baz.json" /* comment */ with {}; ================================================================================ `; diff --git a/tests/format/js/import-attributes/bracket-spacing/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/import-attributes/bracket-spacing/__snapshots__/jsfmt.spec.js.snap index 18d759c642bd..67936c32d946 100644 --- a/tests/format/js/import-attributes/bracket-spacing/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/js/import-attributes/bracket-spacing/__snapshots__/jsfmt.spec.js.snap @@ -69,7 +69,7 @@ printWidth: 80 =====================================input====================================== export * as bar from "bar.json" with { } =====================================output===================================== -export * as bar from "bar.json"; +export * as bar from "bar.json" with {}; ================================================================================ `;