fix(tables): fix tables to match github's md spec

Now Leading and trailing pipes (|) are optional in tables

Closes #230
This commit is contained in:
Estevão Soares dos Santos 2016-01-25 05:24:54 +00:00
parent 8d0cf545b8
commit f58f014bc3
7 changed files with 150 additions and 157 deletions

BIN
dist/showdown.js vendored

Binary file not shown.

BIN
dist/showdown.js.map vendored

Binary file not shown.

BIN
dist/showdown.min.js vendored

Binary file not shown.

Binary file not shown.

View File

@ -1,164 +1,129 @@
showdown.subParser('tables', function (text, options, globals) {
'use strict';
var table = function () {
var tables = {},
filter;
tables.th = function (header, style) {
var id = '';
header = header.trim();
if (header === '') {
return '';
}
if (options.tableHeaderId) {
id = ' id="' + header.replace(/ /g, '_').toLowerCase() + '"';
}
header = showdown.subParser('spanGamut')(header, options, globals);
if (!style || style.trim() === '') {
style = '';
} else {
style = ' style="' + style + '"';
}
return '<th' + id + style + '>' + header + '</th>';
};
tables.td = function (cell, style) {
var subText = showdown.subParser('spanGamut')(cell.trim(), options, globals);
if (!style || style.trim() === '') {
style = '';
} else {
style = ' style="' + style + '"';
}
return '<td' + style + '>' + subText + '</td>';
};
tables.ths = function () {
var out = '',
i = 0,
hs = [].slice.apply(arguments[0]),
style = [].slice.apply(arguments[1]);
for (i; i < hs.length; i += 1) {
out += tables.th(hs[i], style[i]) + '\n';
}
return out;
};
tables.tds = function () {
var out = '',
i = 0,
ds = [].slice.apply(arguments[0]),
style = [].slice.apply(arguments[1]);
for (i; i < ds.length; i += 1) {
out += tables.td(ds[i], style[i]) + '\n';
}
return out;
};
tables.thead = function () {
var out,
hs = [].slice.apply(arguments[0]),
style = [].slice.apply(arguments[1]);
out = '<thead>\n';
out += '<tr>\n';
out += tables.ths.apply(this, [hs, style]);
out += '</tr>\n';
out += '</thead>\n';
return out;
};
tables.tr = function () {
var out,
cs = [].slice.apply(arguments[0]),
style = [].slice.apply(arguments[1]);
out = '<tr>\n';
out += tables.tds.apply(this, [cs, style]);
out += '</tr>\n';
return out;
};
filter = function (text) {
var i = 0,
lines = text.split('\n'),
line,
hs,
out = [];
for (i; i < lines.length; i += 1) {
line = lines[i];
// looks like a table heading
if (line.trim().match(/^[|].*[|]$/)) {
line = line.trim();
var tbl = [],
align = lines[i + 1].trim(),
styles = [],
j = 0;
if (align.match(/^[|][-=|: ]+[|]$/)) {
styles = align.substring(1, align.length - 1).split('|');
for (j = 0; j < styles.length; ++j) {
styles[j] = styles[j].trim();
if (styles[j].match(/^[:][-=| ]+[:]$/)) {
styles[j] = 'text-align:center;';
} else if (styles[j].match(/^[-=| ]+[:]$/)) {
styles[j] = 'text-align:right;';
} else if (styles[j].match(/^[:][-=| ]+$/)) {
styles[j] = 'text-align:left;';
} else {
styles[j] = '';
}
}
}
tbl.push('<table>');
hs = line.substring(1, line.length - 1).split('|');
if (styles.length === 0) {
for (j = 0; j < hs.length; ++j) {
styles.push('text-align:left');
}
}
tbl.push(tables.thead.apply(this, [hs, styles]));
line = lines[++i];
if (!line.trim().match(/^[|][-=|: ]+[|]$/)) {
// not a table rolling back
line = lines[--i];
} else {
line = lines[++i];
tbl.push('<tbody>');
while (line.trim().match(/^[|].*[|]$/)) {
line = line.trim();
tbl.push(tables.tr.apply(this, [line.substring(1, line.length - 1).split('|'), styles]));
line = lines[++i];
}
tbl.push('</tbody>');
tbl.push('</table>');
// we are done with this table and we move along
out.push(tbl.join('\n'));
continue;
}
}
out.push(line);
}
return out.join('\n');
};
return {parse: filter};
};
if (options.tables) {
text = globals.converter._dispatch('tables.before', text, options);
var tableParser = table();
text = tableParser.parse(text);
text = globals.converter._dispatch('tables.after', text, options);
if (!options.tables) {
return text;
}
var tableRgx = /^[ \t]{0,3}\|?.+\|.+\n[ \t]{0,3}\|?[ \t]*:?[ \t]*(?:-|=){3,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:-|=){3,}[^]+?(?:\n\n|~0)/gm;
function parseStyles(sLine) {
if (/^:[ \t]*---*$/.test(sLine)) {
return ' style="text-align:left;"';
} else if (/^---*[ \t]*:[ \t]*$/.test(sLine)) {
return ' style="text-align:right;"';
} else if (/^:[ \t]*---*[ \t]*:$/.test(sLine)) {
return ' style="text-align:center;"';
} else {
return '';
}
}
function parseHeaders(header, style) {
var id = '';
header = header.trim();
if (options.tableHeaderId) {
id = ' id="' + header.replace(/ /g, '_').toLowerCase() + '"';
}
header = showdown.subParser('spanGamut')(header, options, globals);
return '<th' + id + style + '>' + header + '</th>';
}
function parseCells(cell, style) {
var subText = showdown.subParser('spanGamut')(cell, options, globals);
return '<td' + style + '>' + subText + '</td>';
}
function buildTable(headers, cells) {
var tb = '<table>\n<thead>\n<tr>\n',
tblLgn = headers.length;
for (var i = 0; i < tblLgn; ++i) {
tb += headers[i];
}
tb += '</tr>\n</thead>\n<tbody>\n';
for (i = 0; i < cells.length; ++i) {
tb += '<tr>';
for (var ii = 0; ii < tblLgn; ++ii) {
tb += cells[i][ii];
}
tb += '</tr>';
}
tb += '</tbody></table>';
return tb;
}
text = globals.converter._dispatch('tables.before', text, options);
text = text.replace(tableRgx, function (rawTable) {
var i, tableLines = rawTable.split('\n');
// strip wrong first and last column if wrapped tables are used
for (i = 0; i < tableLines.length; ++i) {
if (/^[ \t]{0,3}\|/.test(tableLines[i])) {
tableLines[i] = tableLines[i].replace(/^[ \t]{0,3}\|/, '');
}
if (/\|[ \t]*$/.test(tableLines[i])) {
tableLines[i] = tableLines[i].replace(/\|[ \t]*$/, '');
}
}
var rawHeaders = tableLines[0].split('|').map(function (s) { return s.trim();}),
rawStyles = tableLines[1].split('|').map(function (s) { return s.trim();}),
rawCells = [],
headers = [],
styles = [],
cells = [];
tableLines.shift();
tableLines.shift();
for (i = 0; i < tableLines.length; ++i) {
if (tableLines[i].trim() === '') {
continue;
}
rawCells.push(
tableLines[i]
.split('|')
.map(function (s) {
return s.trim();
})
);
}
if (rawHeaders.length < rawStyles.length) {
return rawTable;
}
for (i = 0; i < rawStyles.length; ++i) {
styles.push(parseStyles(rawStyles[i]));
}
for (i = 0; i < rawHeaders.length; ++i) {
if (showdown.helper.isUndefined(styles[i])) {
styles[i] = '';
}
headers.push(parseHeaders(rawHeaders[i], styles[i]));
}
for (i = 0; i < rawCells.length; ++i) {
var row = [];
for (var ii = 0; ii < headers.length; ++ii) {
if (showdown.helper.isUndefined(rawCells[i][ii])) {
}
row.push(parseCells(rawCells[i][ii], styles[ii]));
}
cells.push(row);
}
return buildTable(headers, cells);
});
text = globals.converter._dispatch('tables.after', text, options);
return text;
});

View File

@ -0,0 +1,24 @@
<table>
<thead>
<tr>
<th>First Header</th>
<th>Second Header</th>
<th>Third Header</th>
</tr>
</thead>
<tbody>
<tr>
<td>Content Cell</td>
<td>Content Cell</td>
<td>C</td>
</tr>
<tr>
<td>Content Cell</td>
<td>Content Cell</td>
<td>C</td>
</tr>
</tbody>
</table>

View File

@ -0,0 +1,4 @@
First Header | Second Header|Third Header
------------- | -------------|---
Content Cell | Content Cell|C
Content Cell | Content Cell|C