diff --git a/changelog_unreleased/angular/18593.md b/changelog_unreleased/angular/18593.md new file mode 100644 index 000000000..7d1ae4039 --- /dev/null +++ b/changelog_unreleased/angular/18593.md @@ -0,0 +1,25 @@ +#### Add support for multiple switch cases (#18593 by @fisker) + +This feature added in Angular v21.1. + + +```html + +@switch (foo) { + @case (0) + @case (1) { +
case 0 or 1
+ } +} + + +SyntaxError: Incomplete block "case". If you meant to write the @ character, you should use the "@" HTML entity instead. (2:3) + + +@switch (a) { + @case (0) + @case (1) { +
case 0 or 1
+ } +} +``` diff --git a/package.json b/package.json index 092a9b626..a61dbfbd1 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "acorn": "8.15.0", "acorn-jsx": "5.3.2", "angular-estree-parser": "15.2.0", - "angular-html-parser": "10.1.1", + "angular-html-parser": "10.3.0", "camelcase": "9.0.0", "ci-info": "4.3.1", "cjk-regex": "3.4.0", diff --git a/src/language-html/print/angular-control-flow-block.js b/src/language-html/print/angular-control-flow-block.js index e1d0919e0..5f9690403 100644 --- a/src/language-html/print/angular-control-flow-block.js +++ b/src/language-html/print/angular-control-flow-block.js @@ -24,18 +24,20 @@ function printAngularControlFlowBlock(path, options, print) { docs.push(" (", group(print("parameters")), ")"); } - docs.push(" {"); + if (!isSwitchFallthroughCase(node)) { + docs.push(" {"); - const shouldPrintCloseBracket = shouldCloseBlock(node); - if (node.children.length > 0) { - node.firstChild.hasLeadingSpaces = true; - node.lastChild.hasTrailingSpaces = true; - docs.push(indent([hardline, printChildren(path, options, print)])); - if (shouldPrintCloseBracket) { - docs.push(hardline, "}"); + const shouldPrintCloseBracket = shouldCloseBlock(node); + if (node.children.length > 0) { + node.firstChild.hasLeadingSpaces = true; + node.lastChild.hasTrailingSpaces = true; + docs.push(indent([hardline, printChildren(path, options, print)])); + if (shouldPrintCloseBracket) { + docs.push(hardline, "}"); + } + } else if (shouldPrintCloseBracket) { + docs.push("}"); } - } else if (shouldPrintCloseBracket) { - docs.push("}"); } return group(docs, { shouldBreak: true }); @@ -48,6 +50,19 @@ function shouldCloseBlock(node) { ); } +const isSwitchCaseBlock = (node) => + node?.kind === "angularControlFlowBlock" && + (node.name === "case" || node.name === "default"); +// https://github.com/angular/angular/commit/0ad3adc7c6d4094f1e3432a3f2e3bdc9862cb4fa#diff-77a6f285c6ea13d6644ef635e7495e71134d1141af2650cb9ae5631ff1f38bf2R263 +// https://github.com/prettier/prettier/issues/18563#issuecomment-3728354491 +function isSwitchFallthroughCase(node) { + return ( + isSwitchCaseBlock(node) && + node.endSourceSpan && + node.endSourceSpan.start.offset === node.endSourceSpan.end.offset + ); +} + function isPreviousBlockUnClosed(path) { const { previous } = path; return ( diff --git a/tests/format/angular/control-flow/__snapshots__/format.test.js.snap b/tests/format/angular/control-flow/__snapshots__/format.test.js.snap index 8e14f252c..57d672535 100644 --- a/tests/format/angular/control-flow/__snapshots__/format.test.js.snap +++ b/tests/format/angular/control-flow/__snapshots__/format.test.js.snap @@ -526,6 +526,120 @@ printWidth: 80 ================================================================================ `; +exports[`multiple-switch-cases.html format 1`] = ` +====================================options===================================== +parsers: ["angular"] +printWidth: 80 + | printWidth +=====================================input====================================== + + +@switch (expr) { + @case ( 'one') + @case ( 'two') { + {{ oneOrTwo()}} + } + @case ( 'three') { + {{ three()}} + } +} + + +@switch (expr) { + @case (1) + @case (2) { + {{oneOrTwo() }} + } + @case (3 ) + @default { + {{default() }} + } +} + +
+ {{message}} + @switch (value()) { + @case ( 0) @case(1 ) { + case 01 + } + @case (2) { + case 2 + } + @default { + default + } + } +
+ +@switch(a){@default @case(2){
default before case
}} +@switch(a){@case(1) @case(2){} @case(3) {
3
}} + +@switch(a){@case(1) @case(2) {}} + +=====================================output===================================== + + +@switch (expr) { + @case ("one") + @case ("two") { + {{ oneOrTwo() }} + } + @case ("three") { + {{ three() }} + } +} + +@switch (expr) { + @case (1) + @case (2) { + {{ oneOrTwo() }} + } + @case (3) + @default { + {{ default() }} + } +} + +
+ {{ message }} + @switch (value()) { + @case (0) + @case (1) { + case 01 + } + @case (2) { + case 2 + } + @default { + default + } + } +
+ +@switch (a) { + @default + @case (2) { +
default before case
+ } +} +@switch (a) { + @case (1) + @case (2) {} + @case (3) { +
3
+ } +} + +@switch (a) { + @case (1) + @case (2) { + + } +} + +================================================================================ +`; + exports[`switch.html format 1`] = ` ====================================options===================================== parsers: ["angular"] diff --git a/tests/format/angular/control-flow/multiple-switch-cases.html b/tests/format/angular/control-flow/multiple-switch-cases.html new file mode 100644 index 000000000..a56e8795d --- /dev/null +++ b/tests/format/angular/control-flow/multiple-switch-cases.html @@ -0,0 +1,43 @@ + + +@switch (expr) { + @case ( 'one') + @case ( 'two') { + {{ oneOrTwo()}} + } + @case ( 'three') { + {{ three()}} + } +} + + +@switch (expr) { + @case (1) + @case (2) { + {{oneOrTwo() }} + } + @case (3 ) + @default { + {{default() }} + } +} + +
+ {{message}} + @switch (value()) { + @case ( 0) @case(1 ) { + case 01 + } + @case (2) { + case 2 + } + @default { + default + } + } +
+ +@switch(a){@default @case(2){
default before case
}} +@switch(a){@case(1) @case(2){} @case(3) {
3
}} + +@switch(a){@case(1) @case(2) {}} diff --git a/yarn.lock b/yarn.lock index d95915db5..173adef45 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2861,10 +2861,10 @@ __metadata: languageName: node linkType: hard -"angular-html-parser@npm:10.1.1": - version: 10.1.1 - resolution: "angular-html-parser@npm:10.1.1" - checksum: 10/ad2995b43fb5c6465e7d1de5f6909f79e08486724997bb3417934c7bc0541e5604f563147a68e18b71eebba57dc61e184cf5d47451ed8b19a4b34d79cecb5f60 +"angular-html-parser@npm:10.3.0": + version: 10.3.0 + resolution: "angular-html-parser@npm:10.3.0" + checksum: 10/97078879db8f53fc9645d2cd8c748c9eb3770790ec96f249bd96e0ab9293f65506b7facd201c17f2f18884e82550f3c362972e7b3a5448b0e1fb2a6938e9ef4d languageName: node linkType: hard @@ -7518,7 +7518,7 @@ __metadata: acorn: "npm:8.15.0" acorn-jsx: "npm:5.3.2" angular-estree-parser: "npm:15.2.0" - angular-html-parser: "npm:10.1.1" + angular-html-parser: "npm:10.3.0" base64-arraybuffer-es6: "npm:3.1.0" browserslist: "npm:4.28.0" browserslist-to-esbuild: "npm:2.1.1"