diff --git a/src/addons/filter/displayh5p/services/handlers/displayh5p.ts b/src/addons/filter/displayh5p/services/handlers/displayh5p.ts index 0ef26c726..8e4dbcb47 100644 --- a/src/addons/filter/displayh5p/services/handlers/displayh5p.ts +++ b/src/addons/filter/displayh5p/services/handlers/displayh5p.ts @@ -20,7 +20,7 @@ import { makeSingleton } from '@singletons'; import { CoreH5PPlayerComponent } from '@features/h5p/components/h5p-player/h5p-player'; import { CoreUrl } from '@singletons/url'; import { CoreH5PHelper } from '@features/h5p/classes/helper'; -import { CoreTemplateElement } from '@/core/utils/create-html-element'; +import { CoreText } from '@singletons/text'; /** * Handler to support the Display H5P filter. @@ -37,41 +37,39 @@ export class AddonFilterDisplayH5PHandlerService extends CoreFilterDefaultHandle filter( text: string, ): string | Promise { - CoreTemplateElement.innerHTML = text; + return CoreText.processHTML(text, (element) => { + const h5pIframes = Array.from(element.querySelectorAll('iframe.h5p-iframe')); - const h5pIframes = Array.from(CoreTemplateElement.content.querySelectorAll('iframe.h5p-iframe')); + // Replace all iframes with an empty div that will be treated in handleHtml. + h5pIframes.forEach((iframe) => { + const placeholder = document.createElement('div'); - // Replace all iframes with an empty div that will be treated in handleHtml. - h5pIframes.forEach((iframe) => { - const placeholder = document.createElement('div'); + placeholder.classList.add('core-h5p-tmp-placeholder'); + placeholder.setAttribute('data-player-src', iframe.src); - placeholder.classList.add('core-h5p-tmp-placeholder'); - placeholder.setAttribute('data-player-src', iframe.src); + iframe.parentElement?.replaceChild(placeholder, iframe); + }); - iframe.parentElement?.replaceChild(placeholder, iframe); + // Handle H5P iframes embedded using the embed HTML code. + const embeddedH5PIframes = Array.from( + element.querySelectorAll('iframe.h5p-player'), + ); + + embeddedH5PIframes.forEach((iframe) => { + // Add the preventredirect param to allow authenticating if auto-login fails. + iframe.src = CoreUrl.addParamsToUrl(iframe.src, { preventredirect: false }); + + // Add resizer script so the H5P has the right height. + CoreH5PHelper.addResizerScript(); + + // If the iframe has a small height, add some minimum initial height so it's seen if auto-login fails. + const styleHeight = Number(iframe.style.height); + const height = Number(iframe.getAttribute('height')); + if ((!height || height < 400) && (!styleHeight || styleHeight < 400)) { + iframe.style.height = '400px'; + } + }); }); - - // Handle H5P iframes embedded using the embed HTML code. - const embeddedH5PIframes = Array.from( - CoreTemplateElement.content.querySelectorAll('iframe.h5p-player'), - ); - - embeddedH5PIframes.forEach((iframe) => { - // Add the preventredirect param to allow authenticating if auto-login fails. - iframe.src = CoreUrl.addParamsToUrl(iframe.src, { preventredirect: false }); - - // Add resizer script so the H5P has the right height. - CoreH5PHelper.addResizerScript(); - - // If the iframe has a small height, add some minimum initial height so it's seen if auto-login fails. - const styleHeight = Number(iframe.style.height); - const height = Number(iframe.getAttribute('height')); - if ((!height || height < 400) && (!styleHeight || styleHeight < 400)) { - iframe.style.height = '400px'; - } - }); - - return CoreTemplateElement.innerHTML; } /** diff --git a/src/addons/filter/mediaplugin/services/handlers/mediaplugin.ts b/src/addons/filter/mediaplugin/services/handlers/mediaplugin.ts index 6d111dca4..363cc109c 100644 --- a/src/addons/filter/mediaplugin/services/handlers/mediaplugin.ts +++ b/src/addons/filter/mediaplugin/services/handlers/mediaplugin.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreTemplateElement } from '@/core/utils/create-html-element'; +import { CoreText } from '@singletons/text'; import { AddonFilterMediaPluginVideoJS } from '@addons/filter/mediaplugin/services/videojs'; import { Injectable } from '@angular/core'; @@ -33,15 +33,13 @@ export class AddonFilterMediaPluginHandlerService extends CoreFilterDefaultHandl * @inheritdoc */ filter(text: string): string | Promise { - CoreTemplateElement.innerHTML = text; + return CoreText.processHTML(text, (element) => { + const videos = Array.from(element.querySelectorAll('video')); - const videos = Array.from(CoreTemplateElement.content.querySelectorAll('video')); - - videos.forEach((video) => { - AddonFilterMediaPluginVideoJS.treatYoutubeVideos(video); + videos.forEach((video) => { + AddonFilterMediaPluginVideoJS.treatYoutubeVideos(video); + }); }); - - return CoreTemplateElement.innerHTML; } /** diff --git a/src/core/services/utils/dom.ts b/src/core/services/utils/dom.ts index f074d20c8..924ef2b8c 100644 --- a/src/core/services/utils/dom.ts +++ b/src/core/services/utils/dom.ts @@ -55,7 +55,7 @@ import { CorePopovers, OpenPopoverOptions } from '@services/popovers'; import { CoreViewer } from '@features/viewer/services/viewer'; import { CoreLoadings } from '@services/loadings'; import { CoreErrorHelper, CoreErrorObject } from '@services/error-helper'; -import { convertTextToHTMLElement, CoreTemplateElement } from '@/core/utils/create-html-element'; +import { convertTextToHTMLElement } from '@/core/utils/create-html-element'; import { CoreHTMLClasses } from '@singletons/html-classes'; /* @@ -197,7 +197,7 @@ export class CoreDomUtilsProvider { * @param html Text to convert. * @returns Element. * - * @deprecated since 4.5. Use convertToElement directly instead. + * @deprecated since 4.5. Use convertTextToHTMLElement directly instead. */ convertToElement(html: string): HTMLElement { return convertTextToHTMLElement(html); @@ -262,24 +262,23 @@ export class CoreDomUtilsProvider { * @returns Fixed HTML text. */ fixHtml(html: string): string { - CoreTemplateElement.innerHTML = html; + 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); + } + }); - // 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(element.children).forEach(fixElement); - }; + }); - Array.from(CoreTemplateElement.content.children).forEach(fixElement); - - return CoreTemplateElement.innerHTML; } /** diff --git a/src/core/singletons/dom.ts b/src/core/singletons/dom.ts index e35035472..c35b87ed6 100644 --- a/src/core/singletons/dom.ts +++ b/src/core/singletons/dom.ts @@ -17,7 +17,7 @@ import { CoreUtils } from '@services/utils/utils'; import { CoreEventObserver } from '@singletons/events'; import { CorePlatform } from '@services/platform'; import { CoreWait } from './wait'; -import { CoreTemplateElement } from '../utils/create-html-element'; +import { convertTextToHTMLElement } from '../utils/create-html-element'; /** * Singleton with helper functions for dom. @@ -118,9 +118,9 @@ export class CoreDom { return true; } - CoreTemplateElement.innerHTML = content; + const element = convertTextToHTMLElement(content); - return !CoreDom.elementHasContent(CoreTemplateElement.content); + return !CoreDom.elementHasContent(element); } /** diff --git a/src/core/utils/create-html-element.ts b/src/core/utils/create-html-element.ts index 60f98e5c2..076d6bbc4 100644 --- a/src/core/utils/create-html-element.ts +++ b/src/core/utils/create-html-element.ts @@ -12,18 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -// A template element to convert HTML to element. -export const CoreTemplateElement: HTMLTemplateElement = document.createElement('template'); - /** - * Convert some HTML as text into an HTMLElement. This HTML is put inside a div or a body. + * Convert some HTML as text into an HTMLElement. This HTML is put inside a div. * * @param html Text to convert. * @returns Element. */ export function convertTextToHTMLElement(html: string): HTMLElement { - // Add a div to hold the content, that's the element that will be returned. - CoreTemplateElement.innerHTML = '
' + html + '
'; + const element = document.createElement('template'); - return CoreTemplateElement.content.children[0]; + // Add a div to hold the content, that's the element that will be returned. + element.innerHTML = '
' + html + '
'; + + return element.content.children[0]; }