From 0372df54fcf7d4470eb89f9103f5562aa10b108c Mon Sep 17 00:00:00 2001 From: John Dickinson Date: Thu, 23 Feb 2012 21:09:03 -0500 Subject: [PATCH 1/4] initial work on database-style tables as an extra. Based off of the ideas of David Wheeler at http://justatheory.com/computers/markup/markdown-table-rfc.html --- lib/markdown2.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/lib/markdown2.py b/lib/markdown2.py index 87e5123f..2f272071 100755 --- a/lib/markdown2.py +++ b/lib/markdown2.py @@ -743,6 +743,8 @@ def _run_block_gamut(self, text): text = self._prepare_pyshell_blocks(text) if "wiki-tables" in self.extras: text = self._do_wiki_tables(text) + if "db-tables" in self.extras: + text = self._do_db_tables(text) text = self._do_code_blocks(text) @@ -816,6 +818,58 @@ def _do_wiki_tables(self, text): (^\1\|\|.+?\|\|\n)* # any number of subsequent lines ''' % less_than_tab, re.M | re.X) return wiki_table_re.sub(self._wiki_table_sub, text) + + def _db_table_sub(self, match): + text = match.group(0).strip() + #print 'db table: %r' % match.group(0) + table = [] + for line in text.splitlines(): + line = line.strip() + if re.match(r'^[-+:]$',line): #discard the heading separator + continue + table.append(re.split(r'(?', ''] + for row in table: + result.append('') + emptyrow = True + for cell in row: + #TODO: determine alignment from whitespace + cell = cell.strip() + if len(cell) < 1 or re.match(r'[-+]', cell): + continue + result.append('') + result.append(self._run_span_gamut(cell)) + result.append('') + emptyrow = False + if emptyrow: + result.pop() + else: + result.append('') + result += ['', ''] + return '\n'.join(result) + '\n' + + def _do_db_tables(self, text): + """ attempt at implementing David Wheeler's + suggestion at a syntax for Markdown Tables. + See http://justatheory.com/computers/markup/markdown-table-rfc.html""" + #Perform trivial optimization like wiki tables + if '|' not in text: + return text + less_than_tab = self.tab_width - 1 + db_table_re = re.compile(r''' + (?:(?<=\n\n)|\A\n?) # blank line before table + ^[ ]{0,4}\|([^\|\n]*\|)*[ ]*\n #first line + #(^[-+:]*\n){0,1} #optional separating line + (^([ ]{0,4})(\|([^|\n]\|)*)[ ]*\n)* # matches the rest of the lines in the table + ''' , re.M | re.X) + db_table_re = re.compile(r''' + (?:(?<=\n\n)|\A\n?) + ^[ ]{0,4}\|([^\|\n]*\|)*[ ]*\n + (^[-+:]*\n){0,1} + (^[ ]{0,4}\|([^\|\n]*\|)*[ ]*\n)* + ''', re.M | re.X) + return db_table_re.sub(self._db_table_sub, text) def _run_span_gamut(self, text): # These are all the transformations that occur *within* block-level From 0e0c43877898d369054800c4c684ea1d79547573 Mon Sep 17 00:00:00 2001 From: John Dickinson Date: Thu, 23 Feb 2012 22:27:17 -0500 Subject: [PATCH 2/4] Much better table implementation now. Changes: Headers by default, not required cells can span columns empty cells work optional horizontal line separators --- lib/markdown2.py | 60 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/lib/markdown2.py b/lib/markdown2.py index 2f272071..a9614780 100755 --- a/lib/markdown2.py +++ b/lib/markdown2.py @@ -823,29 +823,56 @@ def _db_table_sub(self, match): text = match.group(0).strip() #print 'db table: %r' % match.group(0) table = [] + header = True + first = True for line in text.splitlines(): - line = line.strip() - if re.match(r'^[-+:]$',line): #discard the heading separator - continue - table.append(re.split(r'(?', ''] + space_re = re.compile(r'^([ ]*).*?([ ]*)$') #print table - result = ['', ''] for row in table: result.append('') emptyrow = True for cell in row: - #TODO: determine alignment from whitespace + colspan = 1 + while cell[-1] == '|': + colspan += 1 + cell = cell[:-1] + match = space_re.match(cell) + align = 'center' + if match: + #print 'left "'+match.group(1)+'" right "'+match.group(2)+'"' + if len(match.group(1)) < len(match.group(2)) and len(match.group(1)) < 2: + align = 'left' + if len(match.group(2)) < len(match.group(1)) and len(match.group(2)) < 2: + align = 'right' cell = cell.strip() - if len(cell) < 1 or re.match(r'[-+]', cell): + if re.match(r'[-+]', cell): continue - result.append('') + if colspan > 1: + colspan = 'colspan="%d"' % colspan + else: + colspan = '' + tag = '') + if header: + header = False result += ['', '
') - result.append(self._run_span_gamut(cell)) - result.append('') + result.append(self._run_span_gamut(cell)+endtag) emptyrow = False if emptyrow: result.pop() else: result.append('
'] return '\n'.join(result) + '\n' @@ -857,18 +884,11 @@ def _do_db_tables(self, text): if '|' not in text: return text less_than_tab = self.tab_width - 1 - db_table_re = re.compile(r''' - (?:(?<=\n\n)|\A\n?) # blank line before table - ^[ ]{0,4}\|([^\|\n]*\|)*[ ]*\n #first line - #(^[-+:]*\n){0,1} #optional separating line - (^([ ]{0,4})(\|([^|\n]\|)*)[ ]*\n)* # matches the rest of the lines in the table - ''' , re.M | re.X) db_table_re = re.compile(r''' (?:(?<=\n\n)|\A\n?) - ^[ ]{0,4}\|([^\|\n]*\|)*[ ]*\n - (^[-+:]*\n){0,1} - (^[ ]{0,4}\|([^\|\n]*\|)*[ ]*\n)* - ''', re.M | re.X) + ((^[-+:]*\n){0,1} + ^[ ]{0,4}\|([^\|\n]*\|)*[ ]*\n){1,} + (^[-+:]*\n){0,1}''', re.M | re.X) return db_table_re.sub(self._db_table_sub, text) def _run_span_gamut(self, text): From e7d2a33fdc37f7d4a2f4fccdcfaad8153bd1f7f2 Mon Sep 17 00:00:00 2001 From: John Dickinson Date: Fri, 24 Feb 2012 00:00:44 -0500 Subject: [PATCH 3/4] Improved header behavior. No header is now possible, as is one, two, or arbitrary header lines. --- lib/markdown2.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/markdown2.py b/lib/markdown2.py index a9614780..0d7fe14d 100755 --- a/lib/markdown2.py +++ b/lib/markdown2.py @@ -823,19 +823,21 @@ def _db_table_sub(self, match): text = match.group(0).strip() #print 'db table: %r' % match.group(0) table = [] - header = True - first = True + header = 1 + line_num = 0 for line in text.splitlines(): line = line.strip() - if re.match(r'^[-+\|]$',line): - if first: - header = False + #print header, line_num, line, "
" + if header == 1 and re.match(r'^[-+\|]*$',line): + #print "end of header
" + header = line_num continue table.append(re.split(r'(?', ''] space_re = re.compile(r'^([ ]*).*?([ ]*)$') #print table + line_num = 0 for row in table: result.append('') emptyrow = True @@ -861,7 +863,7 @@ def _db_table_sub(self, match): colspan = '' tag = ' line_num: tag = '') @@ -871,8 +873,7 @@ def _db_table_sub(self, match): result.pop() else: result.append('') - if header: - header = False + line_num += 1 result += ['', ''] return '\n'.join(result) + '\n' From 1faeb8862e531ff175dd20d7a9903a3fe4d9696a Mon Sep 17 00:00:00 2001 From: John Dickinson Date: Fri, 24 Feb 2012 20:30:45 -0500 Subject: [PATCH 4/4] Allow '|' characters in rowl dividers --- lib/markdown2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/markdown2.py b/lib/markdown2.py index 0d7fe14d..4b357e50 100755 --- a/lib/markdown2.py +++ b/lib/markdown2.py @@ -887,7 +887,7 @@ def _do_db_tables(self, text): less_than_tab = self.tab_width - 1 db_table_re = re.compile(r''' (?:(?<=\n\n)|\A\n?) - ((^[-+:]*\n){0,1} + ((^[-+:\|]*\n){0,1} ^[ ]{0,4}\|([^\|\n]*\|)*[ ]*\n){1,} (^[-+:]*\n){0,1}''', re.M | re.X) return db_table_re.sub(self._db_table_sub, text)