Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?
MathJax based LaTeX plugin for TiddlyWiki 5

LaTeX plugin for TiddlyWiki 5 (based on MathJax)

(based on http://mathjax-tw5.kantorsite.net/)

To use with NodeJS create a plugins/mathjax/ directory in your wiki containing the two files (plugin.info and init.js), i.e.

plugins/
   mathjax/
      plugin.info
      init.js
tiddlers/
tiddlywiki.info

or you could directly create a tiddler with a name like $:/plugins/kpe/mathjax/init.js and content-type application/javascript and module-type startup with the following content:

//
// create a new application/javascript tiddler with name
//   $:/plugins/kpe/mathjax/init.js
// and a field:
//    module-type  startup
// with the following content
//
 
/*\
title: $:/plugins/kpe/mathjax/init.js
type: application/javascript
module-type: startup

Adds LaTeX support through MathJax

\*/
(function(){

    /*jslint node: true, browser: true */
    /*global $tw: false, Element: false */
    "use strict";

    function appendScriptElement(fn, attr, done) {
        var head = document.getElementsByTagName('head')[0] || document.documentElement;
        var res = document.createElement('script');
        if(typeof fn == 'function') {
            res[window.opera?'innerHTML':'text'] = '('+fn.toString()+')()';
        } else if(typeof fn == 'string'){
            res.src = fn;
        }
        if(attr) {
            for(var aname in attr) {
                if(attr.hasOwnProperty(aname)) {
                    res[aname] = attr[aname];
                }
            }
        }
        var loaded = false;
        res.onload = res.onreadystatechange = function(){
            if(!loaded && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')) {
                loaded = true;
                res.onload = res.onreadystatechange = null;
                if(head && res.parentNode){
                    head.removeChild(res);
                }
                if(typeof done == 'function') {
                    done();
                }
            }
        };
        head.insertBefore(res, head.firstChild);
        return res;
    }


    // Export name and synchronous status
    exports.name = "mathjax";
    exports.platforms = ["browser"];
    exports.after = ["startup"];
    exports.synchronous = false;

    exports.startup = function() {
        appendScriptElement(function(){
            MathJax.Hub.Config({
                tex2jax: {
                    inlineMath: [
                        ['$','$'],
                        ['\\\\(','\\\\)']
                    ]
                }
            });
        }, {type: 'text/x-mathjax-config'});

        appendScriptElement('http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML', null, function(){
            appendScriptElement(function(){
                var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
                if(!MutationObserver) {
                    alert("MathJax plugin for TW5: Sorry, but current version of your browser is not supported!");
                } else {
                    var doMathJaxMagic = function(el,observe){
                        console.log('doing mathjax');
                        MathJax.Hub.Queue(["Typeset", MathJax.Hub].concat(el || []));
                    };
                    var editObserver = new MutationObserver(function(mrecs,obs){
                        mrecs.forEach(function(mrec){
                            [].forEach.call(mrec.addedNodes,function(node){
                                var className = node.className || '';
                                if(/tw-reveal/.test(className) && !node.hidden || node.nodeType == Node.TEXT_NODE) {
                                    var preview = node.parentNode.querySelector('.tw-tiddler-preview-preview');
                                    if(preview) {
                                        doMathJaxMagic(preview);
                                    }
                                }
                            });
                        });
                    });
                    var d = document.getElementsByClassName("story-river")[0];
                    var viewObserver = new MutationObserver(function(mrecs,obs){
                        mrecs.forEach(function(mrec){
                            [].forEach.call(mrec.addedNodes, function(node){
                                var className = node.className || '';
                                if(/tw-tiddler-view-frame/.test(className)) {
                                    console.log('new view frame');
                                    doMathJaxMagic(node);
                                } else if(/tw-tiddler-edit-frame/.test(className)) {
                                    console.log('new edit frame - start observing');
                                    var el = node.querySelector('.tw-keyboard');
                                    editObserver.observe(el,{subtree:false,childList:true});
                                }
                            });
                        });
                    });
                    viewObserver.observe(d,{subtree:false,childList:true});
                }
            });
        });
    };

})();
/*\
title: $:/plugins/kpe/mathjax/init.js
type: application/javascript
module-type: startup
Message handler for LaTeX support through MathJax
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false, Element: false */
"use strict";
function appendScriptElement(fn, attr, done) {
var head = document.getElementsByTagName('head')[0] || document.documentElement;
var res = document.createElement('script');
if(typeof fn == 'function') {
res[window.opera?'innerHTML':'text'] = '('+fn.toString()+')()';
} else if(typeof fn == 'string'){
res.src = fn;
}
if(attr) {
for(var aname in attr) {
if(attr.hasOwnProperty(aname)) {
res[aname] = attr[aname];
}
}
}
var loaded = false;
res.onload = res.onreadystatechange = function(){
if(!loaded && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')) {
loaded = true;
res.onload = res.onreadystatechange = null;
if(head && res.parentNode){
head.removeChild(res);
}
if(typeof done == 'function') {
done();
}
}
};
head.insertBefore(res, head.firstChild);
return res;
}
// Export name and synchronous status
exports.name = "mathjax";
exports.platforms = ["browser"];
exports.after = ["startup"];
exports.synchronous = false;
exports.startup = function() {
appendScriptElement(function(){
MathJax.Hub.Config({
tex2jax: {
inlineMath: [
['$','$'],
['\\\\(','\\\\)']
]
}
});
}, {type: 'text/x-mathjax-config'});
appendScriptElement('http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML', null, function(){
appendScriptElement(function(){
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
if(!MutationObserver) {
alert("MathJax plugin for TW5: Sorry, but current version of your browser is not supported!");
} else {
var doMathJaxMagic = function(el){
console.log('doing mathjax');
MathJax.Hub.Queue(["Typeset", MathJax.Hub].concat(el || []));
};
var editObserver = new MutationObserver(function(mrecs,obs){
mrecs.forEach(function(mrec){
[].forEach.call(mrec.addedNodes,function(node){
var className = node.className || '';
if(/tw-reveal/.test(className) && !node.hidden || node.nodeType == Node.TEXT_NODE) {
var preview = node.parentNode.querySelector('.tw-tiddler-preview-preview');
if(preview) {
doMathJaxMagic(preview);
}
}
});
});
});
var d = document.getElementsByClassName("story-river")[0];
var viewObserver = new MutationObserver(function(mrecs,obs){
mrecs.forEach(function(mrec){
[].forEach.call(mrec.addedNodes, function(node){
var className = node.className || '';
if(/tw-tiddler-view-frame/.test(className)) {
console.log('new view frame');
doMathJaxMagic(node);
} else if(/tw-tiddler-edit-frame/.test(className)) {
console.log('new edit frame - start observing');
var el = node.querySelector('.tw-keyboard');
editObserver.observe(el,{subtree:false,childList:true});
}
});
});
});
viewObserver.observe(d,{subtree:false,childList:true});
}
});
});
};
})();
{
"title": "$:/plugins/kpe/mathjax",
"description": "LaTeX plugin (through MathJax)",
"author": "kpe",
"core-version": ">=5.0.0"
}
@mardukbp

This comment has been minimized.

Show comment
Hide comment
@mardukbp

mardukbp Sep 29, 2014

Hello. I followed the instructions for installation and got this error: TypeError: Argument 1 of MutationObserver.observe is not an object. I'm in Firefox 32 using TW 5.1.2.

mardukbp commented Sep 29, 2014

Hello. I followed the instructions for installation and got this error: TypeError: Argument 1 of MutationObserver.observe is not an object. I'm in Firefox 32 using TW 5.1.2.

@sprowell

This comment has been minimized.

Show comment
Hide comment
@sprowell

sprowell Sep 28, 2016

@mardukbp This can be fixed by replacing story-river with tc-story-river on or about line 89. At least, works for me.

sprowell commented Sep 28, 2016

@mardukbp This can be fixed by replacing story-river with tc-story-river on or about line 89. At least, works for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment