Sascha Schulz
2024-01-15 e6d18a25cc742cc4c70766d9949f8dae9a4569ce
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/**
 * A plugin which enables rendering of math equations inside
 * of reveal.js slides. Essentially a thin wrapper for KaTeX.
 *
 * @author Hakim El Hattab
 * @author Gerhard Burger
 */
export const KaTeX = () => {
    let deck;
 
    let defaultOptions = {
        version: 'latest',
        delimiters: [
            {left: '$$', right: '$$', display: true}, // Note: $$ has to come before $
            {left: '$', right: '$', display: false},
            {left: '\\(', right: '\\)', display: false},
            {left: '\\[', right: '\\]', display: true}
        ],
        ignoredTags: ['script', 'noscript', 'style', 'textarea', 'pre']
    }
 
    const loadCss = src => {
        let link = document.createElement('link');
        link.rel = 'stylesheet';
        link.href = src;
        document.head.appendChild(link);
    };
 
    /**
     * Loads a JavaScript file and returns a Promise for when it is loaded
     * Credits: https://aaronsmith.online/easily-load-an-external-script-using-javascript/
     */
    const loadScript = src => {
        return new Promise((resolve, reject) => {
            const script = document.createElement('script')
            script.type = 'text/javascript'
            script.onload = resolve
            script.onerror = reject
            script.src = src
            document.head.append(script)
        })
    };
 
    async function loadScripts(urls) {
        for(const url of urls) {
            await loadScript(url);
        }
    }
 
    return {
        id: 'katex',
 
        init: function (reveal) {
 
            deck = reveal;
 
            let revealOptions = deck.getConfig().katex || {};
 
            let options = {...defaultOptions, ...revealOptions};
            const {local, version, extensions, ...katexOptions} = options;
 
            let baseUrl = options.local || 'https://cdn.jsdelivr.net/npm/katex';
            let versionString = options.local ? '' : '@' + options.version;
 
            let cssUrl = baseUrl + versionString + '/dist/katex.min.css';
            let katexUrl = baseUrl + versionString + '/dist/katex.min.js';
            let mhchemUrl = baseUrl + versionString + '/dist/contrib/mhchem.min.js'
            let karUrl = baseUrl + versionString + '/dist/contrib/auto-render.min.js';
 
            let katexScripts = [katexUrl];
            if(options.extensions && options.extensions.includes("mhchem")) {
                katexScripts.push(mhchemUrl);
            }
            katexScripts.push(karUrl);
 
            const renderMath = () => {
                renderMathInElement(reveal.getSlidesElement(), katexOptions);
                deck.layout();
            }
 
            loadCss(cssUrl);
 
            // For some reason dynamically loading with defer attribute doesn't result in the expected behavior, the below code does
            loadScripts(katexScripts).then(() => {
                if( deck.isReady() ) {
                    renderMath();
                }
                else {
                    deck.on( 'ready', renderMath.bind( this ) );
                }
            });
 
        }
    }
 
};