diff --git a/src/core/features/compile/components/compile-html/compile-html.ts b/src/core/features/compile/components/compile-html/compile-html.ts index 2cceb8f0fc6..cfd3d9c4705 100644 --- a/src/core/features/compile/components/compile-html/compile-html.ts +++ b/src/core/features/compile/components/compile-html/compile-html.ts @@ -91,6 +91,7 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck { protected differ: KeyValueDiffer; // To detect changes in the jsData input. protected creatingComponent = false; protected pendingCalls = {}; + protected componentStyles = ''; constructor( protected changeDetector: ChangeDetectorRef, @@ -152,7 +153,7 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck { componentClass, this.container, this.extraImports, - this.cssCode, + this.componentStyles, ); this.element.addEventListener('submit', (event) => { @@ -185,7 +186,7 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck { protected async loadCSSCode(): Promise { // Do not allow (yet) to load CSS code to a component that doesn't have text. if (!this.text) { - this.cssCode = ''; + this.componentStyles = ''; return; } @@ -196,10 +197,12 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck { // Prepend all CSS rules with :host to avoid conflicts. if (!this.cssCode || this.cssCode.includes(':host')) { + this.componentStyles = this.cssCode ?? ''; + return; } - this.cssCode = CoreDom.prefixCSS(this.cssCode, ':host ::ng-deep', ':host'); + this.componentStyles = CoreDom.prefixCSS(this.cssCode, ':host ::ng-deep', ':host'); } /** diff --git a/src/core/services/utils/dom.ts b/src/core/services/utils/dom.ts index 924ef2b8ced..165c6595bb3 100644 --- a/src/core/services/utils/dom.ts +++ b/src/core/services/utils/dom.ts @@ -262,23 +262,27 @@ export class CoreDomUtilsProvider { * @returns Fixed HTML text. */ fixHtml(html: string): string { - return CoreText.processHTML(html, (element) => { - // eslint-disable-next-line no-control-regex - const attrNameRegExp = /[^\x00-\x20\x7F-\x9F"'>/=]+/; - const fixElement = (element: Element): void => { - // Remove attributes with an invalid name. - Array.from(element.attributes).forEach((attr) => { - if (!attrNameRegExp.test(attr.name)) { - element.removeAttributeNode(attr); - } - }); - - Array.from(element.children).forEach(fixElement); - }; + // We can't use CoreText.processHTML because it removes elements that + // are not allowed as a child of
, like
  • or . + const template = document.createElement('template'); + template.innerHTML = html; + + // eslint-disable-next-line no-control-regex + const attrNameRegExp = /[^\x00-\x20\x7F-\x9F"'>/=]+/; + const fixElement = (element: Element): void => { + // Remove attributes with an invalid name. + Array.from(element.attributes).forEach((attr) => { + if (!attrNameRegExp.test(attr.name)) { + element.removeAttributeNode(attr); + } + }); Array.from(element.children).forEach(fixElement); - }); + }; + + Array.from(template.content.children).forEach(fixElement); + return template.innerHTML; } /** diff --git a/src/core/singletons/text.ts b/src/core/singletons/text.ts index 482ce044a11..19f0c49fc5b 100644 --- a/src/core/singletons/text.ts +++ b/src/core/singletons/text.ts @@ -418,6 +418,7 @@ export class CoreText { /** * Process HTML string. + * Warning: Top-level elements that are not allowed as a child of
    (like or
  • ) will be removed. * * @param text HTML string. * @param process Method to process the HTML. diff --git a/src/core/utils/create-html-element.ts b/src/core/utils/create-html-element.ts index 076d6bbc4d8..ebdb9a2ff3c 100644 --- a/src/core/utils/create-html-element.ts +++ b/src/core/utils/create-html-element.ts @@ -14,6 +14,7 @@ /** * Convert some HTML as text into an HTMLElement. This HTML is put inside a div. + * Warning: Top-level elements that are not allowed as a child of
    (like or
  • ) will be removed. * * @param html Text to convert. * @returns Element.