tables.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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. Tables Extension for Python-Markdown
  33. ====================================
  34. Added parsing of tables to Python-Markdown.
  35. A simple example:
  36. First Header | Second Header
  37. ------------- | -------------
  38. Content Cell | Content Cell
  39. Content Cell | Content Cell
  40. Copyright 2009 - [Waylan Limberg](http://achinghead.com)
  41. """
  42. from __future__ import absolute_import
  43. from __future__ import unicode_literals
  44. from . import Extension
  45. from ..blockprocessors import BlockProcessor
  46. from ..util import etree
  47. class TableProcessor(BlockProcessor):
  48. """ Process Tables. """
  49. def test(self, parent, block):
  50. rows = block.split('\n')
  51. return (len(rows) > 2 and '|' in rows[0] and
  52. '|' in rows[1] and '-' in rows[1] and
  53. rows[1].strip()[0] in ['|', ':', '-'])
  54. def run(self, parent, blocks):
  55. """ Parse a table block and build table. """
  56. block = blocks.pop(0).split('\n')
  57. header = block[0].strip()
  58. seperator = block[1].strip()
  59. rows = block[2:]
  60. # Get format type (bordered by pipes or not)
  61. border = False
  62. if header.startswith('|'):
  63. border = True
  64. # Get alignment of columns
  65. align = []
  66. for c in self._split_row(seperator, border):
  67. if c.startswith(':') and c.endswith(':'):
  68. align.append('center')
  69. elif c.startswith(':'):
  70. align.append('left')
  71. elif c.endswith(':'):
  72. align.append('right')
  73. else:
  74. align.append(None)
  75. # Build table
  76. table = etree.SubElement(parent, 'table')
  77. thead = etree.SubElement(table, 'thead')
  78. self._build_row(header, thead, align, border)
  79. tbody = etree.SubElement(table, 'tbody')
  80. for row in rows:
  81. self._build_row(row.strip(), tbody, align, border)
  82. def _build_row(self, row, parent, align, border):
  83. """ Given a row of text, build table cells. """
  84. tr = etree.SubElement(parent, 'tr')
  85. tag = 'td'
  86. if parent.tag == 'thead':
  87. tag = 'th'
  88. cells = self._split_row(row, border)
  89. # We use align here rather than cells to ensure every row
  90. # contains the same number of columns.
  91. for i, a in enumerate(align):
  92. c = etree.SubElement(tr, tag)
  93. try:
  94. c.text = cells[i].strip()
  95. except IndexError:
  96. c.text = ""
  97. if a:
  98. c.set('align', a)
  99. def _split_row(self, row, border):
  100. """ split a row of text into list of cells. """
  101. if border:
  102. if row.startswith('|'):
  103. row = row[1:]
  104. if row.endswith('|'):
  105. row = row[:-1]
  106. return row.split('|')
  107. class TableExtension(Extension):
  108. """ Add tables to Markdown. """
  109. def extendMarkdown(self, md, md_globals):
  110. """ Add an instance of TableProcessor to BlockParser. """
  111. md.parser.blockprocessors.add('table',
  112. TableProcessor(md.parser),
  113. '<hashheader')
  114. def makeExtension(configs={}):
  115. return TableExtension(configs=configs)