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 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 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 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 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

@sobjornstad

This comment has been minimized.

Copy link

@sobjornstad sobjornstad commented Sep 26, 2020

After doing the replace @Jasonwi suggested, my wiki loads with no error and the plugin shows up in the Plugins list, but it doesn't actually render any Mathjax within my tiddlers. The console doesn't show any relevant errors. Am I missing something?

@christophM

This comment has been minimized.

Copy link

@christophM christophM commented Jan 7, 2021

The KaTeX plugin did the trick for me: https://tiddlywiki.com/plugins/tiddlywiki/katex/

@cartazio

This comment has been minimized.

Copy link

@cartazio cartazio commented Mar 29, 2021

is there an issue with changes between mathjax 2.3 vs mathjax3?

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