latex.cljs 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. (ns frontend.extensions.latex
  2. (:require [frontend.config :as config]
  3. [frontend.handler.plugin :refer [hook-extensions-enhancers-by-key] :as plugin-handler]
  4. [frontend.loader :as loader]
  5. [frontend.ui :as ui]
  6. [frontend.util :as util]
  7. [goog.dom :as gdom]
  8. [promesa.core :as p]
  9. [rum.core :as rum]))
  10. ;; TODO: extracted to a rum mixin
  11. (defn loaded? []
  12. js/window.katex)
  13. (defonce *loading? (atom false))
  14. (defn render!
  15. [state]
  16. (let [[s _ display?] (:rum/args state)
  17. id (:id state)]
  18. (try
  19. (when-let [elem (gdom/getElement id)]
  20. (js/katex.render s elem
  21. #js {:displayMode display?
  22. :throwOnError false
  23. :strict false}))
  24. (catch :default e
  25. (js/console.error e)))))
  26. (defn- load-and-render!
  27. [state]
  28. (if (loaded?)
  29. (do
  30. (reset! *loading? false)
  31. (render! state))
  32. (when-not @*loading?
  33. (reset! *loading? true)
  34. (loader/load "/js/katex.min.js"
  35. (fn []
  36. (loader/load "/js/mhchem.min.js"
  37. (fn []
  38. (-> (when-let [enhancers (and config/lsp-enabled?
  39. (seq (hook-extensions-enhancers-by-key :katex)))]
  40. (for [{f :enhancer} enhancers]
  41. (when (fn? f) (f js/window.katex))))
  42. (p/all)
  43. (p/finally (fn []
  44. (reset! *loading? false)
  45. (render! state)))))))
  46. state))))
  47. (defn- state-&-load-and-render!
  48. [state]
  49. (load-and-render! state)
  50. state)
  51. (rum/defcs latex < rum/reactive
  52. {:init (fn [state]
  53. (assoc state :id (str (random-uuid))))
  54. :did-mount state-&-load-and-render!
  55. :did-update state-&-load-and-render!}
  56. [state s block? _display?]
  57. (let [id (:id state)
  58. loading? (rum/react *loading?)]
  59. (if loading?
  60. (ui/loading)
  61. (let [element (if block?
  62. :div.latex
  63. :span.latex-inline)]
  64. [element {:id id
  65. :class "initial"}
  66. [:span.opacity-0 s]]))))
  67. (defn html-export
  68. [s block? display?]
  69. (let [element (if block?
  70. :div.latex
  71. :span.latex-inline)]
  72. [element (if (or block? display?)
  73. (util/format "$$%s$$" s)
  74. ;; inline
  75. (util/format "$%s$" s))]))