TracMathJaxPlugin / tracmathjax / tracmathjax.py

from genshi.builder import tag
from genshi.filters import Transformer

from trac.core import Component, implements
from trac.wiki.api import IWikiSyntaxProvider, IWikiMacroProvider
from trac.web.api import ITemplateStreamFilter

MACRO_DESCRIPTION = \
"""Renders a LaTeX using MathJax.

Usage:
{{{
{{{
#!latex
\left( \sum_{k=1}^n a_k b_k \\right)^{\!\!2} \leq
\left( \sum_{k=1}^n a_k^2 \\right) \left( \sum_{k=1}^n b_k^2 \\right)
}}}
}}}

results in output like:
{{{
#!latex
\left( \sum_{k=1}^n a_k b_k \\right)^{\!\!2} \leq
\left( \sum_{k=1}^n a_k^2 \\right) \left( \sum_{k=1}^n b_k^2 \\right)
}}}
"""

MATHJAX_DIR = "MathJax"
MATHJAX_JS = "MathJax.js"

#: Wiki syntax regular expression
WIKI_RE = r"(?P<mathjax_inline>\\\(.*?\\\)|\$\$.*?\$\$|\\\[.*?\\\])"


class TracMathJax(Component):
    implements(IWikiSyntaxProvider,
               IWikiMacroProvider,
               ITemplateStreamFilter)

    # ITemplateStreamFilter methods
    def filter_stream(self, req, method, filename, stream, data):
        address = tag.script(type="text/javascript", src="https://c328740.ssl.cf1.rackcdn.com/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML")
        stream |= Transformer('.//head').append(address)
        return stream

    # IWikiSyntaxProvider methods
    def get_wiki_syntax(self):
        # Capture text in between MathJax delimiters to keep other wiki syntax
        # from being applied.
        yield (WIKI_RE, self._render_inline)

    def get_link_resolvers(self):
        # we have no link resolvers
        return []

    # IWikiMacroProvider methods
    def get_macros(self):
        return ('latex', 'Latex', 'LaTeX')

    def get_macro_description(self, name):
        return MACRO_DESCRIPTION

    def expand_macro(self, formatter, name, content):
        if name.lower() == "latex":
            return "<p>\\[\n%s\n\\]</p>" % content

    def _render_inline(self, formatter, ns, match):
        """Inline rendering function."""
        return match.group("mathjax_inline")
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.