1
'''
2
Abbreviation Extension for Python-Markdown
3
==========================================
4
5
This extension adds abbreviation handling to Python-Markdown.
6
7
Simple Usage:
8
9
    >>> import markdown
10
    >>> text = """
11
    ... Some text with an ABBR and a REF. Ignore REFERENCE and ref.
12
    ...
13
    ... *[ABBR]: Abbreviation
14
    ... *[REF]: Abbreviation Reference
15
    ... """
16
    >>> markdown.markdown(text, ['abbr'])
17
    u'<p>Some text with an <abbr title="Abbreviation">ABBR</abbr> and a <abbr title="Abbreviation Reference">REF</abbr>. Ignore REFERENCE and ref.</p>'
18
19
Copyright 2007-2008
20
* [Waylan Limberg](http://achinghead.com/)
21
* [Seemant Kulleen](http://www.kulleen.org/)
22
	
23
24
'''
25
26
import re
27
import markdown
28
from markdown.util import etree
29
30
# Global Vars
31
ABBR_REF_RE = re.compile(r'[*]\[(?P<abbr>[^\]]*)\][ ]?:\s*(?P<title>.*)')
32
33
class AbbrExtension(markdown.Extension):
34
    """ Abbreviation Extension for Python-Markdown. """
35
36
    def extendMarkdown(self, md, md_globals):
37
        """ Insert AbbrPreprocessor before ReferencePreprocessor. """
38
        md.preprocessors.add('abbr', AbbrPreprocessor(md), '<reference')
39
        
40
           
41
class AbbrPreprocessor(markdown.preprocessors.Preprocessor):
42
    """ Abbreviation Preprocessor - parse text for abbr references. """
43
44
    def run(self, lines):
45
        '''
46
        Find and remove all Abbreviation references from the text.
47
        Each reference is set as a new AbbrPattern in the markdown instance.
48
        
49
        '''
50
        new_text = []
51
        for line in lines:
52
            m = ABBR_REF_RE.match(line)
53
            if m:
54
                abbr = m.group('abbr').strip()
55
                title = m.group('title').strip()
56
                self.markdown.inlinePatterns['abbr-%s'%abbr] = \
57
                    AbbrPattern(self._generate_pattern(abbr), title)
58
            else:
59
                new_text.append(line)
60
        return new_text
61
    
62
    def _generate_pattern(self, text):
63
        '''
64
        Given a string, returns an regex pattern to match that string. 
65
        
66
        'HTML' -> r'(?P<abbr>[H][T][M][L])' 
67
        
68
        Note: we force each char as a literal match (in brackets) as we don't 
69
        know what they will be beforehand.
70
71
        '''
72
        chars = list(text)
73
        for i in range(len(chars)):
74
            chars[i] = r'[%s]' % chars[i]
75
        return r'(?P<abbr>\b%s\b)' % (r''.join(chars))
76
77
78
class AbbrPattern(markdown.inlinepatterns.Pattern):
79
    """ Abbreviation inline pattern. """
80
81
    def __init__(self, pattern, title):
82
        markdown.inlinepatterns.Pattern.__init__(self, pattern)
83
        self.title = title
84
85
    def handleMatch(self, m):
86
        abbr = etree.Element('abbr')
87
        abbr.text = m.group('abbr')
88
        abbr.set('title', self.title)
89
        return abbr
90
91
def makeExtension(configs=None):
92
    return AbbrExtension(configs=configs)
93
94
if __name__ == "__main__":
95
    import doctest
96
    doctest.testmod()