Skip to content

Commit b46a87b

Browse files
atarix83Andrea Barbasso
authored andcommitted
[DURACOM-240] Assure the MathJax script has been registered before rendering
1 parent e8e77f5 commit b46a87b

4 files changed

Lines changed: 54 additions & 13 deletions

File tree

src/app/core/shared/client-math.service.ts

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
1-
import { Injectable } from '@angular/core';
1+
import { DOCUMENT } from '@angular/common';
2+
import {
3+
Inject,
4+
Injectable,
5+
} from '@angular/core';
26
import { Observable, ReplaySubject, Subject } from 'rxjs';
37
import { environment } from 'src/environments/environment';
4-
import { MathJaxConfig, MathService } from './math.service';
8+
import {
9+
NativeWindowRef,
10+
NativeWindowService,
11+
} from '../services/window.service';import { MathJaxConfig, MathService } from './math.service';
512

613
@Injectable({
714
providedIn: 'root'
815
})
16+
/**
17+
* Provide the MathService for CSR
18+
*/
919
export class ClientMathService extends MathService {
1020

1121
protected isReady$: Subject<boolean>;
@@ -31,7 +41,10 @@ export class ClientMathService extends MathService {
3141
id: 'MathJaxBackupScript'
3242
};
3343

34-
constructor() {
44+
constructor(
45+
@Inject(DOCUMENT) private _document: Document,
46+
@Inject(NativeWindowService) protected _window: NativeWindowRef,
47+
) {
3548
super();
3649

3750
this.isReady$ = new ReplaySubject<boolean>();
@@ -44,36 +57,49 @@ export class ClientMathService extends MathService {
4457
});
4558
}
4659

60+
/**
61+
* Register the specified MathJax script in the document
62+
*
63+
* @param config The configuration object for the script
64+
*/
4765
protected async registerMathJaxAsync(config: MathJaxConfig): Promise<any> {
4866
if (environment.markdown.mathjax) {
4967
return new Promise<void>((resolve, reject) => {
5068

51-
const optionsScript: HTMLScriptElement = document.createElement('script');
69+
const optionsScript: HTMLScriptElement = this._document.createElement('script');
5270
optionsScript.type = 'text/javascript';
5371
optionsScript.text = `MathJax = ${JSON.stringify(this.mathJaxOptions)};`;
54-
document.head.appendChild(optionsScript);
72+
this._document.head.appendChild(optionsScript);
5573

56-
const script: HTMLScriptElement = document.createElement('script');
74+
const script: HTMLScriptElement = this._document.createElement('script');
5775
script.id = config.id;
5876
script.type = 'text/javascript';
5977
script.src = config.source;
6078
script.crossOrigin = 'anonymous';
6179
script.async = true;
6280
script.onload = () => resolve();
6381
script.onerror = error => reject(error);
64-
document.head.appendChild(script);
82+
this._document.head.appendChild(script);
6583
});
6684
}
6785
return Promise.resolve();
6886
}
6987

88+
/**
89+
* Return the status of the script registration
90+
*/
7091
ready(): Observable<boolean> {
7192
return this.isReady$;
7293
}
7394

95+
/**
96+
* Render the specified element using the MathJax JavaScript
97+
*
98+
* @param element The element to render with MathJax
99+
*/
74100
render(element: HTMLElement) {
75101
if (environment.markdown.mathjax) {
76-
(window as any).MathJax.typesetPromise([element]);
102+
this._window.nativeWindow.MathJax.typesetPromise([element]);
77103
}
78104
}
79105
}

src/app/core/shared/math.service.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ export interface MathJaxConfig {
55
id: string;
66
}
77

8+
/**
9+
* This service is used to provide the MathJax library with the ability to render markdown code
10+
*/
811
export abstract class MathService {
912
protected abstract mathJaxOptions: any;
1013
protected abstract mathJax: MathJaxConfig;

src/app/core/shared/server-math.service.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import { MathJaxConfig, MathService } from './math.service';
55
@Injectable({
66
providedIn: 'root'
77
})
8+
/**
9+
* Provide the MathService for SSR
10+
*/
811
export class ServerMathService extends MathService {
912

1013
protected signal: Subject<boolean>;

src/app/shared/utils/markdown.directive.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,20 @@ import {
88
OnInit,
99
SecurityContext
1010
} from '@angular/core';
11-
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
11+
import {
12+
DomSanitizer,
13+
SafeHtml,
14+
} from '@angular/platform-browser';
15+
import { Subject } from 'rxjs';
16+
import {
17+
filter,
18+
take,
19+
takeUntil,
20+
} from 'rxjs/operators';
21+
22+
import { environment } from '../../../environments/environment';
1223
import { MathService } from '../../core/shared/math.service';
1324
import { isEmpty } from '../empty.util';
14-
import { environment } from '../../../environments/environment';
15-
import { Subject } from 'rxjs';
16-
import { take, takeUntil } from 'rxjs/operators';
1725

1826
const markdownItLoader = async () => (await import('markdown-it')).default;
1927
type LazyMarkdownIt = ReturnType<typeof markdownItLoader>;
@@ -33,8 +41,8 @@ export class MarkdownDirective implements OnInit, OnDestroy {
3341
el: HTMLElement;
3442

3543
constructor(
36-
protected sanitizer: DomSanitizer,
3744
@Inject(MARKDOWN_IT) private markdownIt: LazyMarkdownIt,
45+
protected sanitizer: DomSanitizer,
3846
private mathService: MathService,
3947
private elementRef: ElementRef) {
4048
this.el = elementRef.nativeElement;
@@ -66,6 +74,7 @@ export class MarkdownDirective implements OnInit, OnDestroy {
6674

6775
private renderMathjax() {
6876
this.mathService.ready().pipe(
77+
filter((ready) => ready),
6978
take(1),
7079
takeUntil(this.alive$)
7180
).subscribe(() => {

0 commit comments

Comments
 (0)