diff --git a/.changeset/tender-flies-remember.md b/.changeset/tender-flies-remember.md
new file mode 100644
index 0000000000..5ac09dd803
--- /dev/null
+++ b/.changeset/tender-flies-remember.md
@@ -0,0 +1,5 @@
+---
+'@builder.io/mitosis': patch
+---
+
+[Angular] Update innerHtml parsing to escape quotes
diff --git a/packages/core/src/__tests__/__snapshots__/angular.import.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.import.test.ts.snap
index 2600ea51b7..0d025871b4 100644
--- a/packages/core/src/__tests__/__snapshots__/angular.import.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/angular.import.test.ts.snap
@@ -4665,6 +4665,49 @@ export class MyComponentModule {}
"
`;
+exports[`Angular with Preserve Imports and File Extensions > jsx > Javascript Test > escapeQuotesInnerHTML 1`] = `
+"/**
+ useMetadata:
+ {\\"angular\\":{\\"changeDetection\\":\\"OnPush\\"}}
+ */
+
+import { NgModule } from \\"@angular/core\\";
+import { CommonModule } from \\"@angular/common\\";
+
+import { Component, ChangeDetectionStrategy } from \\"@angular/core\\";
+import { DomSanitizer } from \\"@angular/platform-browser\\";
+
+@Component({
+ selector: \\"my-component\\",
+ template: \`
+
+
+ \\\\\`)'
+ >
+ \`,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ styles: [
+ \`
+ :host {
+ display: contents;
+ }
+ \`,
+ ],
+})
+export default class MyComponent {
+ constructor(protected sanitizer) {}
+}
+
+@NgModule({
+ declarations: [MyComponent],
+ imports: [CommonModule],
+ exports: [MyComponent],
+})
+export class MyComponentModule {}
+"
+`;
+
exports[`Angular with Preserve Imports and File Extensions > jsx > Javascript Test > eventInputAndChange 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";
@@ -12922,6 +12965,53 @@ export class MyComponentModule {}
"
`;
+exports[`Angular with Preserve Imports and File Extensions > jsx > Typescript Test > escapeQuotesInnerHTML 1`] = `
+"/**
+ useMetadata:
+ {\\"angular\\":{\\"changeDetection\\":\\"OnPush\\"}}
+ */
+
+import { NgModule } from \\"@angular/core\\";
+import { CommonModule } from \\"@angular/common\\";
+
+import { Component, ChangeDetectionStrategy } from \\"@angular/core\\";
+import { DomSanitizer } from \\"@angular/platform-browser\\";
+
+export interface MyComponentProps {
+ text?: string;
+}
+
+@Component({
+ selector: \\"my-component\\",
+ template: \`
+
+
+ \\\\\`)'
+ >
+ \`,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ styles: [
+ \`
+ :host {
+ display: contents;
+ }
+ \`,
+ ],
+})
+export default class MyComponent {
+ constructor(protected sanitizer: DomSanitizer) {}
+}
+
+@NgModule({
+ declarations: [MyComponent],
+ imports: [CommonModule],
+ exports: [MyComponent],
+})
+export class MyComponentModule {}
+"
+`;
+
exports[`Angular with Preserve Imports and File Extensions > jsx > Typescript Test > eventInputAndChange 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";
diff --git a/packages/core/src/__tests__/__snapshots__/angular.mapper.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.mapper.test.ts.snap
index dc64cdf00a..405024d74c 100644
--- a/packages/core/src/__tests__/__snapshots__/angular.mapper.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/angular.mapper.test.ts.snap
@@ -4735,6 +4735,50 @@ export class MyComponentModule {}
"
`;
+exports[`Angular with Import Mapper Tests > jsx > Javascript Test > escapeQuotesInnerHTML 1`] = `
+"/**
+ useMetadata:
+ {\\"angular\\":{\\"changeDetection\\":\\"OnPush\\"}}
+ */
+
+import { NgModule } from \\"@angular/core\\";
+import { CommonModule } from \\"@angular/common\\";
+
+import { Component, ChangeDetectionStrategy } from \\"@angular/core\\";
+import { DomSanitizer } from \\"@angular/platform-browser\\";
+
+@Component({
+ selector: \\"my-component\\",
+ template: \`
+
+
+ \\\\\`)'
+ >
+ \`,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ styles: [
+ \`
+ :host {
+ display: contents;
+ }
+ \`,
+ ],
+})
+export default class MyComponent {
+ constructor(protected sanitizer) {}
+}
+
+@NgModule({
+ declarations: [MyComponent],
+ imports: [CommonModule],
+ exports: [MyComponent],
+ bootstrap: [SomeOtherComponent],
+})
+export class MyComponentModule {}
+"
+`;
+
exports[`Angular with Import Mapper Tests > jsx > Javascript Test > eventInputAndChange 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";
@@ -13127,6 +13171,54 @@ export class MyComponentModule {}
"
`;
+exports[`Angular with Import Mapper Tests > jsx > Typescript Test > escapeQuotesInnerHTML 1`] = `
+"/**
+ useMetadata:
+ {\\"angular\\":{\\"changeDetection\\":\\"OnPush\\"}}
+ */
+
+import { NgModule } from \\"@angular/core\\";
+import { CommonModule } from \\"@angular/common\\";
+
+import { Component, ChangeDetectionStrategy } from \\"@angular/core\\";
+import { DomSanitizer } from \\"@angular/platform-browser\\";
+
+export interface MyComponentProps {
+ text?: string;
+}
+
+@Component({
+ selector: \\"my-component\\",
+ template: \`
+
+
+ \\\\\`)'
+ >
+ \`,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ styles: [
+ \`
+ :host {
+ display: contents;
+ }
+ \`,
+ ],
+})
+export default class MyComponent {
+ constructor(protected sanitizer: DomSanitizer) {}
+}
+
+@NgModule({
+ declarations: [MyComponent],
+ imports: [CommonModule],
+ exports: [MyComponent],
+ bootstrap: [SomeOtherComponent],
+})
+export class MyComponentModule {}
+"
+`;
+
exports[`Angular with Import Mapper Tests > jsx > Typescript Test > eventInputAndChange 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";
diff --git a/packages/core/src/__tests__/__snapshots__/angular.state.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.state.test.ts.snap
index 29fa7867b6..b1fef58764 100644
--- a/packages/core/src/__tests__/__snapshots__/angular.state.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/angular.state.test.ts.snap
@@ -4847,6 +4847,49 @@ export class MyComponentModule {}
"
`;
+exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Javascript Test > escapeQuotesInnerHTML 1`] = `
+"/**
+ useMetadata:
+ {\\"angular\\":{\\"changeDetection\\":\\"OnPush\\"}}
+ */
+
+import { NgModule } from \\"@angular/core\\";
+import { CommonModule } from \\"@angular/common\\";
+
+import { Component, ChangeDetectionStrategy } from \\"@angular/core\\";
+import { DomSanitizer } from \\"@angular/platform-browser\\";
+
+@Component({
+ selector: \\"my-component\\",
+ template: \`
+
+
+ \\\\\`)'
+ >
+ \`,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ styles: [
+ \`
+ :host {
+ display: contents;
+ }
+ \`,
+ ],
+})
+export default class MyComponent {
+ constructor(protected sanitizer) {}
+}
+
+@NgModule({
+ declarations: [MyComponent],
+ imports: [CommonModule],
+ exports: [MyComponent],
+})
+export class MyComponentModule {}
+"
+`;
+
exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Javascript Test > eventInputAndChange 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";
@@ -13433,6 +13476,53 @@ export class MyComponentModule {}
"
`;
+exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Typescript Test > escapeQuotesInnerHTML 1`] = `
+"/**
+ useMetadata:
+ {\\"angular\\":{\\"changeDetection\\":\\"OnPush\\"}}
+ */
+
+import { NgModule } from \\"@angular/core\\";
+import { CommonModule } from \\"@angular/common\\";
+
+import { Component, ChangeDetectionStrategy } from \\"@angular/core\\";
+import { DomSanitizer } from \\"@angular/platform-browser\\";
+
+export interface MyComponentProps {
+ text?: string;
+}
+
+@Component({
+ selector: \\"my-component\\",
+ template: \`
+
+
+ \\\\\`)'
+ >
+ \`,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ styles: [
+ \`
+ :host {
+ display: contents;
+ }
+ \`,
+ ],
+})
+export default class MyComponent {
+ constructor(protected sanitizer: DomSanitizer) {}
+}
+
+@NgModule({
+ declarations: [MyComponent],
+ imports: [CommonModule],
+ exports: [MyComponent],
+})
+export class MyComponentModule {}
+"
+`;
+
exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Typescript Test > eventInputAndChange 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";
diff --git a/packages/core/src/__tests__/__snapshots__/angular.styles.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.styles.test.ts.snap
index c8c1d3c77e..3004ad0f7c 100644
--- a/packages/core/src/__tests__/__snapshots__/angular.styles.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/angular.styles.test.ts.snap
@@ -4223,6 +4223,42 @@ export class MyComponentModule {}
"
`;
+exports[`Angular with visuallyIgnoreHostElement = false > jsx > Javascript Test > escapeQuotesInnerHTML 1`] = `
+"/**
+ useMetadata:
+ {\\"angular\\":{\\"changeDetection\\":\\"OnPush\\"}}
+ */
+
+import { NgModule } from \\"@angular/core\\";
+import { CommonModule } from \\"@angular/common\\";
+
+import { Component, ChangeDetectionStrategy } from \\"@angular/core\\";
+import { DomSanitizer } from \\"@angular/platform-browser\\";
+
+@Component({
+ selector: \\"my-component\\",
+ template: \`
+
+
+ \\\\\`)'
+ >
+ \`,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export default class MyComponent {
+ constructor(protected sanitizer) {}
+}
+
+@NgModule({
+ declarations: [MyComponent],
+ imports: [CommonModule],
+ exports: [MyComponent],
+})
+export class MyComponentModule {}
+"
+`;
+
exports[`Angular with visuallyIgnoreHostElement = false > jsx > Javascript Test > eventInputAndChange 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";
@@ -11619,6 +11655,46 @@ export class MyComponentModule {}
"
`;
+exports[`Angular with visuallyIgnoreHostElement = false > jsx > Typescript Test > escapeQuotesInnerHTML 1`] = `
+"/**
+ useMetadata:
+ {\\"angular\\":{\\"changeDetection\\":\\"OnPush\\"}}
+ */
+
+import { NgModule } from \\"@angular/core\\";
+import { CommonModule } from \\"@angular/common\\";
+
+import { Component, ChangeDetectionStrategy } from \\"@angular/core\\";
+import { DomSanitizer } from \\"@angular/platform-browser\\";
+
+export interface MyComponentProps {
+ text?: string;
+}
+
+@Component({
+ selector: \\"my-component\\",
+ template: \`
+
+
+ \\\\\`)'
+ >
+ \`,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export default class MyComponent {
+ constructor(protected sanitizer: DomSanitizer) {}
+}
+
+@NgModule({
+ declarations: [MyComponent],
+ imports: [CommonModule],
+ exports: [MyComponent],
+})
+export class MyComponentModule {}
+"
+`;
+
exports[`Angular with visuallyIgnoreHostElement = false > jsx > Typescript Test > eventInputAndChange 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";
diff --git a/packages/core/src/__tests__/__snapshots__/angular.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.test.ts.snap
index e9e4e770b4..1f76e348e5 100644
--- a/packages/core/src/__tests__/__snapshots__/angular.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/angular.test.ts.snap
@@ -8898,6 +8898,85 @@ export default class MyComponent {
"
`;
+exports[`Angular > jsx > Javascript Test > escapeQuotesInnerHTML 1`] = `
+"/**
+ useMetadata:
+ {\\"angular\\":{\\"changeDetection\\":\\"OnPush\\"}}
+ */
+
+import { NgModule } from \\"@angular/core\\";
+import { CommonModule } from \\"@angular/common\\";
+
+import { Component, ChangeDetectionStrategy } from \\"@angular/core\\";
+import { DomSanitizer } from \\"@angular/platform-browser\\";
+
+@Component({
+ selector: \\"my-component\\",
+ template: \`
+
+
+ \\\\\`)'
+ >
+ \`,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ styles: [
+ \`
+ :host {
+ display: contents;
+ }
+ \`,
+ ],
+})
+export default class MyComponent {
+ constructor(protected sanitizer) {}
+}
+
+@NgModule({
+ declarations: [MyComponent],
+ imports: [CommonModule],
+ exports: [MyComponent],
+})
+export class MyComponentModule {}
+"
+`;
+
+exports[`Angular > jsx > Javascript Test > escapeQuotesInnerHTML 2`] = `
+"/**
+ useMetadata:
+ {\\"angular\\":{\\"changeDetection\\":\\"OnPush\\"}}
+ */
+
+import { Component, ChangeDetectionStrategy } from \\"@angular/core\\";
+import { DomSanitizer } from \\"@angular/platform-browser\\";
+import { CommonModule } from \\"@angular/common\\";
+
+@Component({
+ selector: \\"my-component\\",
+ template: \`
+
+
+ \\\\\`)'
+ >
+ \`,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ styles: [
+ \`
+ :host {
+ display: contents;
+ }
+ \`,
+ ],
+ standalone: true,
+ imports: [CommonModule],
+})
+export default class MyComponent {
+ constructor(protected sanitizer) {}
+}
+"
+`;
+
exports[`Angular > jsx > Javascript Test > eventInputAndChange 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";
@@ -24566,6 +24645,93 @@ export default class MyComponent {
"
`;
+exports[`Angular > jsx > Typescript Test > escapeQuotesInnerHTML 1`] = `
+"/**
+ useMetadata:
+ {\\"angular\\":{\\"changeDetection\\":\\"OnPush\\"}}
+ */
+
+import { NgModule } from \\"@angular/core\\";
+import { CommonModule } from \\"@angular/common\\";
+
+import { Component, ChangeDetectionStrategy } from \\"@angular/core\\";
+import { DomSanitizer } from \\"@angular/platform-browser\\";
+
+export interface MyComponentProps {
+ text?: string;
+}
+
+@Component({
+ selector: \\"my-component\\",
+ template: \`
+
+
+ \\\\\`)'
+ >
+ \`,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ styles: [
+ \`
+ :host {
+ display: contents;
+ }
+ \`,
+ ],
+})
+export default class MyComponent {
+ constructor(protected sanitizer: DomSanitizer) {}
+}
+
+@NgModule({
+ declarations: [MyComponent],
+ imports: [CommonModule],
+ exports: [MyComponent],
+})
+export class MyComponentModule {}
+"
+`;
+
+exports[`Angular > jsx > Typescript Test > escapeQuotesInnerHTML 2`] = `
+"/**
+ useMetadata:
+ {\\"angular\\":{\\"changeDetection\\":\\"OnPush\\"}}
+ */
+
+import { Component, ChangeDetectionStrategy } from \\"@angular/core\\";
+import { DomSanitizer } from \\"@angular/platform-browser\\";
+import { CommonModule } from \\"@angular/common\\";
+
+export interface MyComponentProps {
+ text?: string;
+}
+
+@Component({
+ selector: \\"my-component\\",
+ template: \`
+
+
+ \\\\\`)'
+ >
+ \`,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ styles: [
+ \`
+ :host {
+ display: contents;
+ }
+ \`,
+ ],
+ standalone: true,
+ imports: [CommonModule],
+})
+export default class MyComponent {
+ constructor(protected sanitizer: DomSanitizer) {}
+}
+"
+`;
+
exports[`Angular > jsx > Typescript Test > eventInputAndChange 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";
diff --git a/packages/core/src/__tests__/data/angular/escape-quotes-innerhtml.raw.tsx b/packages/core/src/__tests__/data/angular/escape-quotes-innerhtml.raw.tsx
new file mode 100644
index 0000000000..7027a85251
--- /dev/null
+++ b/packages/core/src/__tests__/data/angular/escape-quotes-innerhtml.raw.tsx
@@ -0,0 +1,17 @@
+import { useMetadata } from '@builder.io/mitosis';
+
+useMetadata({
+ angular: {
+ changeDetection: 'OnPush',
+ },
+});
+
+export default function MyComponent(props: { text?: string }) {
+ return (
+
+
+ `}
+ />
+ );
+}
diff --git a/packages/core/src/__tests__/test-generator.ts b/packages/core/src/__tests__/test-generator.ts
index 998400bd29..a3d7e89fe5 100644
--- a/packages/core/src/__tests__/test-generator.ts
+++ b/packages/core/src/__tests__/test-generator.ts
@@ -372,6 +372,7 @@ const ANGULAR_TESTS: Tests = {
allSpread: getRawFile('./data/angular/all-spread.raw.tsx'),
changeDetection: getRawFile('./data/angular/change-detection.raw.tsx'),
sanitizeInnerHTML: getRawFile('./data/angular/sanitize-inner-html.raw.tsx'),
+ escapeQuotesInnerHTML: getRawFile('./data/angular/escape-quotes-innerhtml.raw.tsx'),
};
const CONTEXT_TEST: Tests = {
diff --git a/packages/core/src/generators/angular/blocks.ts b/packages/core/src/generators/angular/blocks.ts
index 993551158d..c8a910559a 100644
--- a/packages/core/src/generators/angular/blocks.ts
+++ b/packages/core/src/generators/angular/blocks.ts
@@ -409,7 +409,14 @@ export const blockToAngular = ({
continue;
}
const value = json.properties[key];
- str += ` ${key}="${value}" `;
+ // Better parsing for innerHTML
+ if (key === 'innerHTML') {
+ // Replace double quotes with escaped quotes for proper Angular template handling
+ const escapedValue = String(value).replace(/"/g, '"');
+ str += `[innerHTML]="sanitizer.bypassSecurityTrustHtml('${escapedValue}')" `;
+ } else {
+ str += ` ${key}="${value}" `;
+ }
}
for (const key in json.bindings) {