97 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			97 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
|  * 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 ) );
 | |
| 				}
 | |
| 			});
 | |
| 
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| };
 |