diff --git a/packages/cli/package.json b/packages/cli/package.json
index 63651c3..ea35c1c 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -2,7 +2,7 @@
"name": "@ionic/angular-standalone-codemods",
"version": "0.0.7",
"dependencies": {
- "@angular-eslint/template-parser": "^16.1.2",
+ "@angular-eslint/template-parser": "^17.1.0",
"@clack/core": "^0.3.3",
"@clack/prompts": "^0.7.0",
"@ionic/utils-terminal": "^2.3.4",
diff --git a/packages/cli/src/angular/migrations/standalone/0002-import-standalone-component.test.ts b/packages/cli/src/angular/migrations/standalone/0002-import-standalone-component.test.ts
index e1b5ba4..68c19d8 100644
--- a/packages/cli/src/angular/migrations/standalone/0002-import-standalone-component.test.ts
+++ b/packages/cli/src/angular/migrations/standalone/0002-import-standalone-component.test.ts
@@ -579,4 +579,103 @@ describe("migrateComponents", () => {
);
});
});
+
+ it("should migrate components using inline templates with control flow", async () => {
+ const project = new Project({ useInMemoryFileSystem: true });
+
+ const component = `
+ import { Component } from "@angular/core";
+
+ @Component({
+ selector: 'my-component',
+ template: \`
+
+
+ My Component
+
+
+
+ @defer {
+
+ @for (item of [0, 1, 2]; track item) {
+
+ @if (1 === 1){ }
+ @switch (flag) {
+ @case(0) {
+ My Item
+ }
+ @default {
+ Your Item
+ }
+ }
+
+ }
+
+ } @loading (after 100ms; minimum 1s) {
+
+ }
+
+ \`,
+ standalone: true
+ })
+ export class MyComponent { flag = 1 }
+ `;
+
+ const componentSourceFile = project.createSourceFile(
+ "foo.component.ts",
+ dedent(component),
+ );
+
+ await migrateComponents(project, { dryRun: false });
+
+ expect(dedent(componentSourceFile.getText())).toBe(
+ dedent(`
+ import { Component } from "@angular/core";
+ import { addIcons } from "ionicons";
+ import { logoIonic, reloadOutline } from "ionicons/icons";
+ import { IonHeader, IonToolbar, IonTitle, IonContent, IonList, IonItem, IonIcon, IonLabel } from "@ionic/angular/standalone";
+
+ @Component({
+ selector: 'my-component',
+ template: \`
+
+
+ My Component
+
+
+
+ @defer {
+
+ @for (item of [0, 1, 2]; track item) {
+
+ @if (1 === 1){ }
+ @switch (flag) {
+ @case(0) {
+ My Item
+ }
+ @default {
+ Your Item
+ }
+ }
+
+ }
+
+ } @loading (after 100ms; minimum 1s) {
+
+ }
+
+ \`,
+ standalone: true,
+ imports: [IonHeader, IonToolbar, IonTitle, IonContent, IonList, IonItem, IonIcon, IonLabel]
+ })
+ export class MyComponent {
+ flag = 1
+
+ constructor() {
+ addIcons({ logoIonic, reloadOutline });
+ }
+ }
+ `),
+ );
+ });
});
diff --git a/packages/cli/src/angular/migrations/standalone/0002-import-standalone-component.ts b/packages/cli/src/angular/migrations/standalone/0002-import-standalone-component.ts
index 6109b56..10a8c72 100644
--- a/packages/cli/src/angular/migrations/standalone/0002-import-standalone-component.ts
+++ b/packages/cli/src/angular/migrations/standalone/0002-import-standalone-component.ts
@@ -325,6 +325,38 @@ function detectIonicComponentsAndIcons(htmlAsString: string, filePath: string) {
recursivelyFindIonicComponents(childNode);
}
}
+ } else if (node.type === "IfBlock") {
+ for (const branch of node.branches) {
+ for (const childNode of branch.children) {
+ recursivelyFindIonicComponents(childNode);
+ }
+ }
+ } else if (node.type === "ForLoopBlock") {
+ for (const childNode of node.children) {
+ recursivelyFindIonicComponents(childNode);
+ }
+ } else if (node.type === "SwitchBlock") {
+ for (const c of node.cases) {
+ for (const childNode of c.children) {
+ recursivelyFindIonicComponents(childNode);
+ }
+ }
+ } else if (node.type === "DeferredBlock") {
+ if (node.children) {
+ for (const childNode of node.children) {
+ recursivelyFindIonicComponents(childNode);
+ }
+ }
+
+ for (const childKey of Object.keys(node)) {
+ if (node[childKey]?.children) {
+ for (const childNode of node[childKey].children) {
+ recursivelyFindIonicComponents(Object.assign(childNode, {
+ type: childNode.constructor.name
+ }));
+ }
+ }
+ }
}
};
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index dbac0e6..1ffeb6a 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1,4 +1,4 @@
-lockfileVersion: '6.1'
+lockfileVersion: '6.0'
settings:
autoInstallPeers: true
@@ -245,8 +245,8 @@ importers:
packages/cli:
dependencies:
'@angular-eslint/template-parser':
- specifier: ^16.1.2
- version: 16.1.2(eslint@8.48.0)(typescript@4.9.5)
+ specifier: ^17.1.0
+ version: 17.1.1(eslint@8.48.0)(typescript@4.9.5)
'@clack/core':
specifier: ^0.3.3
version: 0.3.3
@@ -663,6 +663,11 @@ packages:
/@angular-eslint/bundled-angular-compiler@16.1.2:
resolution: {integrity: sha512-wDiHPFsKTijMcQUPNcoHOJ5kezIPCCbmDK6LHH7hAdAC/eDY9NHL5e4zQ2Xkf3/r1PFuwVLGTwwreEHlmeENDw==}
+ dev: true
+
+ /@angular-eslint/bundled-angular-compiler@17.1.1:
+ resolution: {integrity: sha512-xRlSh9qjdUdUKAy/0UQsxX7wf1tHApAsHsfismebPriqfmVAPyEg4HBrM8ImWaZxiqaTGC1AyHsUBQD5FK8o6w==}
+ dev: false
/@angular-eslint/eslint-plugin-template@16.0.0(eslint@7.26.0)(typescript@5.0.2):
resolution: {integrity: sha512-2m2NsB+WHO61eR1qvRvAidL5NBY89U/7bSPivA0o0lYuYZMuAczkDfsOBn4ejlaNdk+/vzXsmchza0B1ujrecA==}
@@ -730,13 +735,13 @@ packages:
typescript: 5.0.2
dev: true
- /@angular-eslint/template-parser@16.1.2(eslint@8.48.0)(typescript@4.9.5):
- resolution: {integrity: sha512-vIkPOShVJLBEHYY3jISCVvJF3lXL//Y70J8T9lY2CBowgqp6AzzJ6cZU7JxrORN6b64rBUVvUtCGo8L36GvfuA==}
+ /@angular-eslint/template-parser@17.1.1(eslint@8.48.0)(typescript@4.9.5):
+ resolution: {integrity: sha512-ofL46rNhRVeSxrSQF0vwhKMco+vJuo+ZGjSOzFmT9N3KAMB0j+WXTbpyGGMy0gQSBc4W6p+j+zxGa2CR2xb6wA==}
peerDependencies:
eslint: ^7.20.0 || ^8.0.0
typescript: '*'
dependencies:
- '@angular-eslint/bundled-angular-compiler': 16.1.2
+ '@angular-eslint/bundled-angular-compiler': 17.1.1
eslint: 8.48.0
eslint-scope: 7.2.2
typescript: 4.9.5