diff --git a/lib/marked.js b/lib/marked.js index 55b06b4aff..05be0b5dfc 100644 --- a/lib/marked.js +++ b/lib/marked.js @@ -107,8 +107,8 @@ block.gfm.paragraph = edit(block.paragraph) */ block.tables = merge({}, block.gfm, { - nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/, - table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/ + nptable: /^ *([^|\n ].*\|.*)\n *([-:]+ *\|[-| :]*)(?:\n((?:.*[^>\n ].*(?:\n|$))*)\n*|$)/, + table: /^ *\|(.+)\n *\|?( *[-:]+[-| :]*)(?:\n((?: *[^>\n ].*(?:\n|$))*)\n*|$)/ }); /** @@ -245,34 +245,36 @@ Lexer.prototype.token = function(src, top) { // table no leading pipe (gfm) if (top && (cap = this.rules.nptable.exec(src))) { - src = src.substring(cap[0].length); - item = { type: 'table', header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')), align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), - cells: cap[3].replace(/\n$/, '').split('\n') + cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : [] }; - for (i = 0; i < item.align.length; i++) { - if (/^ *-+: *$/.test(item.align[i])) { - item.align[i] = 'right'; - } else if (/^ *:-+: *$/.test(item.align[i])) { - item.align[i] = 'center'; - } else if (/^ *:-+ *$/.test(item.align[i])) { - item.align[i] = 'left'; - } else { - item.align[i] = null; + if (item.header.length === item.align.length) { + src = src.substring(cap[0].length); + + for (i = 0; i < item.align.length; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } } - } - for (i = 0; i < item.cells.length; i++) { - item.cells[i] = splitCells(item.cells[i]); - } + for (i = 0; i < item.cells.length; i++) { + item.cells[i] = splitCells(item.cells[i], item.header.length); + } - this.tokens.push(item); + this.tokens.push(item); - continue; + continue; + } } // hr @@ -412,35 +414,38 @@ Lexer.prototype.token = function(src, top) { // table (gfm) if (top && (cap = this.rules.table.exec(src))) { - src = src.substring(cap[0].length); - item = { type: 'table', header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')), align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), - cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') + cells: cap[3] ? cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') : [] }; - for (i = 0; i < item.align.length; i++) { - if (/^ *-+: *$/.test(item.align[i])) { - item.align[i] = 'right'; - } else if (/^ *:-+: *$/.test(item.align[i])) { - item.align[i] = 'center'; - } else if (/^ *:-+ *$/.test(item.align[i])) { - item.align[i] = 'left'; - } else { - item.align[i] = null; + if (item.header.length === item.align.length) { + src = src.substring(cap[0].length); + + for (i = 0; i < item.align.length; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } } - } - for (i = 0; i < item.cells.length; i++) { - item.cells[i] = splitCells( - item.cells[i].replace(/^ *\| *| *\| *$/g, '')); - } + for (i = 0; i < item.cells.length; i++) { + item.cells[i] = splitCells( + item.cells[i].replace(/^ *\| *| *\| *$/g, ''), + item.header.length); + } - this.tokens.push(item); + this.tokens.push(item); - continue; + continue; + } } // lheading @@ -927,13 +932,13 @@ Renderer.prototype.paragraph = function(text) { }; Renderer.prototype.table = function(header, body) { + if (body) body = '' + body + ''; + return '\n' + '\n' + header + '\n' - + '\n' + body - + '\n' + '
\n'; }; @@ -944,7 +949,7 @@ Renderer.prototype.tablerow = function(content) { Renderer.prototype.tablecell = function(content, flags) { var type = flags.header ? 'th' : 'td'; var tag = flags.align - ? '<' + type + ' style="text-align:' + flags.align + '">' + ? '<' + type + ' align="' + flags.align + '">' : '<' + type + '>'; return tag + content + '\n'; }; @@ -1310,10 +1315,16 @@ function merge(obj) { return obj; } -function splitCells(tableRow) { +function splitCells(tableRow, count) { var cells = tableRow.replace(/([^\\])\|/g, '$1 |').split(/ +\| */), i = 0; + if (cells.length > count) { + cells.splice(count); + } else { + while (cells.length < count) cells.push(''); + } + for (; i < cells.length; i++) { cells[i] = cells[i].replace(/\\\|/g, '|'); } diff --git a/test/new/gfm_tables.html b/test/new/gfm_tables.html index 70bec827e3..1c596573c9 100644 --- a/test/new/gfm_tables.html +++ b/test/new/gfm_tables.html @@ -9,11 +9,11 @@ - + - - + +
Header 1Header 2Header 3Header 4
Header 1Header 2Header 3Header 4
Cell 1Cell 2Cell 3Cell 4
Cell 5Cell 6Cell 7Cell 8
Cell 1Cell 2Cell 3Cell 4
Cell 5Cell 6Cell 7Cell 8
Test code
@@ -28,10 +28,10 @@ - + - - + +
Header 1Header 2Header 3Header 4
Header 1Header 2Header 3Header 4
Cell 1Cell 2Cell 3Cell 4
Cell 5Cell 6Cell 7Cell 8
Cell 1Cell 2Cell 3Cell 4
Cell 5Cell 6Cell 7Cell 8
diff --git a/test/specs/gfm/gfm-spec.js b/test/specs/gfm/gfm-spec.js index 3589a5f3e5..bf768bda8c 100644 --- a/test/specs/gfm/gfm-spec.js +++ b/test/specs/gfm/gfm-spec.js @@ -28,7 +28,7 @@ var messenger = new Messenger(); describe('GFM 0.28 Tables', function() { var section = 'Tables'; - var shouldPassButFails = [192, 195, 196, 197]; + var shouldPassButFails = []; var willNotBeAttemptedByCoreTeam = []; diff --git a/test/specs/gfm/gfm.0.28.json b/test/specs/gfm/gfm.0.28.json index 87d12d35ee..d045f8af62 100644 --- a/test/specs/gfm/gfm.0.28.json +++ b/test/specs/gfm/gfm.0.28.json @@ -45,7 +45,7 @@ "section": "Tables", "html": "\n\n\n\n\n\n
abcdef
", "markdown": "| abc | def |\n| --- | --- |", - "example": 197 + "example": 198 }, { "section": "Task list items",