|
1 | | -import { Injectable } from '@angular/core'; |
2 | | -import { Observable, ReplaySubject, Subject } from 'rxjs'; |
| 1 | +import { Observable } from 'rxjs'; |
3 | 2 |
|
4 | | -interface MathJaxConfig { |
| 3 | +export interface MathJaxConfig { |
5 | 4 | source: string; |
6 | 5 | id: string; |
7 | 6 | } |
8 | 7 |
|
9 | | -@Injectable({ |
10 | | - providedIn: 'root' |
11 | | -}) |
12 | | -export class MathService { |
| 8 | +export abstract class MathService { |
| 9 | + protected abstract mathJaxOptions: any; |
| 10 | + protected abstract mathJax: MathJaxConfig; |
| 11 | + protected abstract mathJaxFallback: MathJaxConfig; |
13 | 12 |
|
14 | | - private signal: Subject<boolean>; |
15 | | - |
16 | | - private mathJaxOptions = { |
17 | | - tex: { |
18 | | - inlineMath: [['$', '$'], ['\\(', '\\)']] |
19 | | - }, |
20 | | - svg: { |
21 | | - fontCache: 'global' |
22 | | - }, |
23 | | - startup: { |
24 | | - typeset: false |
25 | | - } |
26 | | - }; |
27 | | - |
28 | | - private mathJax: MathJaxConfig = { |
29 | | - source: 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js', |
30 | | - id: 'MathJaxScript' |
31 | | - }; |
32 | | - private mathJaxFallback: MathJaxConfig = { |
33 | | - source: 'assets/mathjax/mml-chtml.js', |
34 | | - id: 'MathJaxBackupScript' |
35 | | - }; |
36 | | - |
37 | | - constructor() { |
38 | | - |
39 | | - this.signal = new ReplaySubject<boolean>(); |
40 | | - |
41 | | - void this.registerMathJaxAsync(this.mathJax) |
42 | | - .then(() => this.signal.next(true)) |
43 | | - .catch(_ => { |
44 | | - void this.registerMathJaxAsync(this.mathJaxFallback) |
45 | | - .then(() => this.signal.next(true)) |
46 | | - .catch((error) => console.log(error)); |
47 | | - }); |
48 | | - } |
49 | | - |
50 | | - private async registerMathJaxAsync(config: MathJaxConfig): Promise<any> { |
51 | | - return new Promise<void>((resolve, reject) => { |
52 | | - |
53 | | - const optionsScript: HTMLScriptElement = document.createElement('script'); |
54 | | - optionsScript.type = 'text/javascript'; |
55 | | - optionsScript.text = `MathJax = ${JSON.stringify(this.mathJaxOptions)};`; |
56 | | - document.head.appendChild(optionsScript); |
57 | | - |
58 | | - const script: HTMLScriptElement = document.createElement('script'); |
59 | | - script.id = config.id; |
60 | | - script.type = 'text/javascript'; |
61 | | - script.src = config.source; |
62 | | - script.crossOrigin = 'anonymous'; |
63 | | - script.async = true; |
64 | | - script.onload = () => resolve(); |
65 | | - script.onerror = error => reject(error); |
66 | | - document.head.appendChild(script); |
67 | | - }); |
68 | | - } |
69 | | - |
70 | | - ready(): Observable<boolean> { |
71 | | - return this.signal; |
72 | | - } |
73 | | - |
74 | | - render(element: HTMLElement) { |
75 | | - (window as any).MathJax.typesetPromise([element]); |
76 | | - } |
| 13 | + protected abstract registerMathJaxAsync(config: MathJaxConfig): Promise<any>; |
| 14 | + abstract ready(): Observable<boolean>; |
| 15 | + abstract render(element: HTMLElement): void; |
77 | 16 | } |
0 commit comments