Skip to content

Instantly share code, notes, and snippets.

@kpe
Last active March 29, 2021 21:36
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save kpe/cc0547b318e6f8d4ddaa to your computer and use it in GitHub Desktop.
Save kpe/cc0547b318e6f8d4ddaa to your computer and use it in GitHub Desktop.
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
Copy link

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

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

@sobjornstad
Copy link

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

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

@cartazio
Copy link

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