Skip to content

Commit

Permalink
MOBILE-4616 chore: Always use convertTextToHTMLElement to convert HTML
Browse files Browse the repository at this point in the history
  • Loading branch information
crazyserver committed Aug 14, 2024
1 parent c6b8815 commit f0bf6c3
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 70 deletions.
68 changes: 33 additions & 35 deletions src/addons/filter/displayh5p/services/handlers/displayh5p.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -37,41 +37,39 @@ export class AddonFilterDisplayH5PHandlerService extends CoreFilterDefaultHandle
filter(
text: string,
): string | Promise<string> {
CoreTemplateElement.innerHTML = text;

const h5pIframes = <HTMLIFrameElement[]> 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');

placeholder.classList.add('core-h5p-tmp-placeholder');
placeholder.setAttribute('data-player-src', iframe.src);

iframe.parentElement?.replaceChild(placeholder, iframe);
});

// Handle H5P iframes embedded using the embed HTML code.
const embeddedH5PIframes = <HTMLIFrameElement[]> 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 CoreText.processHTML(text, (element) => {
const h5pIframes = <HTMLIFrameElement[]> Array.from(element.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');

placeholder.classList.add('core-h5p-tmp-placeholder');
placeholder.setAttribute('data-player-src', iframe.src);

iframe.parentElement?.replaceChild(placeholder, iframe);
});

// Handle H5P iframes embedded using the embed HTML code.
const embeddedH5PIframes = <HTMLIFrameElement[]> 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';
}
});
});

return CoreTemplateElement.innerHTML;
}

/**
Expand Down
14 changes: 6 additions & 8 deletions src/addons/filter/mediaplugin/services/handlers/mediaplugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -33,15 +33,13 @@ export class AddonFilterMediaPluginHandlerService extends CoreFilterDefaultHandl
* @inheritdoc
*/
filter(text: string): string | Promise<string> {
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;
}

/**
Expand Down
33 changes: 16 additions & 17 deletions src/core/services/utils/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

/*
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -262,24 +262,23 @@ export class CoreDomUtilsProvider {
* @returns Fixed HTML text.
*/
fixHtml(html: string): string {
CoreTemplateElement.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);
}
});
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);
};
Array.from(element.children).forEach(fixElement);
};

Array.from(CoreTemplateElement.content.children).forEach(fixElement);
Array.from(element.children).forEach(fixElement);
});

return CoreTemplateElement.innerHTML;
}

/**
Expand Down
6 changes: 3 additions & 3 deletions src/core/singletons/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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);
}

/**
Expand Down
13 changes: 6 additions & 7 deletions src/core/utils/create-html-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = '<div>' + html + '</div>';
const element = document.createElement('template');

// Add a div to hold the content, that's the element that will be returned.
element.innerHTML = '<div>' + html + '</div>';

return <HTMLElement> CoreTemplateElement.content.children[0];
return <HTMLElement> element.content.children[0];
}

0 comments on commit f0bf6c3

Please sign in to comment.