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