MOBILE-4616 chore: Always use convertTextToHTMLElement to convert HTML
parent
b0c494ee51
commit
00951b22d5
|
@ -20,7 +20,7 @@ import { makeSingleton } from '@singletons';
|
||||||
import { CoreH5PPlayerComponent } from '@features/h5p/components/h5p-player/h5p-player';
|
import { CoreH5PPlayerComponent } from '@features/h5p/components/h5p-player/h5p-player';
|
||||||
import { CoreUrl } from '@singletons/url';
|
import { CoreUrl } from '@singletons/url';
|
||||||
import { CoreH5PHelper } from '@features/h5p/classes/helper';
|
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.
|
* Handler to support the Display H5P filter.
|
||||||
|
@ -37,41 +37,39 @@ export class AddonFilterDisplayH5PHandlerService extends CoreFilterDefaultHandle
|
||||||
filter(
|
filter(
|
||||||
text: string,
|
text: string,
|
||||||
): string | Promise<string> {
|
): string | Promise<string> {
|
||||||
CoreTemplateElement.innerHTML = text;
|
return CoreText.processHTML(text, (element) => {
|
||||||
|
const h5pIframes = <HTMLIFrameElement[]> Array.from(element.querySelectorAll('iframe.h5p-iframe'));
|
||||||
|
|
||||||
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');
|
||||||
|
|
||||||
// Replace all iframes with an empty div that will be treated in handleHtml.
|
placeholder.classList.add('core-h5p-tmp-placeholder');
|
||||||
h5pIframes.forEach((iframe) => {
|
placeholder.setAttribute('data-player-src', iframe.src);
|
||||||
const placeholder = document.createElement('div');
|
|
||||||
|
|
||||||
placeholder.classList.add('core-h5p-tmp-placeholder');
|
iframe.parentElement?.replaceChild(placeholder, iframe);
|
||||||
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';
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// 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 CoreTemplateElement.innerHTML;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// 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 { AddonFilterMediaPluginVideoJS } from '@addons/filter/mediaplugin/services/videojs';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@ -33,15 +33,13 @@ export class AddonFilterMediaPluginHandlerService extends CoreFilterDefaultHandl
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
filter(text: string): string | Promise<string> {
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -55,7 +55,7 @@ import { CorePopovers, OpenPopoverOptions } from '@services/popovers';
|
||||||
import { CoreViewer } from '@features/viewer/services/viewer';
|
import { CoreViewer } from '@features/viewer/services/viewer';
|
||||||
import { CoreLoadings } from '@services/loadings';
|
import { CoreLoadings } from '@services/loadings';
|
||||||
import { CoreErrorHelper, CoreErrorObject } from '@services/error-helper';
|
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';
|
import { CoreHTMLClasses } from '@singletons/html-classes';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -197,7 +197,7 @@ export class CoreDomUtilsProvider {
|
||||||
* @param html Text to convert.
|
* @param html Text to convert.
|
||||||
* @returns Element.
|
* @returns Element.
|
||||||
*
|
*
|
||||||
* @deprecated since 4.5. Use convertToElement directly instead.
|
* @deprecated since 4.5. Use convertTextToHTMLElement directly instead.
|
||||||
*/
|
*/
|
||||||
convertToElement(html: string): HTMLElement {
|
convertToElement(html: string): HTMLElement {
|
||||||
return convertTextToHTMLElement(html);
|
return convertTextToHTMLElement(html);
|
||||||
|
@ -262,24 +262,23 @@ export class CoreDomUtilsProvider {
|
||||||
* @returns Fixed HTML text.
|
* @returns Fixed HTML text.
|
||||||
*/
|
*/
|
||||||
fixHtml(html: string): string {
|
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
|
Array.from(element.children).forEach(fixElement);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { CoreUtils } from '@services/utils/utils';
|
||||||
import { CoreEventObserver } from '@singletons/events';
|
import { CoreEventObserver } from '@singletons/events';
|
||||||
import { CorePlatform } from '@services/platform';
|
import { CorePlatform } from '@services/platform';
|
||||||
import { CoreWait } from './wait';
|
import { CoreWait } from './wait';
|
||||||
import { CoreTemplateElement } from '../utils/create-html-element';
|
import { convertTextToHTMLElement } from '../utils/create-html-element';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Singleton with helper functions for dom.
|
* Singleton with helper functions for dom.
|
||||||
|
@ -118,9 +118,9 @@ export class CoreDom {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoreTemplateElement.innerHTML = content;
|
const element = convertTextToHTMLElement(content);
|
||||||
|
|
||||||
return !CoreDom.elementHasContent(CoreTemplateElement.content);
|
return !CoreDom.elementHasContent(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -12,18 +12,17 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// 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.
|
* @param html Text to convert.
|
||||||
* @returns Element.
|
* @returns Element.
|
||||||
*/
|
*/
|
||||||
export function convertTextToHTMLElement(html: string): HTMLElement {
|
export function convertTextToHTMLElement(html: string): HTMLElement {
|
||||||
// Add a div to hold the content, that's the element that will be returned.
|
const element = document.createElement('template');
|
||||||
CoreTemplateElement.innerHTML = '<div>' + html + '</div>';
|
|
||||||
|
|
||||||
return <HTMLElement> CoreTemplateElement.content.children[0];
|
// Add a div to hold the content, that's the element that will be returned.
|
||||||
|
element.innerHTML = '<div>' + html + '</div>';
|
||||||
|
|
||||||
|
return <HTMLElement> element.content.children[0];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue