16516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru#!usr/bin/python
26516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
36516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru"""
46516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste QueruMeta Data Extension for Python-Markdown
56516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru=======================================
66516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
76516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste QueruThis extension adds Meta Data handling to markdown.
86516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
96516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste QueruBasic Usage:
106516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
116516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    >>> import markdown
126516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    >>> text = '''Title: A Test Doc.
136516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    ... Author: Waylan Limberg
146516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    ...         John Doe
156516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    ... Blank_Data:
166516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    ...
176516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    ... The body. This is paragraph one.
186516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    ... '''
196516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    >>> md = markdown.Markdown(['meta'])
206516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    >>> md.convert(text)
216516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    u'<p>The body. This is paragraph one.</p>'
226516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    >>> md.Meta
236516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    {u'blank_data': [u''], u'author': [u'Waylan Limberg', u'John Doe'], u'title': [u'A Test Doc.']}
246516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
256516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste QueruMake sure text without Meta Data still works (markdown < 1.6b returns a <p>).
266516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
276516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    >>> text = '    Some Code - not extra lines of meta data.'
286516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    >>> md = markdown.Markdown(['meta'])
296516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    >>> md.convert(text)
306516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    u'<pre><code>Some Code - not extra lines of meta data.\\n</code></pre>'
316516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    >>> md.Meta
326516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    {}
336516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
346516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste QueruCopyright 2007-2008 [Waylan Limberg](http://achinghead.com).
356516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
366516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste QueruProject website: <http://www.freewisdom.org/project/python-markdown/Meta-Data>
376516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste QueruContact: markdown@freewisdom.org
386516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
396516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste QueruLicense: BSD (see ../docs/LICENSE for details)
406516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
416516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru"""
426516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
436516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queruimport markdown, re
446516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
456516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# Global Vars
466516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste QueruMETA_RE = re.compile(r'^[ ]{0,3}(?P<key>[A-Za-z0-9_-]+):\s*(?P<value>.*)')
476516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste QueruMETA_MORE_RE = re.compile(r'^[ ]{4,}(?P<value>.*)')
486516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
496516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queruclass MetaExtension (markdown.Extension):
506516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    """ Meta-Data extension for Python-Markdown. """
516516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
526516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    def extendMarkdown(self, md, md_globals):
536516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        """ Add MetaPreprocessor to Markdown instance. """
546516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
556516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        md.preprocessors.add("meta", MetaPreprocessor(md), "_begin")
566516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
576516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
586516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queruclass MetaPreprocessor(markdown.preprocessors.Preprocessor):
596516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    """ Get Meta-Data. """
606516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
616516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    def run(self, lines):
626516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        """ Parse Meta-Data and store in Markdown.Meta. """
636516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        meta = {}
646516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        key = None
656516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        while 1:
666516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            line = lines.pop(0)
676516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            if line.strip() == '':
686516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                break # blank line - done
696516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            m1 = META_RE.match(line)
706516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            if m1:
716516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                key = m1.group('key').lower().strip()
726516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                meta[key] = [m1.group('value').strip()]
736516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            else:
746516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                m2 = META_MORE_RE.match(line)
756516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                if m2 and key:
766516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    # Add another line to existing key
776516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    meta[key].append(m2.group('value').strip())
786516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                else:
796516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    lines.insert(0, line)
806516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    break # no meta data - done
816516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        self.markdown.Meta = meta
826516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        return lines
836516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
846516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
856516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Querudef makeExtension(configs={}):
866516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    return MetaExtension(configs=configs)
876516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
886516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queruif __name__ == "__main__":
896516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    import doctest
906516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    doctest.testmod()
91