Skip to content

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.

Copy link

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.

Copy link

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.

@SeabassWells

This comment has been minimized.

Copy link

SeabassWells commented Oct 9, 2018

Hi, I tried to install this onto the current version of TW and received this message -

"Internal JavaScript Error
Well, this is embarrassing. It is recommended that you restart TiddlyWiki by refreshing your browser
Uncaught TypeError: Failed to execute 'observe' on 'MutationObserver': parameter 1 is not of type 'Node'."

@Jasonwi

This comment has been minimized.

Copy link

Jasonwi commented Jul 16, 2020

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

thx! it's work for me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.