15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# markdown is released under the BSD license 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Copyright 2007, 2008 The Python Markdown Project (v. 1.7 and later) 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b) 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Copyright 2004 Manfred Stienstra (the original version) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# All rights reserved. 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Redistribution and use in source and binary forms, with or without 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# modification, are permitted provided that the following conditions are met: 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# * Redistributions of source code must retain the above copyright 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# notice, this list of conditions and the following disclaimer. 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# * Redistributions in binary form must reproduce the above copyright 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# notice, this list of conditions and the following disclaimer in the 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# documentation and/or other materials provided with the distribution. 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# * Neither the name of the <organization> nor the 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# names of its contributors may be used to endorse or promote products 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# derived from this software without specific prior written permission. 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# THIS SOFTWARE IS PROVIDED BY THE PYTHON MARKDOWN PROJECT ''AS IS'' AND ANY 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# DISCLAIMED. IN NO EVENT SHALL ANY CONTRIBUTORS TO THE PYTHON MARKDOWN PROJECT 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# POSSIBILITY OF SUCH DAMAGE. 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)""" 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Tables Extension for Python-Markdown 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)==================================== 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Added parsing of tables to Python-Markdown. 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)A simple example: 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) First Header | Second Header 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ------------- | ------------- 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Content Cell | Content Cell 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Content Cell | Content Cell 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Copyright 2009 - [Waylan Limberg](http://achinghead.com) 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)""" 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)from __future__ import absolute_import 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)from __future__ import unicode_literals 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)from . import Extension 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)from ..blockprocessors import BlockProcessor 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)from ..util import etree 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class TableProcessor(BlockProcessor): 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """ Process Tables. """ 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def test(self, parent, block): 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rows = block.split('\n') 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return (len(rows) > 2 and '|' in rows[0] and 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) '|' in rows[1] and '-' in rows[1] and 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rows[1].strip()[0] in ['|', ':', '-']) 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def run(self, parent, blocks): 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """ Parse a table block and build table. """ 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) block = blocks.pop(0).split('\n') 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) header = block[0].strip() 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) seperator = block[1].strip() 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rows = block[2:] 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # Get format type (bordered by pipes or not) 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) border = False 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if header.startswith('|'): 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) border = True 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # Get alignment of columns 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) align = [] 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for c in self._split_row(seperator, border): 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if c.startswith(':') and c.endswith(':'): 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) align.append('center') 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c.startswith(':'): 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) align.append('left') 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif c.endswith(':'): 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) align.append('right') 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else: 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) align.append(None) 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # Build table 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) table = etree.SubElement(parent, 'table') 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) thead = etree.SubElement(table, 'thead') 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self._build_row(header, thead, align, border) 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) tbody = etree.SubElement(table, 'tbody') 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for row in rows: 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self._build_row(row.strip(), tbody, align, border) 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def _build_row(self, row, parent, align, border): 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """ Given a row of text, build table cells. """ 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) tr = etree.SubElement(parent, 'tr') 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) tag = 'td' 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if parent.tag == 'thead': 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) tag = 'th' 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cells = self._split_row(row, border) 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # We use align here rather than cells to ensure every row 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # contains the same number of columns. 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for i, a in enumerate(align): 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) c = etree.SubElement(tr, tag) 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) try: 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) c.text = cells[i].strip() 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) except IndexError: 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) c.text = "" 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if a: 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) c.set('align', a) 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def _split_row(self, row, border): 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """ split a row of text into list of cells. """ 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if border: 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if row.startswith('|'): 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) row = row[1:] 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if row.endswith('|'): 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) row = row[:-1] 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return row.split('|') 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class TableExtension(Extension): 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """ Add tables to Markdown. """ 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def extendMarkdown(self, md, md_globals): 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """ Add an instance of TableProcessor to BlockParser. """ 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) md.parser.blockprocessors.add('table', 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) TableProcessor(md.parser), 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) '<hashheader') 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def makeExtension(configs={}): 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return TableExtension(configs=configs) 133