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