abbr.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. # markdown is released under the BSD license
  2. # Copyright 2007, 2008 The Python Markdown Project (v. 1.7 and later)
  3. # Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b)
  4. # Copyright 2004 Manfred Stienstra (the original version)
  5. #
  6. # All rights reserved.
  7. #
  8. # Redistribution and use in source and binary forms, with or without
  9. # modification, are permitted provided that the following conditions are met:
  10. #
  11. # * Redistributions of source code must retain the above copyright
  12. # notice, this list of conditions and the following disclaimer.
  13. # * Redistributions in binary form must reproduce the above copyright
  14. # notice, this list of conditions and the following disclaimer in the
  15. # documentation and/or other materials provided with the distribution.
  16. # * Neither the name of the <organization> nor the
  17. # names of its contributors may be used to endorse or promote products
  18. # derived from this software without specific prior written permission.
  19. #
  20. # THIS SOFTWARE IS PROVIDED BY THE PYTHON MARKDOWN PROJECT ''AS IS'' AND ANY
  21. # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  22. # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  23. # DISCLAIMED. IN NO EVENT SHALL ANY CONTRIBUTORS TO THE PYTHON MARKDOWN PROJECT
  24. # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  25. # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  26. # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27. # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28. # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  29. # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  30. # POSSIBILITY OF SUCH DAMAGE.
  31. '''
  32. Abbreviation Extension for Python-Markdown
  33. ==========================================
  34. This extension adds abbreviation handling to Python-Markdown.
  35. Simple Usage:
  36. >>> import markdown
  37. >>> text = """
  38. ... Some text with an ABBR and a REF. Ignore REFERENCE and ref.
  39. ...
  40. ... *[ABBR]: Abbreviation
  41. ... *[REF]: Abbreviation Reference
  42. ... """
  43. >>> print markdown.markdown(text, ['abbr'])
  44. <p>Some text with an <abbr title="Abbreviation">ABBR</abbr> and a <abbr title="Abbreviation Reference">REF</abbr>. Ignore REFERENCE and ref.</p>
  45. Copyright 2007-2008
  46. * [Waylan Limberg](http://achinghead.com/)
  47. * [Seemant Kulleen](http://www.kulleen.org/)
  48. '''
  49. from __future__ import absolute_import
  50. from __future__ import unicode_literals
  51. from . import Extension
  52. from ..preprocessors import Preprocessor
  53. from ..inlinepatterns import Pattern
  54. from ..util import etree
  55. import re
  56. # Global Vars
  57. ABBR_REF_RE = re.compile(r'[*]\[(?P<abbr>[^\]]*)\][ ]?:\s*(?P<title>.*)')
  58. class AbbrExtension(Extension):
  59. """ Abbreviation Extension for Python-Markdown. """
  60. def extendMarkdown(self, md, md_globals):
  61. """ Insert AbbrPreprocessor before ReferencePreprocessor. """
  62. md.preprocessors.add('abbr', AbbrPreprocessor(md), '<reference')
  63. class AbbrPreprocessor(Preprocessor):
  64. """ Abbreviation Preprocessor - parse text for abbr references. """
  65. def run(self, lines):
  66. '''
  67. Find and remove all Abbreviation references from the text.
  68. Each reference is set as a new AbbrPattern in the markdown instance.
  69. '''
  70. new_text = []
  71. for line in lines:
  72. m = ABBR_REF_RE.match(line)
  73. if m:
  74. abbr = m.group('abbr').strip()
  75. title = m.group('title').strip()
  76. self.markdown.inlinePatterns['abbr-%s'%abbr] = \
  77. AbbrPattern(self._generate_pattern(abbr), title)
  78. else:
  79. new_text.append(line)
  80. return new_text
  81. def _generate_pattern(self, text):
  82. '''
  83. Given a string, returns an regex pattern to match that string.
  84. 'HTML' -> r'(?P<abbr>[H][T][M][L])'
  85. Note: we force each char as a literal match (in brackets) as we don't
  86. know what they will be beforehand.
  87. '''
  88. chars = list(text)
  89. for i in range(len(chars)):
  90. chars[i] = r'[%s]' % chars[i]
  91. return r'(?P<abbr>\b%s\b)' % (r''.join(chars))
  92. class AbbrPattern(Pattern):
  93. """ Abbreviation inline pattern. """
  94. def __init__(self, pattern, title):
  95. super(AbbrPattern, self).__init__(pattern)
  96. self.title = title
  97. def handleMatch(self, m):
  98. abbr = etree.Element('abbr')
  99. abbr.text = m.group('abbr')
  100. abbr.set('title', self.title)
  101. return abbr
  102. def makeExtension(configs=None):
  103. return AbbrExtension(configs=configs)