diff --git a/changelog_unreleased/angular/15926.md b/changelog_unreleased/angular/15926.md new file mode 100644 index 000000000..15a7d1bba --- /dev/null +++ b/changelog_unreleased/angular/15926.md @@ -0,0 +1,42 @@ +#### Respect `trailingComma` in Angular templates (#15926 by @fisker) + +If you are using an old version of Angular doesn't support trailing comma, make sure add + +```yaml +overrides: + - files: "" + options: + trailingComma: none +``` + +to your `.prettierrc` file. + + +```jsx +// Input +
+ +// Prettier stable +
+ +// Prettier main +
+``` diff --git a/src/language-html/embed.js b/src/language-html/embed.js index 3a5924a92..8a339f39a 100644 --- a/src/language-html/embed.js +++ b/src/language-html/embed.js @@ -114,7 +114,6 @@ function embed(path, options) { }; if (options.parser === "angular") { textToDocOptions.parser = "__ng_interpolation"; - textToDocOptions.trailingComma = "none"; } else if (options.parser === "vue") { textToDocOptions.parser = isVueSfcWithTypescriptScript( path, diff --git a/src/language-html/embed/angular-attributes.js b/src/language-html/embed/angular-attributes.js index 8a21a1d2f..431c66ff9 100644 --- a/src/language-html/embed/angular-attributes.js +++ b/src/language-html/embed/angular-attributes.js @@ -18,11 +18,7 @@ function createAngularPrinter({ parser }) { formatAttributeValue( getUnescapedAttributeValue(path.node), textToDoc, - { - parser, - // angular does not allow trailing comma - trailingComma: "none", - }, + { parser }, shouldHugJsExpression, ); } diff --git a/src/language-html/embed/angular-control-flow-block-parameters.js b/src/language-html/embed/angular-control-flow-block-parameters.js index 46750cd5d..c12b49964 100644 --- a/src/language-html/embed/angular-control-flow-block-parameters.js +++ b/src/language-html/embed/angular-control-flow-block-parameters.js @@ -24,7 +24,6 @@ function printAngularControlFlowBlockParameters( { parser: "__ng_directive", __isInHtmlAttribute: false, - trailingComma: "none", }, shouldHugJsExpression, ); diff --git a/src/language-html/embed/angular-interpolation.js b/src/language-html/embed/angular-interpolation.js index 53caceeb8..2fc953739 100644 --- a/src/language-html/embed/angular-interpolation.js +++ b/src/language-html/embed/angular-interpolation.js @@ -19,7 +19,6 @@ async function printAngularInterpolation(text, textToDoc) { await formatAttributeValue(part, textToDoc, { parser: "__ng_interpolation", __isInHtmlInterpolation: true, // to avoid unexpected `}}` - trailingComma: "none", }), ]), line, diff --git a/src/language-js/print/call-arguments.js b/src/language-js/print/call-arguments.js index ca6b65c0f..affc3320c 100644 --- a/src/language-js/print/call-arguments.js +++ b/src/language-js/print/call-arguments.js @@ -82,7 +82,12 @@ function printCallArguments(path, options, print) { const isDynamicImport = node.type === "ImportExpression" || node.callee.type === "Import"; const maybeTrailingComma = - !isDynamicImport && shouldPrintComma(options, "all") ? "," : ""; + // Angular does not allow trailing comma + !options.parser.startsWith("__ng_") && + !isDynamicImport && + shouldPrintComma(options, "all") + ? "," + : ""; function allArgsBrokenOut() { return group( diff --git a/tests/format/angular/angular/__snapshots__/format.test.js.snap b/tests/format/angular/angular/__snapshots__/format.test.js.snap index f6aa3e031..f257aeded 100644 --- a/tests/format/angular/angular/__snapshots__/format.test.js.snap +++ b/tests/format/angular/angular/__snapshots__/format.test.js.snap @@ -451,10 +451,10 @@ printWidth: 80 [target]="{a: 1}" [target]="{a: 1}" [target]="{ - trailingComma: 'notAllowed' + trailingComma: 'notAllowed', }" [target]="[ - longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong + longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong, ]" [target]="true" [target]="undefined" @@ -540,14 +540,14 @@ printWidth: 80 listRow.NextScheduledSendStatus == 3 " [target]="{ - longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true + longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true, }" [error]="'We couldn\\\\\\'t find anything with that name.'" *ngIf="form.controls.details?.controls.amount?.errors.min" [ngClass]="{ 'btn-success': (dialog$ | async).level === dialogLevelEnum.SUCCESS, 'btn-warning': (dialog$ | async).level === dialogLevelEnum.WARNING, - 'btn-svg': (dialog$ | async).level === dialogLevelEnum.DANGER + 'btn-svg': (dialog$ | async).level === dialogLevelEnum.DANGER, }" [stickout]="+toolAssembly.stickoutMm" test="{{ 'test' | translate }}" @@ -730,10 +730,10 @@ printWidth: 80 [target]="{ a: 1 }" [target]="{ a: 1 }" [target]="{ - trailingComma: 'notAllowed' + trailingComma: 'notAllowed', }" [target]="[ - longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong + longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong, ]" [target]="true" [target]="undefined" @@ -819,14 +819,14 @@ printWidth: 80 listRow.NextScheduledSendStatus == 3 " [target]="{ - longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true + longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true, }" [error]="'We couldn\\\\\\'t find anything with that name.'" *ngIf="form.controls.details?.controls.amount?.errors.min" [ngClass]="{ 'btn-success': (dialog$ | async).level === dialogLevelEnum.SUCCESS, 'btn-warning': (dialog$ | async).level === dialogLevelEnum.WARNING, - 'btn-svg': (dialog$ | async).level === dialogLevelEnum.DANGER + 'btn-svg': (dialog$ | async).level === dialogLevelEnum.DANGER, }" [stickout]="+toolAssembly.stickoutMm" test="{{ 'test' | translate }}" @@ -1053,20 +1053,20 @@ printWidth: 1 ] " [target]="[ - 1 + 1, ]" [target]="{ - a: 1 + a: 1, }" [target]="{ - a: 1 + a: 1, }" [target]="{ trailingComma: - 'notAllowed' + 'notAllowed', }" [target]="[ - longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong + longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong, ]" [target]=" true @@ -1210,7 +1210,7 @@ printWidth: 1 1, 2, 3, - 666666666666666666666666666666666666 + 666666666666666666666666666666666666, ]; let i = index " @@ -1320,7 +1320,7 @@ printWidth: 1 3 " [target]="{ - longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true + longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true, }" [error]=" 'We couldn\\\\\\'t find anything with that name.' @@ -1355,7 +1355,7 @@ printWidth: 1 | async ) .level === - dialogLevelEnum.DANGER + dialogLevelEnum.DANGER, }" [stickout]=" +toolAssembly.stickoutMm @@ -1636,10 +1636,10 @@ trailingComma: "es5" [target]="{ a: 1 }" [target]="{ a: 1 }" [target]="{ - trailingComma: 'notAllowed' + trailingComma: 'notAllowed', }" [target]="[ - longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong + longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong, ]" [target]="true" [target]="undefined" @@ -1725,14 +1725,14 @@ trailingComma: "es5" listRow.NextScheduledSendStatus == 3 " [target]="{ - longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true + longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true, }" [error]="'We couldn\\\\\\'t find anything with that name.'" *ngIf="form.controls.details?.controls.amount?.errors.min" [ngClass]="{ 'btn-success': (dialog$ | async).level === dialogLevelEnum.SUCCESS, 'btn-warning': (dialog$ | async).level === dialogLevelEnum.WARNING, - 'btn-svg': (dialog$ | async).level === dialogLevelEnum.DANGER + 'btn-svg': (dialog$ | async).level === dialogLevelEnum.DANGER, }" [stickout]="+toolAssembly.stickoutMm" test="{{ 'test' | translate }}" @@ -3395,21 +3395,21 @@ printWidth: 1
{{ [ - 1 + 1, ] }}
{{ { - a: 1 + a: 1, } }}
{{ { - a: 1 + a: 1, } }}
@@ -3599,8 +3599,8 @@ printWidth: 1 | translate : { count: - array.length - }) + array.length, + }), } }}

@@ -3609,7 +3609,7 @@ printWidth: 1 { a: 1 + - {} + {}, } }}

@@ -3618,14 +3618,14 @@ printWidth: 1 { a: a === - {} + {}, } }}

{{ { - a: !{} + a: !{}, } }}

@@ -3634,7 +3634,7 @@ printWidth: 1 { a: a ? b - : {} + : {}, } }}

@@ -8391,7 +8391,7 @@ can be found in the LICENSE file at http://angular.io/license
@@ -9371,7 +9371,7 @@ bindon-ngModel [ngClass]="{ bad: false, curly: true, - special: true + special: true, }" > Curly diff --git a/tests/format/angular/trailing-comma/__snapshots__/format.test.js.snap b/tests/format/angular/trailing-comma/__snapshots__/format.test.js.snap new file mode 100644 index 000000000..4f734d6a6 --- /dev/null +++ b/tests/format/angular/trailing-comma/__snapshots__/format.test.js.snap @@ -0,0 +1,622 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`trailing-comma.html - {"trailingComma":"all"} format 1`] = ` +====================================options===================================== +parsers: ["angular"] +printWidth: 80 +trailingComma: "all" + | printWidth +=====================================input====================================== +
+ +=====================================output===================================== +
+ +================================================================================ +`; + +exports[`trailing-comma.html - {"trailingComma":"es5"} format 1`] = ` +====================================options===================================== +parsers: ["angular"] +printWidth: 80 +trailingComma: "es5" + | printWidth +=====================================input====================================== +
+ +=====================================output===================================== +
+ +================================================================================ +`; + +exports[`trailing-comma.html - {"trailingComma":"none"} format 1`] = ` +====================================options===================================== +parsers: ["angular"] +printWidth: 80 +trailingComma: "none" + | printWidth +=====================================input====================================== +
+ +=====================================output===================================== +
+ +================================================================================ +`; diff --git a/tests/format/angular/trailing-comma/format.test.js b/tests/format/angular/trailing-comma/format.test.js new file mode 100644 index 000000000..08fb6de70 --- /dev/null +++ b/tests/format/angular/trailing-comma/format.test.js @@ -0,0 +1,3 @@ +runFormatTest(import.meta, ["angular"], { trailingComma: "none" }); +runFormatTest(import.meta, ["angular"], { trailingComma: "es5" }); +runFormatTest(import.meta, ["angular"], { trailingComma: "all" }); diff --git a/tests/format/angular/trailing-comma/trailing-comma.html b/tests/format/angular/trailing-comma/trailing-comma.html new file mode 100644 index 000000000..7e40dc499 --- /dev/null +++ b/tests/format/angular/trailing-comma/trailing-comma.html @@ -0,0 +1,56 @@ +