feat(subParsers/table): support for table alignment

Credits to [torcellite (Karthik Balakrishnan)](https://github.com/torcellite)
This commit is contained in:
Estevão Soares dos Santos 2015-07-11 18:21:43 +01:00
parent 3a924e3c7e
commit 1c8c928d0a
22 changed files with 264 additions and 86 deletions

View File

@ -33,7 +33,11 @@ Credits
Bug fixing and late maintainer
* [Hannah Wolfe](https://github.com/ErisDS)<br/>
Bug fixes
* [Alexandre Courtiol](https://github.com/acourtiol)
* [Alexandre Courtiol](https://github.com/acourtiol)<br/>
Bug fixes and build optimization
* [Karthik Balakrishnan](https://github.com/torcellite)<br/>
Support for table alignment
- Original Project
* [John Gruber](http://daringfireball.net/projects/markdown/)<br/>

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

@ -15,7 +15,8 @@ var showdown = {},
simplifiedAutoLink: false,
literalMidWordUnderscores: false,
strikethrough: false,
tables: false
tables: false,
tablesHeaderId: false
},
globalOptions = JSON.parse(JSON.stringify(defaultOptions)); //clone default options out of laziness =P

View File

@ -4,46 +4,68 @@ showdown.subParser('tables', function (text, options, globals) {
var table = function () {
var tables = {},
style = 'text-align:left;',
filter;
tables.th = function (header) {
if (header.trim() === '') {
tables.th = function (header, style) {
var id = '';
header = header.trim();
if (header === '') {
return '';
}
var id = header.trim().replace(/ /g, '_').toLowerCase();
return '<th id="' + id + '" style="' + style + '">' + header + '</th>';
if (options.tableHeaderId) {
id = ' id="' + header.replace(/ /g, '_').toLowerCase() + '"';
}
if (style.trim() === '') {
style = '';
} else {
style = ' style="' + style + '"';
}
return '<th' + id + style + '>' + header + '</th>';
};
tables.td = function (cell) {
var subText = showdown.subParser('blockGamut')(cell, options, globals);
return '<td style="' + style + '">' + subText + '</td>';
tables.td = function (cell, style) {
var subText = showdown.subParser('spanGamut')(cell.trim(), options, globals);
if (style.trim() === '') {
style = '';
} else {
style = ' style="' + style + '"';
}
return '<td' + style + '>' + subText + '</td>';
};
tables.ths = function () {
var out = '',
i = 0,
hs = [].slice.apply(arguments);
i = 0,
hs = [].slice.apply(arguments[0]),
style = [].slice.apply(arguments[1]);
for (i; i < hs.length; i += 1) {
out += tables.th(hs[i]) + '\n';
out += tables.th(hs[i], style[i]) + '\n';
}
return out;
};
tables.tds = function () {
var out = '', i = 0, ds = [].slice.apply(arguments);
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]) + '\n';
out += tables.td(ds[i], style[i]) + '\n';
}
return out;
};
tables.thead = function () {
var out,
hs = [].slice.apply(arguments);
hs = [].slice.apply(arguments[0]),
style = [].slice.apply(arguments[1]);
out = '<thead>\n';
out += '<tr>\n';
out += tables.ths.apply(this, hs);
out += tables.ths.apply(this, [hs, style]);
out += '</tr>\n';
out += '</thead>\n';
return out;
@ -51,9 +73,11 @@ showdown.subParser('tables', function (text, options, globals) {
tables.tr = function () {
var out,
cs = [].slice.apply(arguments);
cs = [].slice.apply(arguments[0]),
style = [].slice.apply(arguments[1]);
out = '<tr>\n';
out += tables.tds.apply(this, cs);
out += tables.tds.apply(this, [cs, style]);
out += '</tr>\n';
return out;
};
@ -64,15 +88,44 @@ showdown.subParser('tables', function (text, options, globals) {
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 = [];
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('|');
tbl.push(tables.thead.apply(this, hs));
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
@ -82,7 +135,7 @@ showdown.subParser('tables', function (text, options, globals) {
tbl.push('<tbody>');
while (line.trim().match(/^[|].*[|]$/)) {
line = line.trim();
tbl.push(tables.tr.apply(this, line.substring(1, line.length - 1).split('|')));
tbl.push(tables.tr.apply(this, [line.substring(1, line.length - 1).split('|'), styles]));
line = lines[++i];
}
tbl.push('</tbody>');

View File

@ -1,20 +1,20 @@
<table>
<thead>
<tr>
<th id="first_header" style="text-align:left;"> First Header </th>
<th id="second_header" style="text-align:left;"> Second Header </th>
<th style="text-align:left;">First Header</th>
<th style="text-align:left;">Second Header</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left;"><p>Row 1 Cell 1 </p></td>
<td style="text-align:left;"><p>Row 1 Cell 2 </p></td>
<td style="text-align:left;">Row 1 Cell 1</td>
<td style="text-align:left;">Row 1 Cell 2</td>
</tr>
<tr>
<td style="text-align:left;"><p>Row 2 Cell 1 </p></td>
<td style="text-align:left;"><p>Row 2 Cell 2 </p></td>
<td style="text-align:left;">Row 2 Cell 1</td>
<td style="text-align:left;">Row 2 Cell 2</td>
</tr>
</tbody>

View File

@ -1,20 +1,20 @@
<table>
<thead>
<tr>
<th id="first_header" style="text-align:left;"> First Header </th>
<th id="second_header" style="text-align:left;"> Second Header </th>
<th>First Header</th>
<th>Second Header</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left;"><p>Row 1 Cell 1 </p></td>
<td style="text-align:left;"><p>Row 1 Cell 2 </p></td>
<td>Row 1 Cell 1</td>
<td>Row 1 Cell 2</td>
</tr>
<tr>
<td style="text-align:left;"><p>Row 2 Cell 1 </p></td>
<td style="text-align:left;"><p>Row 2 Cell 2 </p></td>
<td>Row 2 Cell 1</td>
<td>Row 2 Cell 2</td>
</tr>
</tbody>

View File

@ -0,0 +1,21 @@
<table>
<thead>
<tr>
<th id="first_header">First Header</th>
<th id="second_header">Second Header</th>
</tr>
</thead>
<tbody>
<tr>
<td>Row 1 Cell 1</td>
<td>Row 1 Cell 2</td>
</tr>
<tr>
<td>Row 2 Cell 1</td>
<td>Row 2 Cell 2</td>
</tr>
</tbody>
</table>

View File

@ -0,0 +1,4 @@
| First Header | Second Header |
| ------------- | ------------- |
| Row 1 Cell 1 | Row 1 Cell 2 |
| Row 2 Cell 1 | Row 2 Cell 2 |

View File

@ -0,0 +1,48 @@
<table>
<thead>
<tr>
<th style="text-align:left;">First Header</th>
<th style="text-align:center;">Second Header</th>
<th style="text-align:right;">Third Header</th>
<th>Fourth Header</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left;">Row 1 Cell 1</td>
<td style="text-align:center;">Row 1 Cell 2</td>
<td style="text-align:right;">Row 1 Cell 3</td>
<td>Row 1 Cell 4</td>
</tr>
<tr>
<td style="text-align:left;">Row 2 Cell 1</td>
<td style="text-align:center;">Row 2 Cell 2</td>
<td style="text-align:right;">Row 2 Cell 3</td>
<td>Row 2 Cell 4</td>
</tr>
<tr>
<td style="text-align:left;">Row 3 Cell 1</td>
<td style="text-align:center;">Row 3 Cell 2</td>
<td style="text-align:right;">Row 3 Cell 3</td>
<td>Row 3 Cell 4</td>
</tr>
<tr>
<td style="text-align:left;">Row 4 Cell 1</td>
<td style="text-align:center;">Row 4 Cell 2</td>
<td style="text-align:right;">Row 4 Cell 3</td>
<td>Row 4 Cell 4</td>
</tr>
<tr>
<td style="text-align:left;">Row 5 Cell 1</td>
<td style="text-align:center;">Row 5 Cell 2</td>
<td style="text-align:right;">Row 5 Cell 3</td>
<td>Row 5 Cell 4</td>
</tr>
</tbody>
</table>

View File

@ -0,0 +1,7 @@
| First Header | Second Header | Third Header | Fourth Header |
| :------------ |: ----------- :| ------------ :| ------------- |
| Row 1 Cell 1 | Row 1 Cell 2 | Row 1 Cell 3 | Row 1 Cell 4 |
| Row 2 Cell 1 | Row 2 Cell 2 | Row 2 Cell 3 | Row 2 Cell 4 |
| Row 3 Cell 1 | Row 3 Cell 2 | Row 3 Cell 3 | Row 3 Cell 4 |
| Row 4 Cell 1 | Row 4 Cell 2 | Row 4 Cell 3 | Row 4 Cell 4 |
| Row 5 Cell 1 | Row 5 Cell 2 | Row 5 Cell 3 | Row 5 Cell 4 |

View File

@ -1,47 +1,47 @@
<table>
<thead>
<tr>
<th id="first_header" style="text-align:left;"> First Header </th>
<th id="second_header" style="text-align:left;"> Second Header </th>
<th id="third_header" style="text-align:left;"> Third Header </th>
<th id="fourth_header" style="text-align:left;"> Fourth Header </th>
<th>First Header</th>
<th>Second Header</th>
<th>Third Header</th>
<th>Fourth Header</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left;"><p>Row 1 Cell 1 </p></td>
<td style="text-align:left;"><p>Row 1 Cell 2 </p></td>
<td style="text-align:left;"><p>Row 1 Cell 3 </p></td>
<td style="text-align:left;"><p>Row 1 Cell 4 </p></td>
<td>Row 1 Cell 1</td>
<td>Row 1 Cell 2</td>
<td>Row 1 Cell 3</td>
<td>Row 1 Cell 4</td>
</tr>
<tr>
<td style="text-align:left;"><p>Row 2 Cell 1 </p></td>
<td style="text-align:left;"><p>Row 2 Cell 2 </p></td>
<td style="text-align:left;"><p>Row 2 Cell 3 </p></td>
<td style="text-align:left;"><p>Row 2 Cell 4 </p></td>
<td>Row 2 Cell 1</td>
<td>Row 2 Cell 2</td>
<td>Row 2 Cell 3</td>
<td>Row 2 Cell 4</td>
</tr>
<tr>
<td style="text-align:left;"><p>Row 3 Cell 1 </p></td>
<td style="text-align:left;"><p>Row 3 Cell 2 </p></td>
<td style="text-align:left;"><p>Row 3 Cell 3 </p></td>
<td style="text-align:left;"><p>Row 3 Cell 4 </p></td>
<td>Row 3 Cell 1</td>
<td>Row 3 Cell 2</td>
<td>Row 3 Cell 3</td>
<td>Row 3 Cell 4</td>
</tr>
<tr>
<td style="text-align:left;"><p>Row 4 Cell 1 </p></td>
<td style="text-align:left;"><p>Row 4 Cell 2 </p></td>
<td style="text-align:left;"><p>Row 4 Cell 3 </p></td>
<td style="text-align:left;"><p>Row 4 Cell 4 </p></td>
<td>Row 4 Cell 1</td>
<td>Row 4 Cell 2</td>
<td>Row 4 Cell 3</td>
<td>Row 4 Cell 4</td>
</tr>
<tr>
<td style="text-align:left;"><p>Row 5 Cell 1 </p></td>
<td style="text-align:left;"><p>Row 5 Cell 2 </p></td>
<td style="text-align:left;"><p>Row 5 Cell 3 </p></td>
<td style="text-align:left;"><p>Row 5 Cell 4 </p></td>
<td>Row 5 Cell 1</td>
<td>Row 5 Cell 2</td>
<td>Row 5 Cell 3</td>
<td>Row 5 Cell 4</td>
</tr>
</tbody>

View File

@ -0,0 +1,29 @@
<table>
<thead>
<tr>
<th style="text-align:left;">Left-Aligned</th>
<th style="text-align:center;">Center-Aligned</th>
<th style="text-align:right;">Right-Aligned</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left;">col 3 is</td>
<td style="text-align:center;">some wordy paragraph</td>
<td style="text-align:right;">$1600</td>
</tr>
<tr>
<td style="text-align:left;">col 2 is</td>
<td style="text-align:center;">centered</td>
<td style="text-align:right;">$12</td>
</tr>
<tr>
<td style="text-align:left;">zebra stripes</td>
<td style="text-align:center;">are neat</td>
<td style="text-align:right;">$1</td>
</tr>
</tbody>
</table>

View File

@ -0,0 +1,5 @@
| Left-Aligned | Center-Aligned | Right-Aligned |
| :------------ |:--------------------:| -------------:|
| col 3 is | some wordy paragraph | $1600 |
| col 2 is | centered | $12 |
| zebra stripes | are neat | $1 |

View File

@ -5,17 +5,17 @@
<table>
<thead>
<tr>
<th id="header1" style="text-align:left;">header1 </th>
<th id="header2" style="text-align:left;">header2 </th>
<th id="header3" style="text-align:left;">header3</th>
<th>header1</th>
<th>header2</th>
<th>header3</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left;"><p>Value1 </p></td>
<td style="text-align:left;"><p>Value2 </p></td>
<td style="text-align:left;"><p>Value3 </p></td>
<td>Value1</td>
<td>Value2</td>
<td>Value3</td>
</tr>
</tbody>
@ -26,17 +26,17 @@
<table>
<thead>
<tr>
<th id="headera" style="text-align:left;">headerA </th>
<th id="headerb" style="text-align:left;">headerB </th>
<th id="headerc" style="text-align:left;">headerC</th>
<th>headerA</th>
<th>headerB</th>
<th>headerC</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left;"><p>ValueA </p></td>
<td style="text-align:left;"><p>ValueB </p></td>
<td style="text-align:left;"><p>ValueC </p></td>
<td>ValueA</td>
<td>ValueB</td>
<td>ValueC</td>
</tr>
</tbody>

View File

@ -1,20 +1,20 @@
<table>
<thead>
<tr>
<th id="first_header" style="text-align:left;"> First Header </th>
<th id="second_header" style="text-align:left;"> Second Header </th>
<th>First Header</th>
<th>Second Header</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left;"><p>Row 1 Cell 1 </p></td>
<td style="text-align:left;"><p>Row 1 Cell 2 </p></td>
<td>Row 1 Cell 1</td>
<td>Row 1 Cell 2</td>
</tr>
<tr>
<td style="text-align:left;"><p>Row 2 Cell 1 </p></td>
<td style="text-align:left;"><p>Row 2 Cell 2 </p></td>
<td>Row 2 Cell 1</td>
<td>Row 2 Cell 2</td>
</tr>
</tbody>

View File

@ -6,20 +6,20 @@ vulputate dictum. Vestibulum consequat ultricies nibh, sed tempus nisl mattis a.
<table>
<thead>
<tr>
<th id="first_header" style="text-align:left;"> First Header </th>
<th id="second_header" style="text-align:left;"> Second Header </th>
<th>First Header</th>
<th>Second Header</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left;"><p>Row 1 Cell 1 </p></td>
<td style="text-align:left;"><p>Row 1 Cell 2 </p></td>
<td>Row 1 Cell 1</td>
<td>Row 1 Cell 2</td>
</tr>
<tr>
<td style="text-align:left;"><p>Row 2 Cell 1 </p></td>
<td style="text-align:left;"><p>Row 2 Cell 2 </p></td>
<td>Row 2 Cell 1</td>
<td>Row 2 Cell 2</td>
</tr>
</tbody>

View File

@ -1,8 +1,8 @@
<table>
<thead>
<tr>
<th id="first_header" style="text-align:left;"> First Header </th>
<th id="second_header" style="text-align:left;"> Second Header </th>
<th>First Header</th>
<th>Second Header</th>
</tr>
</thead>

View File

@ -26,7 +26,8 @@ describe('showdown.options', function () {
simplifiedAutoLink: false,
literalMidWordUnderscores: false,
strikethrough: false,
tables: false
tables: false,
tablesHeaderId: false
};
expect(showdown.getDefaultOptions()).to.be.eql(opts);
});

View File

@ -28,8 +28,13 @@ describe('makeHtml() features testsuite', function () {
}
describe('table support', function () {
var converter = new showdown.Converter({tables: true});
var converter;
for (var i = 0; i < tableSuite.length; ++i) {
if (tableSuite[i].name === 'basic_with_header_ids') {
converter = new showdown.Converter({tables: true, tableHeaderId: true});
} else {
converter = new showdown.Converter({tables: true});
}
it(tableSuite[i].name, assertion(tableSuite[i], converter));
}
});