/** * @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 */ import { trustedHTMLFromString } from '../util/security/trusted_types'; /** * 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) { const inertDocumentHelper = new InertDocumentHelper(defaultDoc); return isDOMParserAvailable() ? new DOMParserHelper(inertDocumentHelper) : inertDocumentHelper; } /** * Uses DOMParser to create and fill an inert body element. * This is the default strategy used in browsers that support it. */ class DOMParserHelper { constructor(inertDocumentHelper) { this.inertDocumentHelper = inertDocumentHelper; } getInertBodyElement(html) { // 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. Note that the `` tag is closed implicitly to prevent unclosed tags // in `html` from consuming the otherwise explicit `` tag. html = '' + html; try { const body = new window.DOMParser() .parseFromString(trustedHTMLFromString(html), 'text/html') .body; if (body === null) { // In some browsers (e.g. Mozilla/5.0 iPad AppleWebKit Mobile) the `body` property only // becomes available in the following tick of the JS engine. In that case we fall back to // the `inertDocumentHelper` instead. return this.inertDocumentHelper.getInertBodyElement(html); } 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 { constructor(defaultDoc) { this.defaultDoc = defaultDoc; 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) { // Prefer using