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