katex.js 2.5 KB

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