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