From 4a028cc7c0bf1a23d45ef05b954f89c4eb1e644a Mon Sep 17 00:00:00 2001 From: Carsten Dominik Date: Fri, 20 Aug 2010 18:12:59 +0200 Subject: [PATCH] Add org-static-mathjax to the contrib directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks to Jan Böker for this contribution. --- contrib/lisp/org-static-mathjax.el | 171 +++++++++++++++ contrib/scripts/staticmathjax/.gitignore | 1 + contrib/scripts/staticmathjax/README.org | 79 +++++++ contrib/scripts/staticmathjax/README.txt | 91 ++++++++ contrib/scripts/staticmathjax/application.ini | 11 + .../staticmathjax/chrome/chrome.manifest | 1 + .../staticmathjax/chrome/content/main.js | 198 ++++++++++++++++++ .../staticmathjax/chrome/content/main.xul | 11 + .../defaults/preferences/prefs.js | 1 + 9 files changed, 564 insertions(+) create mode 100644 contrib/lisp/org-static-mathjax.el create mode 100644 contrib/scripts/staticmathjax/.gitignore create mode 100644 contrib/scripts/staticmathjax/README.org create mode 100644 contrib/scripts/staticmathjax/README.txt create mode 100644 contrib/scripts/staticmathjax/application.ini create mode 100644 contrib/scripts/staticmathjax/chrome/chrome.manifest create mode 100644 contrib/scripts/staticmathjax/chrome/content/main.js create mode 100644 contrib/scripts/staticmathjax/chrome/content/main.xul create mode 100644 contrib/scripts/staticmathjax/defaults/preferences/prefs.js diff --git a/contrib/lisp/org-static-mathjax.el b/contrib/lisp/org-static-mathjax.el new file mode 100644 index 000000000..6a9f0ecb2 --- /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 + +;; 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 "\\ + +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 > + + + 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 :: + 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 000000000..cbcaea117 --- /dev/null +++ b/contrib/scripts/staticmathjax/README.txt @@ -0,0 +1,91 @@ + Static MathJax v0.1 README + ========================== + +Author: Jan Böcker +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 > + + + 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 : + 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 000000000..d7957b0ec --- /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 000000000..a05d8c8ff --- /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 000000000..2e71f3b24 --- /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 tag + try{ + var scriptTags = docFrame.contentDocument.getElementsByTagName("script"); + for (var i=0; i + + + + +