diff --git a/lib/marked.js b/lib/marked.js index fce4f4c4..d48997c8 100644 --- a/lib/marked.js +++ b/lib/marked.js @@ -13,6 +13,8 @@ var block = { newline: /^\n+/, code: /^( {4}[^\n]+\n*)+/, fences: noop, + table: noop, + nptable: noop, hr: /^( *[-*_]){3,} *(?:\n+|$)/, heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/, lheading: /^([^\n]+)\n *(=|-){3,} *\n*/, @@ -53,12 +55,16 @@ block.paragraph = replace(block.paragraph) block.normal = { fences: block.fences, - paragraph: block.paragraph + paragraph: block.paragraph, + table: block.table, + nptable: block.nptable }; block.gfm = { fences: /^ *(`{3,}|~{3,}) *(\w+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/, - paragraph: /^/ + paragraph: /^/, + table: /^ {0,3}[|](.+)\n {0,3}[|]( *[-:]+[-| :]*)\n((?: *[|].*\n)*)\n*/, + nptable: /^ {0,3}(\S.*[|].*)\n {0,3}([-:]+ *[|][-| :]*)\n((?:.*[|].*\n)*)\n*/ }; block.gfm.paragraph = replace(block.paragraph) @@ -126,6 +132,44 @@ block.token = function(src, tokens, top) { continue; } + // table (gfm) + if (cap = block.table.exec(src)) { + src = src.substring(cap[0].length); + tokens.push({ + type: 'table', + header: cap[1].replace(/(^ *| *[|] *$)/g, '').split(/ *[|] */), + align: cap[2].replace(/(^ *|[|] *$)/g, '').split(/ *[|] */).map(function(row){ + return row.match(/^ *-+: *$/) ? "right" + : row.match(/^ *:-+: *$/) ? "center" + : row.match(/^ *:-+ *$/) ? "left" + : false; + }), + cells: cap[3].replace(/( *[|] *)?\n$/, '').split("\n").map(function(row){ + return row.replace(/(^ *[|] *| *[|] *$)/g, '').split(/ *[|] */); + }) + }); + continue; + } + + // table no leading pipe (gfm) + if (cap = block.nptable.exec(src)) { + src = src.substring(cap[0].length); + tokens.push({ + type: 'table', + header: cap[1].replace(/(^ *| *[|] *$)/g, '').split(/ *[|] */), + align: cap[2].replace(/(^ *|[|] *$)/g, '').split(/ *[|] */).map(function(row){ + return row.match(/^ *-+: *$/) ? "right" + : row.match(/^ *:-+: *$/) ? "center" + : row.match(/^ *:-+ *$/) ? "left" + : false; + }), + cells: cap[3].replace(/\n$/, '').split("\n").map(function(row){ + return row.split(/ *[|] */); + }) + }); + continue; + } + // heading if (cap = block.heading.exec(src)) { src = src.substring(cap[0].length); @@ -300,7 +344,7 @@ block.token = function(src, tokens, top) { */ var inline = { - escape: /^\\([\\`*{}\[\]()#+\-.!_>])/, + escape: /^\\([\\`*{}\[\]()#+\-.!_>|])/, autolink: /^<([^ >]+(@|:\/)[^ >]+)>/, url: noop, tag: /^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/, @@ -559,6 +603,48 @@ function tok() { + token.text + '\n'; } + case 'table': { + var thead = '\t\n\t\t'; + token.header.forEach(function(heading, i){ + heading = inline.lexer(heading); + var align = i < token.align.length ? token.align[i] : false; + switch(align){ + case "left": + case "right": + case "center": + thead += '' + heading + ''; + break; + default: + thead += '' + heading + ''; + } + }); + thead += '\n\t\n'; + + var tbody = '\t\n'; + token.cells.forEach(function(row){ + tbody += '\t\t'; + row.forEach(function(cell, i){ + cell = inline.lexer(cell); + var align = i < token.align.length ? token.align[i] : false; + switch(align){ + case "left": + case "right": + case "center": + tbody += '' + cell + ''; + break; + default: + tbody += '' + cell + ''; + } + }); + tbody += '\n'; + }); + tbody += '\t\n'; + + return '\n' + + thead + + tbody + + '
\n' + } case 'blockquote_start': { var body = ''; @@ -740,11 +826,15 @@ function setOptions(opt) { if (options.gfm) { block.fences = block.gfm.fences; block.paragraph = block.gfm.paragraph; + block.table = block.gfm.table; + block.nptable = block.gfm.nptable; inline.text = inline.gfm.text; inline.url = inline.gfm.url; } else { block.fences = block.normal.fences; block.paragraph = block.normal.paragraph; + block.table = block.normal.table; + block.nptable = block.normal.table; inline.text = inline.normal.text; inline.url = inline.normal.url; } diff --git a/test/new/gfm_tables.html b/test/new/gfm_tables.html new file mode 100644 index 00000000..1dd37334 --- /dev/null +++ b/test/new/gfm_tables.html @@ -0,0 +1,38 @@ + + + + + + + + +
Heading 1Heading 2
Cell 1Cell 2
Cell 3Cell 4
+ + + + + + + + +
Header 1Header 2Header 3Header 4
Cell 1Cell 2Cell 3Cell 4
Cell 5Cell 6Cell 7Cell 8
+
Test code
+ + + + + + + + +
Header 1Header 2
Cell 1Cell 2
Cell 3Cell 4
+ + + + + + + + +
Header 1Header 2Header 3Header 4
Cell 1Cell 2Cell 3Cell 4
Cell 5Cell 6Cell 7Cell 8
+ diff --git a/test/new/gfm_tables.text b/test/new/gfm_tables.text new file mode 100644 index 00000000..5fd6321c --- /dev/null +++ b/test/new/gfm_tables.text @@ -0,0 +1,21 @@ +| Heading 1 | Heading 2 +| --------- | --------- +| Cell 1 | Cell 2 +| Cell 3 | Cell 4 + +| Header 1 | Header 2 | Header 3 | Header 4 | +| :------: | -------: | :------- | -------- | +| Cell 1 | Cell 2 | Cell 3 | Cell 4 | +| Cell 5 | Cell 6 | Cell 7 | Cell 8 | + + Test code + +Header 1 | Header 2 +-------- | -------- +Cell 1 | Cell 2 +Cell 3 | Cell 4 + +Header 1|Header 2|Header 3|Header 4 +:-------|:------:|-------:|-------- +Cell 1 |Cell 2 |Cell 3 |Cell 4 +*Cell 5*|Cell 6 |Cell 7 |Cell 8 diff --git a/test/tests/gfm_tables.html b/test/tests/gfm_tables.html new file mode 100644 index 00000000..1dd37334 --- /dev/null +++ b/test/tests/gfm_tables.html @@ -0,0 +1,38 @@ + + + + + + + + +
Heading 1Heading 2
Cell 1Cell 2
Cell 3Cell 4
+ + + + + + + + +
Header 1Header 2Header 3Header 4
Cell 1Cell 2Cell 3Cell 4
Cell 5Cell 6Cell 7Cell 8
+
Test code
+ + + + + + + + +
Header 1Header 2
Cell 1Cell 2
Cell 3Cell 4
+ + + + + + + + +
Header 1Header 2Header 3Header 4
Cell 1Cell 2Cell 3Cell 4
Cell 5Cell 6Cell 7Cell 8
+ diff --git a/test/tests/gfm_tables.text b/test/tests/gfm_tables.text new file mode 100644 index 00000000..5fd6321c --- /dev/null +++ b/test/tests/gfm_tables.text @@ -0,0 +1,21 @@ +| Heading 1 | Heading 2 +| --------- | --------- +| Cell 1 | Cell 2 +| Cell 3 | Cell 4 + +| Header 1 | Header 2 | Header 3 | Header 4 | +| :------: | -------: | :------- | -------- | +| Cell 1 | Cell 2 | Cell 3 | Cell 4 | +| Cell 5 | Cell 6 | Cell 7 | Cell 8 | + + Test code + +Header 1 | Header 2 +-------- | -------- +Cell 1 | Cell 2 +Cell 3 | Cell 4 + +Header 1|Header 2|Header 3|Header 4 +:-------|:------:|-------:|-------- +Cell 1 |Cell 2 |Cell 3 |Cell 4 +*Cell 5*|Cell 6 |Cell 7 |Cell 8