/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ /** * This helper is used to get hold of an inert tree of DOM elements containing dirty HTML * that needs sanitizing. * Depending upon browser support we use one of two strategies for doing this. * Default: DOMParser strategy * Fallback: InertDocument strategy */ export function getInertBodyHelper(defaultDoc: Document): InertBodyHelper { return isDOMParserAvailable() ? new DOMParserHelper() : new InertDocumentHelper(defaultDoc); } export interface InertBodyHelper { /** * Get an inert DOM element containing DOM created from the dirty HTML string provided. */ getInertBodyElement: (html: string) => HTMLElement | null; } /** * Uses DOMParser to create and fill an inert body element. * This is the default strategy used in browsers that support it. */ class DOMParserHelper implements InertBodyHelper { getInertBodyElement(html: string): HTMLElement|null { // We add these extra elements to ensure that the rest of the content is parsed as expected // e.g. leading whitespace is maintained and tags like `` do not get hoisted to the // `` tag. html = '' + html + ''; try { const body = new (window as any).DOMParser().parseFromString(html, 'text/html').body as HTMLBodyElement; body.removeChild(body.firstChild!); return body; } catch { return null; } } } /** * Use an HTML5 `template` element, if supported, or an inert body element created via * `createHtmlDocument` to create and fill an inert DOM element. * This is the fallback strategy if the browser does not support DOMParser. */ class InertDocumentHelper implements InertBodyHelper { private inertDocument: Document; constructor(private defaultDoc: Document) { this.inertDocument = this.defaultDoc.implementation.createHTMLDocument('sanitization-inert'); if (this.inertDocument.body == null) { // usually there should be only one body element in the document, but IE doesn't have any, so // we need to create one. const inertHtml = this.inertDocument.createElement('html'); this.inertDocument.appendChild(inertHtml); const inertBodyElement = this.inertDocument.createElement('body'); inertHtml.appendChild(inertBodyElement); } } getInertBodyElement(html: string): HTMLElement|null { // Prefer using