MOBILE-2364 format-text: Download inline styles files

main
Dani Palou 2018-08-13 16:31:24 +02:00
parent e6c5607463
commit c4221f1367
2 changed files with 57 additions and 6 deletions

View File

@ -20,6 +20,7 @@ import { CoreFilepoolProvider } from '@providers/filepool';
import { CoreSitesProvider } from '@providers/sites';
import { CoreDomUtilsProvider } from '@providers/utils/dom';
import { CoreUrlUtilsProvider } from '@providers/utils/url';
import { CoreUtilsProvider } from '@providers/utils/utils';
/**
* Directive to handle external content.
@ -28,6 +29,8 @@ import { CoreUrlUtilsProvider } from '@providers/utils/url';
* which we want to have available when the app is offline. Typically media and links.
*
* If a file is downloaded, its URL will be replaced by the local file URL.
*
* From v3.5.2 this directive will also download inline styles, so it can be used in any element as long as it has inline styles.
*/
@Directive({
selector: '[core-external-content]'
@ -42,7 +45,7 @@ export class CoreExternalContentDirective implements AfterViewInit {
constructor(element: ElementRef, logger: CoreLoggerProvider, private filepoolProvider: CoreFilepoolProvider,
private platform: Platform, private sitesProvider: CoreSitesProvider, private domUtils: CoreDomUtilsProvider,
private urlUtils: CoreUrlUtilsProvider, private appProvider: CoreAppProvider) {
private urlUtils: CoreUrlUtilsProvider, private appProvider: CoreAppProvider, private utils: CoreUtilsProvider) {
// This directive can be added dynamically. In that case, the first param is the HTMLElement.
this.element = element.nativeElement || element;
this.logger = logger.getInstance('CoreExternalContentDirective');
@ -58,6 +61,11 @@ export class CoreExternalContentDirective implements AfterViewInit {
let targetAttr,
sourceAttr;
// Always handle inline styles (if any).
this.handleInlineStyles(siteId).catch((error) => {
this.logger.error('Error treating inline styles.', this.element);
});
if (tagName === 'A') {
targetAttr = 'href';
sourceAttr = 'href';
@ -81,9 +89,6 @@ export class CoreExternalContentDirective implements AfterViewInit {
}
} else {
// Unsupported tag.
this.logger.warn('Directive attached to non-supported tag: ' + tagName);
return;
}
@ -217,4 +222,39 @@ export class CoreExternalContentDirective implements AfterViewInit {
});
});
}
/**
* Handle inline styles, trying to download referenced files.
*
* @param {string} siteId Site ID.
* @return {Promise<any>} Promise resolved if the element is successfully treated.
*/
protected handleInlineStyles(siteId: string): Promise<any> {
let inlineStyles = this.element.getAttribute('style');
if (!inlineStyles) {
return Promise.resolve();
}
let urls = inlineStyles.match(/https?:\/\/[^"'\) ;]*/g);
if (!urls || !urls.length) {
return Promise.resolve();
}
const promises = [];
urls = this.utils.uniqueArray(urls); // Remove duplicates.
urls.forEach((url) => {
promises.push(this.filepoolProvider.getUrlByUrl(siteId, url, this.component, this.componentId, 0, true, true)
.then((finalUrl) => {
this.logger.debug('Using URL ' + finalUrl + ' for ' + url + ' in inline styles');
inlineStyles = inlineStyles.replace(new RegExp(url, 'gi'), finalUrl);
}));
});
return this.utils.allPromises(promises).then(() => {
this.element.setAttribute('style', inlineStyles);
});
}
}

View File

@ -87,7 +87,7 @@ export class CoreFormatTextDirective implements OnChanges {
protected addExternalContent(element: HTMLElement): void {
// Angular 2 doesn't let adding directives dynamically. Create the CoreExternalContentDirective manually.
const extContent = new CoreExternalContentDirective(<any> element, this.loggerProvider, this.filepoolProvider,
this.platform, this.sitesProvider, this.domUtils, this.urlUtils, this.appProvider);
this.platform, this.sitesProvider, this.domUtils, this.urlUtils, this.appProvider, this.utils);
extContent.component = this.component;
extContent.componentId = this.componentId;
@ -313,7 +313,8 @@ export class CoreFormatTextDirective implements OnChanges {
audios,
videos,
iframes,
buttons;
buttons,
elementsWithInlineStyles;
div.innerHTML = formatted;
images = Array.from(div.querySelectorAll('img'));
@ -322,6 +323,7 @@ export class CoreFormatTextDirective implements OnChanges {
videos = Array.from(div.querySelectorAll('video'));
iframes = Array.from(div.querySelectorAll('iframe'));
buttons = Array.from(div.querySelectorAll('.button'));
elementsWithInlineStyles = Array.from(div.querySelectorAll('*[style]'));
// Walk through the content to find the links and add our directive to it.
// Important: We need to look for links first because in 'img' we add new links without core-link.
@ -370,6 +372,15 @@ export class CoreFormatTextDirective implements OnChanges {
}
});
// Handle inline styles.
elementsWithInlineStyles.forEach((el: HTMLElement) => {
// Only add external content for tags that haven't been treated already.
if (el.tagName != 'A' && el.tagName != 'IMG' && el.tagName != 'AUDIO' && el.tagName != 'VIDEO'
&& el.tagName != 'SOURCE' && el.tagName != 'TRACK') {
this.addExternalContent(el);
}
});
return div;
});
}