This is a quick and dirty implementation of allowing <math> LaTeX </math> to do formulae in Markdown. We'll call this page right here the "official site" for this extension I think.

It requires "latex" and "dvipng". I use MiKTeX on Win32 in particular, but I'm sure other types of them would work fine.

Finally, I've never written any Python before so please feel free to tidy/fix.

-- Scott http://h4ck3r.net

#!/usr/bin/env python

"""
Math extension for Python-Markdown
"""

import markdown
import os
import re
import md5

BEFORE_TEX = """\\documentclass[12pt]{article}
\\usepackage[latin1]{inputenc}
\\usepackage{amsmath}
\\usepackage{amsfonts}
\\usepackage{amssymb}
\\pagestyle{empty}
\\begin{document}
$"""

AFTER_TEX = """$
\\end{document}
"""

BLACKLIST = [
        "include",
        "def",
        "command",
        "loop",
        "repeat",
        "open",
        "toks",
        "output",
        "input",
        "catcode",
        "name",
        "^^",
        "\\every",
        "\\errhelp",
        "\\errorstopmode",
        "\\scrollmode",
        "\\nonstopmode",
        "\\batchmode",
        "\\read",
        "\\write",
        "csname",
        "\\newhelp",
        "\\uppercase",
        "\\lowercase",
        "\\relax",
        "\\aftergroup",
        "\\afterassignment",
        "\\expandafter",
        "\\noexpand",
        "\\special"
        ]



class MathPattern(markdown.Pattern):
    def __init__ (self, md):
        markdown.Pattern.__init__(self, r'(<|<)math>(.*)(<|<)/math>')
        self.md = md

    def getFnFromCode(self, code):
        hash = md5.new(code).hexdigest()
        matches = re.match("(.)(.)(.)(.*)", hash)
        dirs = "static\\images\\" + matches.group(1) + "\\" + matches.group(2) + "\\" + matches.group(3) + "\\"
        file = dirs + hash
        png = file + ".png"
        tex = file + ".tex"
        dvi = file + ".dvi"
        aux = file + ".aux"
        log = file + ".log"
        return (dirs, png, tex, dvi, aux, log)

    def handleMatch(self, m, doc):

        code = m.group(3).strip()
        code = code.replace("<", "<")
        code = code.replace(">", ">")

        (dirsb, pngb, texb, dvib, auxb, logb) = self.getFnFromCode(code)
        pngf = pngb.replace("\\", "/")

        def done(fn):
            img = doc.createElement('img')
            img.setAttribute("src", "/" + fn)
            img.setAttribute("alt", code)
            return img

        def error():
            err = doc.createElement("font")
            err.setAttribute("color", "red")
            err.appendChild(doc.createTextNode("error rendering: " + code))
            return err

        if os.path.exists(pngb): return done(pngf)

        def checker(x,y):
            if not x: return False
            return code.find(y) == -1
        if not reduce(checker, BLACKLIST, True):
            return error()

        if not os.path.exists(dirsb): os.makedirs(dirsb)
        f = open(texb, "w")
        f.writelines([BEFORE_TEX, code, AFTER_TEX])
        f.close()

        if os.system("latex -quiet -interaction=batchmode -output-directory=" + dirsb + " -aux-directory=" + dirsb + " " + texb) != 0: return error()
        if os.system("dvipng -D 150 -o " + pngb + " -T tight " + dvib) != 0: return error()
        os.remove(texb)
        os.remove(auxb)
        os.remove(dvib)
        os.remove(logb)
        return done(pngf)


class MathExtension(markdown.Extension):
    def extendMarkdown(self, md, md_globals):
        md.inlinePatterns.insert(0, MathPattern(md))


def makeExtension(configs):
    return MathExtension(configs)



Powered by Sputnik | XHTML 1.1