LaTeX for TiddlyWiki – A MathJax Plugin

Update: The MathJax Plugin for TiddlyWiki has a new home: https://github.com/guyru/tiddlywiki-mathjax
Some time ago I came across MathJax, a nifty, Javascript based engine for displaying TeX and LaTeX equations. It works by “translating” the equation to MathML or HTML+CSS, so it works on all modern browsers. The result isn’t a raster image, like in most LaTeX solutions (e.g. MediaWiki), so it’s scales with the text around it. Furthermore, it’s quite easy to integrate as it doesn’t require any real installation, and you could always use MathJax’s own CDN, which makes things even simpler.

TiddlyWiki with the MathJaxPlugin

A tiddler with LaTeX equations.


I quickly realized MathJax will be a perfect fit for TiddlyWiki which is also based on pure Javascript. It will allow me to enter complex formulas in tiddlers and still be able to carry my wiki anywhere with me, independent of a real TeX installation. I searched the web for an existing MathJaX plugin for TiddlyWiki but I came up empty handed (I did find some links, but they referenced pages that no longer exist). So I regarded it as a nice opportunity to begin writing some plugins for TiddlyWiki and created the MathJaxPlugin which integrates MathJax with TiddlyWiki.

As I don’t have an online TiddlyWiki, you’ll won’t be able to import the plugin, instead you’ll have to install it manually (which is pretty simple).

Start by creating a new tiddler named MathJaxPlugin, and tag with systemConfig (this tag will tell TiddlyWiki to execute the JS code in the tiddler, thus making it a plugin. Now copy the following code to the tiddler content:

/***
|''Name:''|MathJaxPlugin|
|''Description:''|Enable LaTeX formulas for TiddlyWiki|
|''Version:''|1.0.1|
|''Date:''|Feb 11, 2012|
|''Source:''|http://www.guyrutenberg.com/2011/06/25/latex-for-tiddlywiki-a-mathjax-plugin|
|''Author:''|Guy Rutenberg|
|''License:''|[[BSD open source license]]|
|''~CoreVersion:''|2.5.0|

!! Changelog
!!! 1.0.1 Feb 11, 2012
* Fixed interoperability with TiddlerBarPlugin
!! How to Use
Currently the plugin supports the following delemiters:
* """\(""".."""\)""" - Inline equations
* """$$""".."""$$""" - Displayed equations
* """\[""".."""\]""" - Displayed equations
!! Demo
This is an inline equation \(P(E)   = {n \choose k} p^k (1-p)^{ n-k}\) and this is a displayed equation:
\[J_\alpha(x) = \sum_{m=0}^\infty \frac{(-1)^m}{m! \, \Gamma(m + \alpha + 1)}{\left({\frac{x}{2}}\right)}^{2 m + \alpha}\]
This is another displayed equation $$e=mc^2$$
!! Code
***/
//{{{
config.extensions.MathJax = {
  mathJaxScript : "http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML",
  // uncomment the following line if you want to access MathJax using SSL
  // mathJaxScript : "https://d3eoax9i5htok0.cloudfront.net/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML",
  displayTiddler: function(TiddlerName) {
    config.extensions.MathJax.displayTiddler_old.apply(this, arguments);
    MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
  }
};
 
jQuery.getScript(config.extensions.MathJax.mathJaxScript, function(){
    MathJax.Hub.Config({
      extensions: ["tex2jax.js"],
      "HTML-CSS": { scale: 100 }
    });
 
    MathJax.Hub.Startup.onload();
    config.extensions.MathJax.displayTiddler_old = story.displayTiddler;
    story.displayTiddler = config.extensions.MathJax.displayTiddler;
});
 
config.formatters.push({
	name: "mathJaxFormula",
	match: "\\\\\\[|\\$\\$|\\\\\\(",
	//lookaheadRegExp: /(?:\\\[|\$\$)((?:.|\n)*?)(?:\\\]|$$)/mg,
	handler: function(w)
	{
		switch(w.matchText) {
		case "\\[": // displayed equations
			this.lookaheadRegExp = /\\\[((?:.|\n)*?)(\\\])/mg;
			break;
		case "$$": // inline equations
			this.lookaheadRegExp = /\$\$((?:.|\n)*?)(\$\$)/mg;
			break;
		case "\\(": // inline equations
			this.lookaheadRegExp = /\\\(((?:.|\n)*?)(\\\))/mg;
			break;
		default:
			break;
		}
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
			createTiddlyElement(w.output,"span",null,null,lookaheadMatch[0]);
			w.nextMatch = this.lookaheadRegExp.lastIndex;
		}
	}
});
//}}}

After saving the tiddler, reload the wiki and the MathJaxPlugin should be active. You can test it by creating a new tiddler with some equations in it:

This is an inline equation $$P(E)   = {n \choose k} p^k (1-p)^{ n-k}$$ and this is a displayed equation:
\[J_\alpha(x) = \sum_{m=0}^\infty \frac{(-1)^m}{m! \, \Gamma(m + \alpha + 1)}{\left({\frac{x}{2}}\right)}^{2 m + \alpha}\]

Which should result in the tiddler that appears in the above image.

Update 2011-08-19: Removed debugging code from the plugin.

Changelog 1.0.1 (Feb 11, 2012

  • Applied Winter Young’s fix for interoperability with other plugins (mainly TiddlerBarPlugin

60 thoughts on “LaTeX for TiddlyWiki – A MathJax Plugin

  1. Jackson

    Thanks for this code and guide. I am very new to TiddlyWiki. What would be the best way to be able to use MathJax.js offline. I see that it calls upon a web address to use this. Ideally I would like my TiddlyWiki to be completely usable offline. Thanks again.

    -Jackson

  2. Guy Post author

    You should make a local installation of MathJax right next to your TiddlyWiki. MathJax is served statically so it shouldn’t be a problem. Next you should set the MathJax url in the plugin’s source to the relative path to the MathJax installation.

  3. Markus

    Hi Guy,
    thank you for this very important Plugin!
    I just started using a TiddlyWiki as a LabNotebook, so your plugin ist perfect for it!
    But unfortunately it seems to interfere with TiddlerBarPlugin, which opens each new Tiddler in a Browser-like tab.
    Since i am a absolute beginner in javascript, i’m helpless there.
    Do you have any tip for me?

    Thanks Markus

  4. Zelhar

    Thanks allot for the plugin, it certainly adds functionality to TiddlyWiki.

    When I use it on my browser (firefox 6 beta) I see no difference between “inline” and “displayed”. In both cases the formula is centered and with the same font size.

  5. Zelhar

    A follow up to Jackson’s question:

    I tried to implement and it didn’t work. I put the link as:
    “/mathjax/MathJax.js?config=TeX-AMS-MML_HTMLorMML”

    (mathjax is a folder on the same level as my tiddlywiki)

  6. Georg

    @Jackson & Zelhar:

    I tried it too and it did not work so far. Have you got any further?

  7. Milind

    I also tried to do it offline but it just doesn’t work. I tried giving the absolute path but nothing. Anyway it would be really great if someone can create a plugin for MathQuill for Tiddlywiki. It also allows easy editing for the equation rather than remembering the cumbersome latex syntax.

    http://mathquill.github.com/

  8. Guy Post author

    @Markus: I’ve never used TiddlerBarPlugin, so I didn’t check for conflicts.

    @Zelhar,Georg,Milind: I’ll be looking into it hopefully this weekend. Did anyone of you tried setting

    mathJaxScript : "mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"
    

    ? Note that there is no preceding slash.

  9. Guy Post author

    Ok, I looked into the issue and I solved it. Replace the line:

    mathJaxScript : "http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML",
    

    with

    mathJaxScript : "mathjax/MathJax.js?config=TeX-AMS-MML_HTMLorMML",
    

    and replace the this block

    jQuery.getScript(config.extensions.MathJax.mathJaxScript, function(){
        MathJax.Hub.Config({
          extensions: ["tex2jax.js"],
          "HTML-CSS": { scale: 100 }
        });
     
        MathJax.Hub.Startup.onload();
        story.displayTiddler = config.extensions.MathJax.displayTiddler;
    });
    

    with

    var mathjax_script = document.createElement('script');
    mathjax_script.setAttribute('type', 'text/javascript');
    mathjax_script.setAttribute('src', config.extensions.MathJax.mathJaxScript);
    mathjax_script.onload = function() {
        MathJax.Hub.Config({
          extensions: ["tex2jax.js"],
          "TML-CSS": { scale: 100 }
        });
     
        MathJax.Hub.Startup.onload();
        story.displayTiddler = config.extensions.MathJax.displayTiddler;
    };
    document.getElementsByTagName('head')[0].appendChild(mathjax_script);
    

    This should work. I assumed that the MathJax is installed at a directory named “mathjax” right next to the TiddlyWiki file. If it isn’t the case, you should adjust it to point to the MathJax.js file correctly.

    The problem was that the original script used AJAX to fetch the MathJax code, and thus was limited by the Same-Origin policy. The new version bypasses it.

  10. Georg

    Well done. It nearly works now.
    At my place, it renders math only for the first tiddler opened after loading the wiki. It does not render math for all other tiddlers.

  11. Tom

    Hey Guy! First, thank you very much for this post. This is by far, the best LaTeX solution that I have found for TiddlyWiki.

    I would just like to reiterate Zelhar’s earlier comment. While in the documentation says that $$…$$ makes an inline equation, it displays more like a block/display equation. However if one makes a \(…\) inline equation, it displays as a true inline equation as expected. Is this a problem with MathJax or with the configuration (something that we can change.) Attached is an image to demonstrate how it is working on a test TiddlyWiki (blank except that it’s using MathJax and MPTW.)

    http://dl.dropbox.com/u/5725314/mathjax_tiddlywiki.png

    This is of course only a minor detail to an otherwise wonderful plugin. Thanks Guy!

  12. Deepak

    Every couple of months or, for the past two years, I have googled “tiddlywiki + mathjax”. You’ve helped make my dream come true. Goodbye jsmath, hello mathjax. But, let us not forget Bob McElrath (jsmath) who allowed tiddlywiki to be turned into a scientific note taking platform.

  13. john

    This is brilliant!
    Thanks very much for this wonderful plugin.

    p.s. Is there any way packages and/or to define global newcommands? (For example if I want a command \C for \mathbb{C})

  14. Sam Kearns

    First up, thanks for an awesome plugin! I’ve only been using it for one afternoon but so far so good.

    After installing LaTeX for TiddlyWiki of course I then immediately wanted a “live preview” so I searched, found and installed the PreviewPlugin by Eric Shulman. At first it worked! but then as soon as you start editing the rendered formulas in the preview window vanish and you just see the plain unrendered LaTeX code. 🙁

    So I dug into the source of the two plugins and found the problem. LaTeX for TiddlyWiki only tells Tiddly Wiki to process Math formulas when a Tiddler is first displayed, but PreviewPlugin is changing a Tiddler after inital display. So here is the solution:

    In the LaTeX for TiddlyWiki plugin you will see this line of code…
    MathJax.Hub.Queue(["Typeset", MathJax.Hub]);

    That code needs to also be added to the PreviewPlugin code in the “render” function right after the “wikify” command at line 60. There is only one line in the whole plugin code that starts with “wikify” so if you see it then you know you have the right place, just add that line above right after that one and it should work!

    Wheee!

  15. Sam Kearns

    OK so now that I’ve used it for a day I’ve run into another problem. After entering just a few formulae into a single Tiddler editor, the preview becomes very slow to render (500ms+ (I am using a netbook)). Since you can’t type while the preview is rendering, and every keystroke triggers a re-render, this makes typing in the editor window extremely clunky and frustrating.

    My fix to this problem was to make a small change to the PreviewPlugin code so that instead of updating the preview on every keystroke, it only updates when you have stopped typing for a moment. Here is how to do it.

    Edit the tiddler that contains the PreviewPlugin code and locate the following code at lines 33 to 36


    ta.onkeyup=function(ev) {
    if (this.saved_onkeyup) this.saved_onkeyup.apply(this,arguments);
    config.macros.preview.render(this.id,this.getAttribute("previewid"));
    }

    Replace that code with the following code

    ta.onkeyup=function(ev) {
    if (this.saved_onkeyup) this.saved_onkeyup.apply(this,arguments);
    if (this.render_timer !== null) {
    clearTimeout(this.render_timer);
    }
    var that = this;
    this.render_timer = setTimeout( function() {
    config.macros.preview.render(that.id,that.getAttribute("previewid"));
    },
    1000 // Preview timeout in milliseconds
    );
    }

    Save the tiddler, save the wiki and reload the browser window. Editing formulae with live preview should now be a lot nicer to use.

    You can adjust the length of time it waits for more keystrokes before updating the preview. In the code listed above, you will notice the number 1000 on the 3rd last line, this is the number of milliseconds it will wait after the last keystroke before updating the preview. Changing this number to 500, for example, will decrease the time-out to half a second, 2000 will make it 2 seconds, etc.

    Hope this helps! 🙂

  16. Winter Young

    Hi, this article is great, saved my ass! Thanks a lot!

    But there’s a bug that caused this plugin can interfere with other plugins, like TiddlersBarPlugin. The problem is about the timing of overriding story.displayTiddler.

    The process that backs up the original displayTiddler function should be done at the moment the overriding actually takes place instead of being done at the plugin loading stage.

    The fix is to add this statement

    config.extensions.MathJax.displayTiddler_old = story.displayTiddler;
    

    before

    story.displayTiddler = config.extensions.MathJax.displayTiddler;
    

    and delete the statement

    displayTiddler_old = story.displayTiddler;
    
  17. rafi

    Hi,

    I am new to tiddlywiki. I’ve copied the plugin and installed mathjax (which works). However, when I’ve copied the example I did not see the Latex formula just the Tex script.

    Any idea why?

    Thanks,

  18. Guy Post author

    I updated the plugin to reflect Winter Young’s fixes.

    @Zelhar, @Tom: I made a mistake (now fixed), $$..$$ mark a displayed equation. This can be fixed by adding the following line

    tex2jax: {inlineMath: [['$$','$$'], ['\\(','\\)']]}
    

    to the MathJaxHub.Config line.

    @Rafi: Did you reload the wiki after adding the plugin?

    I’ve also just checked the plugin with mGSD (formerly monkeyGTD) and it works as well.

  19. secobi

    Excellent work here! The online mode works beautifully but I’m having trouble using/setting-up the offline mode. I tried your patch, and the MathJax folder is beside the TiddlyWiki file, but when I replace the block of code my TiddlyWiki file breaks: the page loads up fine but I’m no longer able to open, edit or create any tiddler, however the “backstage” seems to still work or at least I can interact with it. I use Chrome and I know there are some particulars involved with that but I also tried to open it with Firefox after editing and I encountered the same problem.

    I know very little about JS but it appears as though something in code block is being interpreted as being left open and..

    mathjax_script.onload = function() {
    MathJax.Hub.Config({
    extensions: ["tex2jax.js"],
    "TML-CSS": { scale: 100 }
    });

    MathJax.Hub.Startup.onload();
    story.displayTiddler = config.extensions.MathJax.displayTiddler;
    };

    this part of the block seemed like it could be the culprit but I don’t know what alternatives to try for myself.

  20. Guy Post author

    Are you sure you copied and replaced everything correctly? No leftover braces/parentheses?

  21. Ben

    How do i modify the code to enable single dollar signs for inline equations? i prefer to use $ rather than \(.

    Thank you very much.

  22. Ben

    I am complete noob, where exactly do i add it? Any paranthesis, commas, etc.? Tried couple things, no luck yet.

  23. Guy Post author

    Add the tex2jax line to the MathJax.Hub.Config part so it will look exactly like this:

        MathJax.Hub.Config({
          tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]},
          extensions: ["tex2jax.js"],
          "TML-CSS": { scale: 100 }
        });
    

    It will allow you to use single $ sign instead of double.

  24. Eric

    @Guy: You’ve integrated it perfectly, zero effort required on my part. Thank you so much for taking the time to do this and to do it right.

  25. Steven

    This is amazing, got it to work as advertised for online mathjax (it makes for an amazing contribution to a maths study wiki). I can’t seem to get it to work for local/offline mathjax though.

    I have exactly the same problem as secobi – as soon as I implement the changes specified it stops me being able to edit anything. The code I have pasted is
    http://pastebin.com/mhGsnPHi

    and using the latest version of mathjax and tiddlywiki.

  26. PaulH

    Great tool. Everything works except I was wondering if someone could help me with setting the font. The formulas are all produced at the same font as the surrounding text. I have tried statements such as $$…$$ but it does not change the font. Any sugestions?

  27. PaulH

    Sorry, the rendering on this site wiped out my span tags surrounding $$…$$ where I had set the font.

  28. Guy Post author

    Have you read MathJax’ documentation? I tend to think changing the font is possible via some configuration for MathJax itself.

  29. PaulH

    For anybody who has problems with the size of the rendered symbols change the plugin by finding the line that says:
    createTiddlyElement(w.output, …)
    and change it to
    var elm = createTiddlyElement(w.output, …)
    elm.style.fontSize=”200%”;

  30. van

    I just want to install the MathJax locally. As mentioned above by @Guy, the installation should right next to the tiddlywiki, and update the mathjax src in your plugin, the result is mathjax tell me failed to load (failed to load : extensions …), while I try to replace the jquery part with your provided code, then I can’t open any tiddly any more! I guess there has some compatibility problems…

    by the way, my tiddly version is 2.6.3

  31. Guy Post author

    I guess that it’s possible, you’ll have to check MathJax documentation and update the place where the plugin initializes the library.

  32. tobibeer

    @PaulH,

    Better use a class…


    var elm = createTiddlyElement(w.output, …)
    elm.setAttribute('class',elm.className + ' mathjax')

    …and then use your StyleSheet tiddler!

    @Guy

    Great stuff!

    Please consider creating a TiddlySpace o shake hands with IgorP for publishing your plugin and documenting all the possible tweaks. Way better than following up only through comments.

    If that’s not too much to ask, also create a plugin-only space which only contains the plugin itself and a pointer to the documentation space… not even the system-xyz spaces, except system-plugins.

  33. Thomas Gettys

    I followed your directions, and embedded the test code in a tiddler and it all worked – very cool!

    however, I have been unsuccessful in getting anything myself to work. if I enter:
    \[\sqrt{d}\]
    I see a squareroot of d displayed, centered on the screen. if I enter only:
    \sqrt{d}
    it is not interpreted.

    What am I missing?

  34. Guy Post author

    @tobibear It does sound like a good way to publish it. I’m a bit short of time lately, but I’ll put it on my task list.

  35. zelhar

    Is there a way to stop tiddlywiki to use its wikiformatting for content that is between mathjax brace $$—-$$, \(—-\) etc. ?

    There is collision between the wiki syntax and the asciimathml syntax, and perhaps there are some collisions between wiki syntax to latex which I haven’t found out yet.

    Example:
    ` A ^^^ B` messes up the entire tiddler.

Leave a Reply

Your email address will not be published. Required fields are marked *

 

This site uses Akismet to reduce spam. Learn how your comment data is processed.