org-static-mathjax.el 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. ;;; org-static-mathjax.el --- Muse-like tags in Org-mode
  2. ;;
  3. ;; Author: Jan Böker <jan dot boecker at jboecker dot de>
  4. ;; This elisp code integrates Static MathJax into the
  5. ;; HTML export process of Org-mode.
  6. ;;
  7. ;; The supporting files for this package are in contrib/scripts/staticmathjax
  8. ;; Please read the README.org file in that directory for more information.
  9. ;; To use it, evaluate it on startup, add the following to your .emacs:
  10. ;; (require 'org-static-mathjax)
  11. ;;
  12. ;; You will then have to customize the following two variables:
  13. ;; - org-static-mathjax-app-ini-path
  14. ;; - org-static-mathjax-local-mathjax-path
  15. ;;
  16. ;; If xulrunner is not in your $PATH, you will also need to customize
  17. ;; org-static-mathjax-xulrunner-path.
  18. ;;
  19. ;; If everything is setup correctly, you can trigger Static MathJax on
  20. ;; export to HTML by adding the following line to your Org file:
  21. ;; #+StaticMathJax: embed-fonts:nil output-file-name:"embedded-math.html"
  22. ;;
  23. ;; You can omit either argument.
  24. ;; embed-fonts defaults to nil. If you do not specify output-file-name,
  25. ;; the exported file is overwritten with the static version.
  26. ;;
  27. ;; If embed-fonts is non-nil, the fonts are embedded directly into the
  28. ;; output file using data: URIs.
  29. ;;
  30. ;; output-file-name specifies the file name of the static version. You
  31. ;; can use any arbitrary lisp form here, for example:
  32. ;; output-file-name:(concat (file-name-sans-extension buffer-file-name) "-static.html")
  33. ;;
  34. ;; The StaticMathJax XULRunner application expects a UTF-8 encoded
  35. ;; input file. If the static version displays random characters instead
  36. ;; of your math, add the following line at the top of your Org file:
  37. ;; -*- coding: utf-8; -*-
  38. ;;
  39. ;; License: GPL v2 or later
  40. (defcustom org-static-mathjax-app-ini-path
  41. (or (expand-file-name
  42. "../scripts/staticmatchjax/application.ini"
  43. (file-name-directory (or load-file-name buffer-file-name)))
  44. "")
  45. "Path to \"application.ini\" of the Static MathJax XULRunner application.
  46. If you have extracted StaticMathJax to e.g. ~/.local/staticmathjax, set
  47. this to ~/.local/staticmathjax/application.ini"
  48. :type 'string)
  49. (defcustom org-static-mathjax-xulrunner-path
  50. "xulrunner"
  51. "Path to your xulrunner binary"
  52. :type 'string)
  53. (defcustom org-static-mathjax-local-mathjax-path
  54. ""
  55. "Extract the MathJax zip file somewhere on your local
  56. hard drive and specify the path here.
  57. The directory has to be writeable, as org-static-mathjax
  58. creates a temporary file there during export."
  59. :type 'string)
  60. (defvar org-static-mathjax-debug
  61. nil
  62. "If non-nil, org-static-mathjax will print some debug messages")
  63. (defun org-static-mathjax-hook-installer ()
  64. "Installs org-static-mathjax-process in after-save-hook.
  65. Sets the following buffer-local variables for org-static-mathjax-process to pick up:
  66. org-static-mathjax-mathjax-path: The path to MathJax.js as used by Org HTML export
  67. org-static-mathjax-options: The string given with #+STATICMATHJAX: in the file"
  68. (let ((static-mathjax-option-string (plist-get opt-plist :static-mathjax)))
  69. (if static-mathjax-option-string
  70. (progn (set (make-local-variable 'org-static-mathjax-options) static-mathjax-option-string)
  71. (set (make-local-variable 'org-static-mathjax-mathjax-path)
  72. (nth 1 (assq 'path org-export-html-mathjax-options)))
  73. (let ((mathjax-options (plist-get opt-plist :mathjax)))
  74. (if mathjax-options
  75. (if (string-match "\\<path:" mathjax-options)
  76. (set 'org-static-mathjax-mathjax-path
  77. (car (read-from-string
  78. (substring mathjax-options (match-end 0))))))))
  79. (add-hook 'after-save-hook
  80. 'org-static-mathjax-process
  81. nil t)))))
  82. (defun org-static-mathjax-process ()
  83. (save-excursion
  84. ; some sanity checking
  85. (if (or (string= org-static-mathjax-app-ini-path "")
  86. (not (file-exists-p org-static-mathjax-app-ini-path)))
  87. (error "Static MathJax: You must customize org-static-mathjax-app-ini-path!"))
  88. (if (or (string= org-static-mathjax-local-mathjax-path "")
  89. (not (file-exists-p org-static-mathjax-local-mathjax-path)))
  90. (error "Static MathJax: You must customize org-static-mathjax-local-mathjax-path!"))
  91. ; define variables
  92. (let* ((options org-static-mathjax-options)
  93. (output-file-name buffer-file-name)
  94. (input-file-name (let ((temporary-file-directory (file-name-directory org-static-mathjax-local-mathjax-path)))
  95. (make-temp-file "org-static-mathjax-" nil ".html")))
  96. (html-code (buffer-string))
  97. (mathjax-oldpath (concat "src=\"" org-static-mathjax-mathjax-path))
  98. (mathjax-newpath (concat "src=\"" org-static-mathjax-local-mathjax-path))
  99. embed-fonts)
  100. ; read file-local options
  101. (mapc
  102. (lambda (symbol)
  103. (if (string-match (concat "\\<" (symbol-name symbol) ":") options)
  104. (set symbol (eval (car (read-from-string
  105. (substring options (match-end 0))))))))
  106. '(embed-fonts output-file-name))
  107. ; debug
  108. (when org-static-mathjax-debug
  109. (message "output file name, embed-fonts")
  110. (print output-file-name)
  111. (print embed-fonts))
  112. ; open (temporary) input file, copy contents there, replace MathJax path with local installation
  113. (with-temp-buffer
  114. (insert html-code)
  115. (goto-char 1)
  116. (replace-regexp mathjax-oldpath mathjax-newpath)
  117. (write-file input-file-name))
  118. ; prepare argument list for call-process
  119. (let ((call-process-args (list org-static-mathjax-xulrunner-path
  120. nil nil nil
  121. org-static-mathjax-app-ini-path
  122. input-file-name
  123. output-file-name)))
  124. ; if fonts are embedded, just append the --embed-fonts flag
  125. (if embed-fonts
  126. (add-to-list 'call-process-args "--embed-fonts" t))
  127. ; if fonts are not embedded, the XULRunner app must replace all references
  128. ; to the font files with the real location (Firefox inserts file:// URLs there,
  129. ; because we are using a local MathJax installation here)
  130. (if (not embed-fonts)
  131. (progn
  132. (add-to-list 'call-process-args "--final-mathjax-url" t)
  133. (add-to-list 'call-process-args
  134. (file-name-directory org-static-mathjax-mathjax-path)
  135. t)))
  136. ; debug
  137. (when org-static-mathjax-debug
  138. (print call-process-args))
  139. ; call it
  140. (apply 'call-process call-process-args)
  141. ; delete our temporary input file
  142. (kill-buffer)
  143. (delete-file input-file-name)
  144. (let ((backup-file (concat input-file-name "~")))
  145. (if (file-exists-p backup-file)
  146. (delete-file backup-file)))))))
  147. (add-to-list 'org-export-inbuffer-options-extra
  148. '("STATICMATHJAX" :static-mathjax))
  149. (add-hook 'org-export-html-final-hook 'org-static-mathjax-hook-installer)
  150. (provide 'org-static-mathjax)