summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Dominik <carsten.dominik@gmail.com>2010-08-20 18:12:59 +0200
committerCarsten Dominik <carsten.dominik@gmail.com>2010-08-20 18:12:59 +0200
commit4a028cc7c0bf1a23d45ef05b954f89c4eb1e644a (patch)
tree6e10625199ffbcc4f49c48e92c5e837c2105c4de
parent190e88cfc9478e994bfa8b4c82c2a4cc96b6c959 (diff)
downloadorg-mode-4a028cc7c0bf1a23d45ef05b954f89c4eb1e644a.tar.gz
Add org-static-mathjax to the contrib directory
Thanks to Jan Böker for this contribution.
-rw-r--r--contrib/lisp/org-static-mathjax.el171
-rw-r--r--contrib/scripts/staticmathjax/.gitignore1
-rw-r--r--contrib/scripts/staticmathjax/README.org79
-rw-r--r--contrib/scripts/staticmathjax/README.txt91
-rw-r--r--contrib/scripts/staticmathjax/application.ini11
-rw-r--r--contrib/scripts/staticmathjax/chrome/chrome.manifest1
-rw-r--r--contrib/scripts/staticmathjax/chrome/content/main.js198
-rw-r--r--contrib/scripts/staticmathjax/chrome/content/main.xul11
-rw-r--r--contrib/scripts/staticmathjax/defaults/preferences/prefs.js1
9 files changed, 564 insertions, 0 deletions
diff --git a/contrib/lisp/org-static-mathjax.el b/contrib/lisp/org-static-mathjax.el
new file mode 100644
index 0000000..6a9f0ec
--- /dev/null
+++ b/contrib/lisp/org-static-mathjax.el
@@ -0,0 +1,171 @@
+;;; org-static-mathjax.el --- Muse-like tags in Org-mode
+;;
+;; Author: Jan Böker <jan dot boecker at jboecker dot de>
+
+;; This elisp code integrates Static MathJax into the
+;; HTML export process of Org-mode.
+;;
+;; The supporting files for this package are in contrib/scripts/staticmathjax
+;; Please read the README.org file in that directory for more information.
+
+;; To use it, evaluate it on startup, add the following to your .emacs:
+
+;; (require 'org-static-mathjax)
+;;
+;; You will then have to customize the following two variables:
+;; - org-static-mathjax-app-ini-path
+;; - org-static-mathjax-local-mathjax-path
+;;
+;; If xulrunner is not in your $PATH, you will also need to customize
+;; org-static-mathjax-xulrunner-path.
+;;
+;; If everything is setup correctly, you can trigger Static MathJax on
+;; export to HTML by adding the following line to your Org file:
+;; #+StaticMathJax: embed-fonts:nil output-file-name:"embedded-math.html"
+;;
+;; You can omit either argument.
+;; embed-fonts defaults to nil. If you do not specify output-file-name,
+;; the exported file is overwritten with the static version.
+;;
+;; If embed-fonts is non-nil, the fonts are embedded directly into the
+;; output file using data: URIs.
+;;
+;; output-file-name specifies the file name of the static version. You
+;; can use any arbitrary lisp form here, for example:
+;; output-file-name:(concat (file-name-sans-extension buffer-file-name) "-static.html")
+;;
+;; The StaticMathJax XULRunner application expects a UTF-8 encoded
+;; input file. If the static version displays random characters instead
+;; of your math, add the following line at the top of your Org file:
+;; -*- coding: utf-8; -*-
+;;
+;; License: GPL v2 or later
+
+(defcustom org-static-mathjax-app-ini-path
+ (or (expand-file-name
+ "../scripts/staticmatchjax/application.ini"
+ (file-name-directory (or load-file-name buffer-file-name)))
+ "")
+ "Path to \"application.ini\" of the Static MathJax XULRunner application.
+If you have extracted StaticMathJax to e.g. ~/.local/staticmathjax, set
+this to ~/.local/staticmathjax/application.ini"
+ :type 'string)
+
+(defcustom org-static-mathjax-xulrunner-path
+ "xulrunner"
+ "Path to your xulrunner binary"
+ :type 'string)
+
+(defcustom org-static-mathjax-local-mathjax-path
+ ""
+ "Extract the MathJax zip file somewhere on your local
+hard drive and specify the path here.
+
+The directory has to be writeable, as org-static-mathjax
+creates a temporary file there during export."
+ :type 'string)
+
+(defvar org-static-mathjax-debug
+ nil
+ "If non-nil, org-static-mathjax will print some debug messages")
+
+(defun org-static-mathjax-hook-installer ()
+ "Installs org-static-mathjax-process in after-save-hook.
+
+Sets the following buffer-local variables for org-static-mathjax-process to pick up:
+org-static-mathjax-mathjax-path: The path to MathJax.js as used by Org HTML export
+org-static-mathjax-options: The string given with #+STATICMATHJAX: in the file"
+ (let ((static-mathjax-option-string (plist-get opt-plist :static-mathjax)))
+ (if static-mathjax-option-string
+ (progn (set (make-local-variable 'org-static-mathjax-options) static-mathjax-option-string)
+ (set (make-local-variable 'org-static-mathjax-mathjax-path)
+ (nth 1 (assq 'path org-export-html-mathjax-options)))
+ (let ((mathjax-options (plist-get opt-plist :mathjax)))
+ (if mathjax-options
+ (if (string-match "\\<path:" mathjax-options)
+ (set 'org-static-mathjax-mathjax-path
+ (car (read-from-string
+ (substring mathjax-options (match-end 0))))))))
+ (add-hook 'after-save-hook
+ 'org-static-mathjax-process
+ nil t)))))
+
+
+(defun org-static-mathjax-process ()
+ (save-excursion
+ ; some sanity checking
+ (if (or (string= org-static-mathjax-app-ini-path "")
+ (not (file-exists-p org-static-mathjax-app-ini-path)))
+ (error "Static MathJax: You must customize org-static-mathjax-app-ini-path!"))
+ (if (or (string= org-static-mathjax-local-mathjax-path "")
+ (not (file-exists-p org-static-mathjax-local-mathjax-path)))
+ (error "Static MathJax: You must customize org-static-mathjax-local-mathjax-path!"))
+
+ ; define variables
+ (let* ((options org-static-mathjax-options)
+ (output-file-name buffer-file-name)
+ (input-file-name (let ((temporary-file-directory (file-name-directory org-static-mathjax-local-mathjax-path)))
+ (make-temp-file "org-static-mathjax-" nil ".html")))
+ (html-code (buffer-string))
+ (mathjax-oldpath (concat "src=\"" org-static-mathjax-mathjax-path))
+ (mathjax-newpath (concat "src=\"" org-static-mathjax-local-mathjax-path))
+ embed-fonts)
+ ; read file-local options
+ (mapc
+ (lambda (symbol)
+ (if (string-match (concat "\\<" (symbol-name symbol) ":") options)
+ (set symbol (eval (car (read-from-string
+ (substring options (match-end 0))))))))
+ '(embed-fonts output-file-name))
+
+ ; debug
+ (when org-static-mathjax-debug
+ (message "output file name, embed-fonts")
+ (print output-file-name)
+ (print embed-fonts))
+
+ ; open (temporary) input file, copy contents there, replace MathJax path with local installation
+ (with-temp-buffer
+ (insert html-code)
+ (goto-char 1)
+ (replace-regexp mathjax-oldpath mathjax-newpath)
+ (write-file input-file-name))
+
+ ; prepare argument list for call-process
+ (let ((call-process-args (list org-static-mathjax-xulrunner-path
+ nil nil nil
+ org-static-mathjax-app-ini-path
+ input-file-name
+ output-file-name)))
+ ; if fonts are embedded, just append the --embed-fonts flag
+ (if embed-fonts
+ (add-to-list 'call-process-args "--embed-fonts" t))
+ ; if fonts are not embedded, the XULRunner app must replace all references
+ ; to the font files with the real location (Firefox inserts file:// URLs there,
+ ; because we are using a local MathJax installation here)
+ (if (not embed-fonts)
+ (progn
+ (add-to-list 'call-process-args "--final-mathjax-url" t)
+ (add-to-list 'call-process-args
+ (file-name-directory org-static-mathjax-mathjax-path)
+ t)))
+
+ ; debug
+ (when org-static-mathjax-debug
+ (print call-process-args))
+ ; call it
+ (apply 'call-process call-process-args)
+ ; delete our temporary input file
+ (kill-buffer)
+ (delete-file input-file-name)
+ (let ((backup-file (concat input-file-name "~")))
+ (if (file-exists-p backup-file)
+ (delete-file backup-file)))))))
+
+(add-to-list 'org-export-inbuffer-options-extra
+'("STATICMATHJAX" :static-mathjax))
+
+(add-hook 'org-export-html-final-hook 'org-static-mathjax-hook-installer)
+
+
+(provide 'org-static-mathjax)
diff --git a/contrib/scripts/staticmathjax/.gitignore b/contrib/scripts/staticmathjax/.gitignore
new file mode 100644
index 0000000..b25c15b
--- /dev/null
+++ b/contrib/scripts/staticmathjax/.gitignore
@@ -0,0 +1 @@
+*~
diff --git a/contrib/scripts/staticmathjax/README.org b/contrib/scripts/staticmathjax/README.org
new file mode 100644
index 0000000..d28fc90
--- /dev/null
+++ b/contrib/scripts/staticmathjax/README.org
@@ -0,0 +1,79 @@
+Static MathJax v0.1 README
+#+AUTHOR: Jan Böcker <jan.boecker@jboecker.de>
+
+Static MathJax is a XULRunner application which loads a HTML input
+file that uses MathJax into a browser, waits until MathJax is done
+processing, and then writes the formatted result to an output HTML
+file.
+
+I have only tested exports from Emacs Org-mode as input files. (As of
+2010-08-14, MathJax is used by default with HTML exports in the
+current Org development version.)
+
+Optionally, references to the math fonts used will be converted to
+"data:" URIs, thus embedding the font data into the HTML file itself.
+(see [[http://en.wikipedia.org/wiki/Data_URI_scheme]])
+
+The code is licensed under the GNU General Public License version
+2, or, at your option, any later version.
+
+
+* Usage
+ To run Static MathJax, an existing XULRunner installation is
+ required. From the directory to which you unpacked Static MathJax,
+ run:
+
+ xulrunner application.ini <--embed-fonts | --final-mathjax-url <URL>>
+ <input file> <output file>
+
+ If you prefer to call "staticmathjax" instead of "xulrunner
+ application.ini", link xulrunner-stub into the directory:
+ ln /usr/lib/xulrunner-1.9.2.8/xulrunner-stub ./staticmathjax
+
+ - input file ::
+ name of the input file (the result of a HTML export
+ from Org-mode). It is assumed that this file uses the
+ UTF-8 character encoding.
+
+ - output file ::
+ name of the output file.
+
+ - --embed-fonts ::
+ if specified, the math fonts will be embedded into
+ the output file using data: URIs
+
+ - --final-mathjax-url <URL> ::
+ if --embed-fonts is not specified, this
+ must be the URL to a MathJax installation folder (e.g. "MathJax"
+ if MathJax is installed in a subdirectory, or
+ "http://orgmode.org/mathjax" to use the version hosted on the Org
+ website.
+
+ All references to math fonts in the output file will point to
+ this directory.
+
+* Caveats
+
+ The input file must not use a MathJax installation on the
+ web. Otherwise, due to a security feature of Firefox, MathJax will
+ fallback to image fonts. If you have unpacked MathJax to a
+ subdirectory "MathJax", specify the following in your Org file:
+
+ #+MathJax: path:"MathJax"
+
+ The math is rendered in Firefox, so MathJax applies its
+ Firefox-specific settings. When viewing the output files in other
+ browsers, it will look slightly different than the result that
+ running MathJax in that browser would produce.
+
+ Internet Explorer does not use the correct font, because it only
+ supports the EOT font format. For all other browsers (including
+ Firefox), MathJax uses the OTF font format.
+
+ Embedding fonts into the HTML file wastes some space due to the
+ base64 encoding used in data: URIs.
+
+ I have found no way to access stdout or set an exit code in an
+ XULRunner app, so any code which calls Static MathJax has no idea if
+ processing was successful and when an error occurs, graphical
+ message boxes are displayed.
diff --git a/contrib/scripts/staticmathjax/README.txt b/contrib/scripts/staticmathjax/README.txt
new file mode 100644
index 0000000..cbcaea1
--- /dev/null
+++ b/contrib/scripts/staticmathjax/README.txt
@@ -0,0 +1,91 @@
+ Static MathJax v0.1 README
+ ==========================
+
+Author: Jan Böcker <jan.boecker@jboecker.de>
+Date: 2010-08-15 13:53:39 CEST
+
+
+Static MathJax is a XULRunner application which loads a HTML input
+file that uses MathJax into a browser, waits until MathJax is done
+processing, and then writes the formatted result to an output HTML
+file.
+
+I have only tested exports from Emacs Org-mode as input files. (As of
+2010-08-14, MathJax is used by default with HTML exports in the
+current Org development version.)
+
+Optionally, references to the math fonts used will be converted to
+"data:" URIs, thus embedding the font data into the HTML file itself.
+(see [http://en.wikipedia.org/wiki/Data_URI_scheme])
+
+The code is licensed under the GNU General Public License version
+2, or, at your option, any later version.
+
+
+Table of Contents
+=================
+1 Usage
+2 Caveats
+
+
+1 Usage
+~~~~~~~~
+ To run Static MathJax, an existing XULRunner installation is
+ required. From the directory to which you unpacked Static MathJax,
+ run:
+
+ xulrunner application.ini <--embed-fonts | --final-mathjax-url <URL>>
+ <input file> <output file>
+
+ If you prefer to call "staticmathjax" instead of "xulrunner
+ application.ini", link xulrunner-stub into the directory:
+ ln /usr/lib/xulrunner-1.9.2.8/xulrunner-stub ./staticmathjax
+
+ input file:
+ name of the input file (the result of a HTML export
+ from Org-mode). It is assumed that this file uses the
+ UTF-8 character encoding.
+
+ output file:
+ name of the output file.
+
+ --embed-fonts:
+ if specified, the math fonts will be embedded into
+ the output file using data: URIs
+
+ --final-mathjax-url <URL>:
+ if --embed-fonts is not specified, this
+ must be the URL to a MathJax installation folder (e.g. "MathJax"
+ if MathJax is installed in a subdirectory, or
+ "[http://orgmode.org/mathjax]" to use the version hosted on the Org
+ website.
+
+ All references to math fonts in the output file will point to
+ this directory.
+
+2 Caveats
+~~~~~~~~~~
+
+ The input file must not use a MathJax installation on the
+ web. Otherwise, due to a security feature of Firefox, MathJax will
+ fallback to image fonts. If you have unpacked MathJax to a
+ subdirectory "MathJax", specify the following in your Org file:
+
+ #+MathJax: path:"MathJax"
+
+ The math is rendered in Firefox, so MathJax applies its
+ Firefox-specific settings. When viewing the output files in other
+ browsers, it will look slightly different than the result that
+ running MathJax in that browser would produce.
+
+ Internet Explorer does not use the correct font, because it only
+ supports the EOT font format. For all other browsers (including
+ Firefox), MathJax uses the OTF font format.
+
+ Embedding fonts into the HTML file wastes some space due to the
+ base64 encoding used in data: URIs.
+
+ I have found no way to access stdout or set an exit code in an
+ XULRunner app, so any code which calls Static MathJax has no idea if
+ processing was successful and when an error occurs, graphical
+ message boxes are displayed.
diff --git a/contrib/scripts/staticmathjax/application.ini b/contrib/scripts/staticmathjax/application.ini
new file mode 100644
index 0000000..d7957b0
--- /dev/null
+++ b/contrib/scripts/staticmathjax/application.ini
@@ -0,0 +1,11 @@
+[App]
+Vendor=Jan Boecker
+Name=StaticMathJax
+Version=0.2
+BuildID=2
+Copyright=Copyright (c) 2010 Jan Boecker
+ID=xulapp@jboecker.de
+
+[Gecko]
+MinVersion=1.8
+
diff --git a/contrib/scripts/staticmathjax/chrome/chrome.manifest b/contrib/scripts/staticmathjax/chrome/chrome.manifest
new file mode 100644
index 0000000..a05d8c8
--- /dev/null
+++ b/contrib/scripts/staticmathjax/chrome/chrome.manifest
@@ -0,0 +1 @@
+content staticmathjax file:content/
diff --git a/contrib/scripts/staticmathjax/chrome/content/main.js b/contrib/scripts/staticmathjax/chrome/content/main.js
new file mode 100644
index 0000000..2e71f3b
--- /dev/null
+++ b/contrib/scripts/staticmathjax/chrome/content/main.js
@@ -0,0 +1,198 @@
+var docFrame;
+var logtextbox;
+var destFile;
+var embedFonts = false;
+var finalMathJaxURL = null;
+
+function log(text)
+{
+ logtextbox.setAttribute("value", logtextbox.getAttribute("value") + "\n" + text);
+}
+
+function init()
+{
+ try {
+ docFrame = document.getElementById("docFrame");
+ logtextbox = document.getElementById("logtextbox");
+
+ // parse command line arguments
+ var cmdLine = window.arguments[0];
+ cmdLine = cmdLine.QueryInterface(Components.interfaces.nsICommandLine);
+
+ embedFonts = cmdLine.handleFlag("embed-fonts", false);
+ finalMathJaxURL = cmdLine.handleFlagWithParam("final-mathjax-url", false);
+
+ if (!embedFonts && !finalMathJaxURL) {
+ alert("You must eiher specify --embed-fonts or --final-mathjax-url");
+ window.close();
+ return;
+ }
+
+ sourceFilePath = cmdLine.getArgument(0);
+ destFilePath = cmdLine.getArgument(1);
+ if ( !sourceFilePath || !destFilePath ) {
+ alert("Not enough parameters, expecting two arguments:\nInput file, output file");
+ window.close();
+ return;
+ }
+
+ sourceFile = cmdLine.resolveFile(sourceFilePath);
+ if (! (sourceFile.exists() && sourceFile.isFile()) ) {
+ alert("Invalid source file path.");
+ window.close();
+ return;
+ }
+ sourceURI = cmdLine.resolveURI(sourceFilePath);
+
+ // create a nsIFile object for the output file
+ try{
+ destFile = cmdLine.resolveURI(destFilePath).QueryInterface(Components.interfaces.nsIFileURL).file;
+ }catch(e){
+ alert("Invalid destination file.\n\nException:\n" + e);
+ window.close();
+ return;
+ }
+
+ // add iframeLoaded() as an onload event handler, then navigate to the source file
+ docFrame.addEventListener("DOMContentLoaded", iframeLoaded, true);
+ docFrame.setAttribute("src", sourceURI.spec);
+
+ } catch (e) {
+ alert("Error in init():\n\n" + e);
+ window.close();
+ return;
+ }
+}
+
+function iframeLoaded()
+{
+ /*
+ // print every MathJax signal to the log
+ docFrame.contentWindow.MathJax.Hub.Startup.signal.Interest(
+ function (message) {log("Startup: "+message)}
+ );
+ docFrame.contentWindow.MathJax.Hub.signal.Interest(
+ function (message) {log("Hub: "+message)}
+ );
+ */
+
+ // tell MathJax to call serialize() when finished
+ docFrame.contentWindow.MathJax.Hub.Register.StartupHook("End", function() {serialize();});
+}
+
+function fileURLtoDataURI(url)
+{
+ var ios = Components.classes["@mozilla.org/network/io-service;1"]
+ .getService(Components.interfaces.nsIIOService);
+ var url_object = ios.newURI(url, "", null);
+ var file = url_object.QueryInterface(Components.interfaces.nsIFileURL).file;
+
+ var data = "";
+ var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"].
+ createInstance(Components.interfaces.nsIFileInputStream);
+ fstream.init(file, -1, -1, false);
+ var bstream = Components.classes["@mozilla.org/binaryinputstream;1"].
+ createInstance(Components.interfaces.nsIBinaryInputStream);
+ bstream.setInputStream(fstream);
+
+ var bytes = bstream.readBytes(bstream.available());
+ b64bytes = btoa(bytes);
+
+ return "data:;base64," + b64bytes;
+
+}
+
+function serialize()
+{
+ var MathJaxURL = docFrame.contentWindow.MathJax.Hub.config.root;
+
+ var searchURIList = new Array();
+ var replacementURIList = new Array();
+
+ log("serialize: preprocessing");
+
+ // remove the MathJax status message window
+ msgdiv = docFrame.contentDocument.getElementById("MathJax_Message");
+ msgdiv.parentNode.removeChild(msgdiv);
+
+ /* Loop through all CSS rules to find all @font-face rules.
+ At this point, they refer to local absolute paths using file:// URLs.
+ Replace them either with appropriate URLs relative to finalMathJaxURL
+ or with data URIs. */
+
+ for (var i = 0; i<docFrame.contentDocument.styleSheets.length; i++) {
+ var stylesheet = docFrame.contentDocument.styleSheets[i];
+
+ for (var j=0; j< stylesheet.cssRules.length; j++) {
+ var rule = stylesheet.cssRules[j];
+ if (rule.cssText.match("font-face")) {
+
+ url = rule.style.getPropertyValue("src");
+ url = url.match(/url\(\"(.+)\"\)/)[1];
+
+ // Since the properties seem read-only here, we populate
+ // searchURIList and replacementURIList to do text substitution
+ // after serialization
+ searchURIList.push(url);
+ if (embedFonts) {
+ replacementURIList.push(fileURLtoDataURI(url));
+ } else {
+ replacementURIList.push(url.replace(MathJaxURL, finalMathJaxURL));
+ }
+ }
+ }
+ }
+
+
+ // find and remove the MathJax <script> tag
+ try{
+ var scriptTags = docFrame.contentDocument.getElementsByTagName("script");
+ for (var i=0; i<scriptTags.length; i++) {
+ if (scriptTags[i].getAttribute("src") && scriptTags[i].getAttribute("src").match(/MathJax.js/i))
+ scriptTags[i].parentNode.removeChild(scriptTags[i]);
+ }
+ }catch(e){alert(e);}
+
+ log("serialize: serializing");
+
+ var serializer = new XMLSerializer();
+ var xhtml = serializer.serializeToString(docFrame.contentDocument);
+
+ log("serialize: postprocessing");
+ // make the MathJax URL relative again
+ // xhtml = xhtml.replace(findMathJaxURL, "MathJax");
+
+ try{
+ r1 = RegExp("&lt;!--/\\*--&gt;&lt;!\\[CDATA\\[/\\*&gt;&lt;!--\\*/", "g");
+ xhtml = xhtml.replace(r1, "");
+ r2 = RegExp("/\\*\\]\\]&gt;\\*/--&gt;", "g");
+ xhtml = xhtml.replace(r2, "");
+ r3 = RegExp("/\\*\\]\\]&gt;\\*///--&gt;", "g");
+ xhtml = xhtml.replace(r3, "");
+ }catch(e){alert(e);}
+ for (var i=0; i<searchURIList.length; i++)
+ xhtml = xhtml.replace(searchURIList[i], replacementURIList[i]);
+
+ save(xhtml);
+ window.close();
+}
+
+function save(xhtml)
+{
+ try {
+ var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"].
+ createInstance(Components.interfaces.nsIFileOutputStream);
+
+ foStream.init(destFile, 0x02 | 0x08 | 0x20, 0666, 0);
+ // write, create, truncate
+
+ // write in UTF-8 encoding
+ var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].
+ createInstance(Components.interfaces.nsIConverterOutputStream);
+ converter.init(foStream, "UTF-8", 0, 0);
+ converter.writeString(xhtml);
+ converter.close(); // this closes foStream
+ } catch (e) {
+ alert("Error in save():\n\n" + e);
+ }
+}
diff --git a/contrib/scripts/staticmathjax/chrome/content/main.xul b/contrib/scripts/staticmathjax/chrome/content/main.xul
new file mode 100644
index 0000000..35a00f2
--- /dev/null
+++ b/contrib/scripts/staticmathjax/chrome/content/main.xul
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<window onload="init();" id="main" title="Static MathJax" width="300" height="300"
+xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<script language="JavaScript" src="chrome://staticmathjax/content/main.js"/>
+
+ <browser flex="1" id="docFrame" src="" style="background-color:white;"/>
+ <textbox flex="1" id="logtextbox" multiline="true" style="display:none;"/>
+</window>
diff --git a/contrib/scripts/staticmathjax/defaults/preferences/prefs.js b/contrib/scripts/staticmathjax/defaults/preferences/prefs.js
new file mode 100644
index 0000000..0532ce0
--- /dev/null
+++ b/contrib/scripts/staticmathjax/defaults/preferences/prefs.js
@@ -0,0 +1 @@
+pref("toolkit.defaultChromeURI", "chrome://staticmathjax/content/main.xul");