text: import re
  
  __all__ = ['plugin_table']
  
  TABLE_PATTERN = re.compile(
      r' {0,3}\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*'
  )
  NP_TABLE_PATTERN = re.compile(
      r' {0,3}(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*'
  )
  HEADER_SUB = re.compile(r'\| *$')
  HEADER_SPLIT = re.compile(r' *\| *')
  ALIGN_SPLIT = re.compile(r' *\| *')
  
  
  def parse_table(self, m, state):
      header = HEADER_SUB.sub('', m.group(1)).strip()
      align = HEADER_SUB.sub('', m.group(2))
      thead, aligns = _process_table(header, align)
  
      text = re.sub(r'(?: *\| *)?\n$', '', m.group(3))
      rows = []
      for i, v in enumerate(text.split('\n')):
          v = re.sub(r'^ *\| *| *\| *$', '', v)
          rows.append(_process_row(v, aligns))
  
      children = [thead, {'type': 'table_body', 'children': rows}]
      return {'type': 'table', 'children': children}
  
  
  def text_parse_and_render_table(self, m, state):
      table = parse_table(self, m, state)
      thead = table['children'][0]['children']
      headers = [cell['text'] for cell in thead]
      tbody = table['children'][1]['children']
      rows = [[cell['text'] for cell in row['children']] for row in tbody]
  
      return {'type': 'table', 'raw': {'headers': headers, 'rows': rows}}
  
  
  def parse_nptable(self, m, state):
      thead, aligns = _process_table(m.group(1), m.group(2))
  
      text = re.sub(r'\n$', '', m.group(3))
      rows = []
      for i, v in enumerate(text.split('\n')):
          rows.append(_process_row(v, aligns))
  
      children = [thead, {'type': 'table_body', 'children': rows}]
      return {'type': 'table', 'children': children}
  
  
  def _process_table(header, align):
      headers = HEADER_SPLIT.split(header)
      aligns = ALIGN_SPLIT.split(align)
  
      if header.endswith('|'):
          headers.append('')
  
      cells = []
      for i, v in enumerate(aligns):
          if re.search(r'^ *-+: *$', v):
              aligns[i] = 'right'
          elif re.search(r'^ *:-+: *$', v):
              aligns[i] = 'center'
          elif re.search(r'^ *:-+ *$', v):
              aligns[i] = 'left'
          else:
              aligns[i] = None
  
          if len(headers) > i:
              cells.append({
                  'type': 'table_cell',
                  'text': headers[i],
                  'params': (aligns[i], True)
              })
  
      i += 1
      while i + 1 < len(headers):
          cells.append({
              'type': 'table_cell',
              'text': headers[i],
              'params': (None, True)
          })
          aligns.append(None)
          i += 1
  
      thead = {'type': 'table_head', 'children': cells}
      return thead, aligns
  
  
  def _process_row(row, aligns):
      cells = []
      for i, s in enumerate(re.split(r' *(?<!\\)\| *', row)):
          text = re.sub(r'\\\|', '|', s.strip())
          if len(aligns) < i + 1:
              cells.append({
                  'type': 'table_cell',
                  'text': text,
                  'params': (None, False)
              })
          else:
              cells.append({
                  'type': 'table_cell',
                  'text': text,
                  'params': (aligns[i], False)
              })
      return {'type': 'table_row', 'children': cells}
  
  
  def render_html_table(text):
      return '<table>\n' + text + '</table>\n'
  
  
  def render_html_table_head(text):
      return '<thead>\n<tr>\n' + text + '</tr>\n</thead>\n'
  
  
  def render_html_table_body(text):
      return '<tbody>\n' + text + '</tbody>\n'
  
  
  def render_html_table_row(text):
      return '<tr>\n' + text + '</tr>\n'
  
  
  def render_html_table_cell(text, align=None, is_head=False):
      if is_head:
          tag = 'th'
      else:
          tag = 'td'
  
      html = '  <' + tag
      if align:
          html += ' style="text-align:' + align + '"'
  
      return html + '>' + text + '</' + tag + '>\n'
  
  
  def render_ast_table_cell(children, align=None, is_head=False):
      return {
          'type': 'table_cell',
          'children': children,
          'align': align,
          'is_head': is_head
      }
  
  
  def plugin_table(md):
      md.block.register_rule('table', TABLE_PATTERN, parse_table)
      md.block.register_rule('nptable', NP_TABLE_PATTERN, parse_nptable)
      md.block.rules.append('table')
      md.block.rules.append('nptable')
  
      if md.renderer.NAME == 'html':
          md.renderer.register('table', render_html_table)
          md.renderer.register('table_head', render_html_table_head)
          md.renderer.register('table_body', render_html_table_body)
          md.renderer.register('table_row', render_html_table_row)
          md.renderer.register('table_cell', render_html_table_cell)
  
      elif md.renderer.NAME == 'ast':
          md.renderer.register('table_cell', render_ast_table_cell)
  
      elif md.renderer.NAME == 'text' or md.renderer.NAME == 'terminal':
          md.block.register_rule('table', TABLE_PATTERN, text_parse_and_render_table)
  