Skip to content

Commit 8b34f1f

Browse files
authored
Merge pull request #4123 from crazyserver/MOBILE-4632
Mobile 4632
2 parents 41879a3 + e8a1ff8 commit 8b34f1f

File tree

14 files changed

+182
-91
lines changed

14 files changed

+182
-91
lines changed

src/addons/mod/data/components/index/addon-mod-data-index.html

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,7 @@
7575
</ng-container>
7676

7777
<div class="addon-data-contents addon-data-entries addon-data-entries-{{database.id}}" *ngIf="!isEmpty && database">
78-
<core-style [css]="database.csstemplate" prefix="div.addon-data-entries.addon-data-entries-{{database.id}}" />
79-
80-
<core-compile-html [text]="entriesRendered" [jsData]="jsData" [extraImports]="extraImports" />
78+
<core-compile-html [text]="entriesRendered" [jsData]="jsData" [extraImports]="extraImports" [cssCode]="database.csstemplate" />
8179
</div>
8280

8381

src/addons/mod/data/pages/edit/edit.html

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,9 @@ <h1>
2121
[courseId]="database?.course" />
2222

2323
<div class="addon-data-contents addon-data-edit-entry {{cssClass}}" *ngIf="database">
24-
<core-style [css]="database.csstemplate" prefix="div.addon-data-edit-entry.{{cssClass}}" />
25-
2624
<form (ngSubmit)="save($event)" [formGroup]="editForm" #editFormEl>
27-
<core-compile-html [text]="editFormRender" [jsData]="jsData" [extraImports]="extraImports" />
25+
<core-compile-html [text]="editFormRender" [jsData]="jsData" [extraImports]="extraImports"
26+
[cssCode]="database.csstemplate" />
2827
</form>
2928
</div>
3029
</core-loading>

src/addons/mod/data/pages/entry/entry.html

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,8 @@ <h1>
2828
[courseId]="courseId" />
2929

3030
<div class="addon-data-contents addon-data-entry addon-data-entries-{{database.id}}" *ngIf="database && entry">
31-
<core-style [css]="database.csstemplate" prefix="div.addon-data-entry.addon-data-entries-{{database.id}}" />
32-
33-
<core-compile-html [text]="entryHtml" [jsData]="jsData" [extraImports]="extraImports" (compiling)="setRenderingEntry($event)" />
31+
<core-compile-html [text]="entryHtml" [jsData]="jsData" [extraImports]="extraImports" (compiling)="setRenderingEntry($event)"
32+
[cssCode]="database.csstemplate" />
3433
</div>
3534

3635
<core-rating-rate *ngIf="database && entry && ratingInfo && (!database.approval || entry.approved)" [ratingInfo]="ratingInfo"

src/core/components/components.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ import { CoreSitesListComponent } from './sites-list/sites-list';
100100
CoreShowPasswordComponent,
101101
CoreSitePickerComponent,
102102
CoreSplitViewComponent,
103+
// eslint-disable-next-line deprecation/deprecation
103104
CoreStyleComponent,
104105
CoreSwipeSlidesComponent,
105106
CoreTabComponent,
@@ -155,6 +156,7 @@ import { CoreSitesListComponent } from './sites-list/sites-list';
155156
CoreShowPasswordComponent,
156157
CoreSitePickerComponent,
157158
CoreSplitViewComponent,
159+
// eslint-disable-next-line deprecation/deprecation
158160
CoreStyleComponent,
159161
CoreSwipeSlidesComponent,
160162
CoreTabComponent,

src/core/components/style/style.ts

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// limitations under the License.
1414

1515
import { Component, ElementRef, Input, OnChanges } from '@angular/core';
16+
import { CoreDom } from '@singletons/dom';
1617

1718
/**
1819
* Component to add a <style> tag.
@@ -23,6 +24,7 @@ import { Component, ElementRef, Input, OnChanges } from '@angular/core';
2324
* Example:
2425
*
2526
* <core-style [css]="'p { color: red; }'" prefix=".custom-rules"></core-style>
27+
* @deprecated since 4.5.0. Not needed anymore, core-compile-html accepts now CSS code.
2628
*/
2729
@Component({
2830
selector: 'core-style',
@@ -41,37 +43,11 @@ export class CoreStyleComponent implements OnChanges {
4143
ngOnChanges(): void {
4244
if (this.element && this.element.nativeElement) {
4345
const style = document.createElement('style');
44-
style.innerHTML = this.prefixCSS(this.css, this.prefix);
46+
style.innerHTML = CoreDom.prefixCSS(this.css, this.prefix);
4547

4648
this.element.nativeElement.innerHTML = '';
4749
this.element.nativeElement.appendChild(style);
4850
}
4951
}
5052

51-
/**
52-
* Add a prefix to all rules in a CSS string.
53-
*
54-
* @param css CSS code to be prefixed.
55-
* @param prefix Prefix css selector.
56-
* @returns Prefixed CSS.
57-
*/
58-
protected prefixCSS(css: string, prefix: string): string {
59-
if (!css) {
60-
return '';
61-
}
62-
63-
if (!prefix) {
64-
return css;
65-
}
66-
67-
// Remove comments first.
68-
let regExp = /\/\*[\s\S]*?\*\/|([^:]|^)\/\/.*$/gm;
69-
css = css.replace(regExp, '');
70-
71-
// Add prefix.
72-
regExp = /([^]*?)({[^]*?}|,)/g;
73-
74-
return css.replace(regExp, prefix + ' $1 $2');
75-
}
76-
7753
}

src/core/features/compile/components/compile-html/compile-html.ts

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ import { CorePromisedValue } from '@classes/promised-value';
3838
import { CoreCompile } from '@features/compile/services/compile';
3939
import { CoreDomUtils } from '@services/utils/dom';
4040
import { CoreUtils } from '@services/utils/utils';
41+
import { CoreWS } from '@services/ws';
42+
import { CoreDom } from '@singletons/dom';
4143

4244
/**
4345
* This component has a behaviour similar to $compile for AngularJS. Given an HTML code, it will compile it so all its
@@ -64,6 +66,8 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
6466
@Input() text!: string; // The HTML text to display.
6567
@Input() javascript?: string; // The Javascript to execute in the component.
6668
@Input() jsData?: Record<string, unknown>; // Data to pass to the fake component.
69+
@Input() cssCode?: string; // The styles to apply.
70+
@Input() stylesPath?: string; // The styles URL to apply (only if cssCode is not set).
6771
@Input() extraImports: unknown[] = []; // Extra import modules.
6872
@Input() extraProviders: Type<unknown>[] = []; // Extra providers.
6973
@Input() forceCompile = false; // Set it to true to force compile even if the text/javascript hasn't changed.
@@ -101,12 +105,13 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
101105

102106
// Check if there's any change in the jsData object.
103107
const changes = this.differ.diff(this.jsData || {});
104-
if (changes) {
105-
this.setInputData();
108+
if (!changes) {
109+
return;
110+
}
111+
this.setInputData();
106112

107-
if (this.componentInstance.ngOnChanges) {
108-
this.componentInstance.ngOnChanges(CoreDomUtils.createChangesFromKeyValueDiff(changes));
109-
}
113+
if (this.componentInstance.ngOnChanges) {
114+
this.componentInstance.ngOnChanges(CoreDomUtils.createChangesFromKeyValueDiff(changes));
110115
}
111116
}
112117

@@ -116,7 +121,8 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
116121
async ngOnChanges(changes: Record<string, SimpleChange>): Promise<void> {
117122
// Only compile if text/javascript has changed or the forceCompile flag has been set to true.
118123
if (this.text === undefined ||
119-
!(changes.text || changes.javascript || (changes.forceCompile && CoreUtils.isTrueOrOne(this.forceCompile)))) {
124+
!(changes.text || changes.javascript || changes.cssCode || changes.stylesPath ||
125+
(changes.forceCompile && CoreUtils.isTrueOrOne(this.forceCompile)))) {
120126
return;
121127
}
122128

@@ -132,11 +138,14 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
132138

133139
// Create the component.
134140
if (this.container) {
141+
await this.loadCSSCode();
142+
135143
this.componentRef = await CoreCompile.createAndCompileComponent(
136144
this.text,
137145
componentClass,
138146
this.container,
139147
this.extraImports,
148+
this.cssCode,
140149
);
141150

142151
this.element.addEventListener('submit', (event) => {
@@ -163,6 +172,29 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
163172
this.componentRef?.destroy();
164173
}
165174

175+
/**
176+
* Retrieve the CSS code from the stylesPath if not loaded yet.
177+
*/
178+
protected async loadCSSCode(): Promise<void> {
179+
// Do not allow (yet) to load CSS code to a component that doesn't have text.
180+
if (!this.text) {
181+
this.cssCode = '';
182+
183+
return;
184+
}
185+
186+
if (this.stylesPath && !this.cssCode) {
187+
this.cssCode = await CoreUtils.ignoreErrors(CoreWS.getText(this.stylesPath));
188+
}
189+
190+
// Prepend all CSS rules with :host to avoid conflicts.
191+
if (!this.cssCode || this.cssCode.includes(':host')) {
192+
return;
193+
}
194+
195+
this.cssCode = CoreDom.prefixCSS(this.cssCode, ':host ::ng-deep', ':host');
196+
}
197+
166198
/**
167199
* Get a class that defines the dynamic component.
168200
*

src/core/features/compile/services/compile.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,19 +175,25 @@ export class CoreCompileProvider {
175175
* @param componentClass The JS class of the component.
176176
* @param viewContainerRef View container reference to inject the component.
177177
* @param extraImports Extra imported modules if needed and not imported by this class.
178+
* @param styles CSS code to apply to the component.
178179
* @returns Promise resolved with the component reference.
179180
*/
180181
async createAndCompileComponent<T = unknown>(
181182
template: string,
182183
componentClass: Type<T>,
183184
viewContainerRef: ViewContainerRef,
184185
extraImports: any[] = [], // eslint-disable-line @typescript-eslint/no-explicit-any
186+
styles?: string,
185187
): Promise<ComponentRef<T> | undefined> {
186188
// Import the Angular compiler to be able to compile components in runtime.
187189
await import('@angular/compiler');
188190

189191
// Create the component using the template and the class.
190-
const component = Component({ template, host: { 'compiled-component-id': String(this.componentId++) } })(componentClass);
192+
const component = Component({
193+
template,
194+
host: { 'compiled-component-id': String(this.componentId++) },
195+
styles,
196+
})(componentClass);
191197

192198
const lazyImports = await Promise.all(this.LAZY_IMPORTS.map(getModules => getModules()));
193199
const imports = [

src/core/features/siteplugins/classes/call-ws-directive.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ export class CoreSitePluginsCallWSBaseDirective implements OnInit, OnDestroy {
127127
}
128128

129129
/**
130-
* Directive destroyed.
130+
* @inheritdoc
131131
*/
132132
ngOnDestroy(): void {
133133
this.invalidateObserver?.unsubscribe();

src/core/features/siteplugins/constants.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,7 @@
1313
// limitations under the License.
1414

1515
export const CORE_SITE_PLUGINS_UPDATE_COURSE_CONTENT = 'siteplugins_update_course_content';
16+
17+
export const CORE_SITE_PLUGINS_COMPONENT = 'CoreSitePlugins';
18+
19+
export const CORE_SITE_PLUGINS_PATH = 'siteplugins';

0 commit comments

Comments
 (0)