Handle colspan in TD tags

This commit is contained in:
Laurent Cozic 2018-05-24 12:31:40 +01:00
parent 44aa7353f0
commit 59153ece46
2 changed files with 35 additions and 10 deletions

View File

@ -8,6 +8,7 @@ This is a fork of the original [turndown-plugin-gfm](https://github.com/domchris
- New: Don't render the border of tables that contain other tables (frequent for websites that do the layout using tables). Only render the inner tables, if any, and if they also don't contain other tables. - New: Don't render the border of tables that contain other tables (frequent for websites that do the layout using tables). Only render the inner tables, if any, and if they also don't contain other tables.
- New: Replace newlines (`\n`) with `<br>` inside table cells so that multi-line content is displayed correctly as Markdown. - New: Replace newlines (`\n`) with `<br>` inside table cells so that multi-line content is displayed correctly as Markdown.
- New: Table cells are at least three characters long (padded with spaces) so that they render correctly in GFM-compliant renderers. - New: Table cells are at least three characters long (padded with spaces) so that they render correctly in GFM-compliant renderers.
- New: Handle colspan in TD tags
- Fixed: Ensure there are no blank lines inside tables (due for example to an empty `<tr>` tag) - Fixed: Ensure there are no blank lines inside tables (due for example to an empty `<tr>` tag)
## Installation ## Installation

View File

@ -13,21 +13,26 @@ rules.tableCell = {
rules.tableRow = { rules.tableRow = {
filter: 'tr', filter: 'tr',
replacement: function (content, node) { replacement: function (content, node) {
if (nodeContainsTable(nodeParentTable(node))) return content; const parentTable = nodeParentTable(node);
if (nodeContainsTable(parentTable)) return content;
var borderCells = '' var borderCells = ''
var alignMap = { left: ':--', right: '--:', center: ':-:' } var alignMap = { left: ':--', right: '--:', center: ':-:' }
if (isHeadingRow(node)) { if (isHeadingRow(node)) {
for (var i = 0; i < node.childNodes.length; i++) { const colCount = tableColCount(parentTable);
for (var i = 0; i < colCount; i++) {
const childNode = colCount >= node.childNodes.length ? null : node.childNodes[i];
var border = '---' var border = '---'
var align = ( var align = childNode ? (childNode.getAttribute('align') || '').toLowerCase() : '';
node.childNodes[i].getAttribute('align') || ''
).toLowerCase()
if (align) border = alignMap[align] || border if (align) border = alignMap[align] || border
borderCells += cell(border, node.childNodes[i]) if (childNode) {
borderCells += cell(border, node.childNodes[i])
} else {
borderCells += cell(border, null, i);
}
} }
} }
return '\n' + content + (borderCells ? '\n' + borderCells : '') return '\n' + content + (borderCells ? '\n' + borderCells : '')
@ -46,7 +51,7 @@ rules.table = {
// If table has no heading, add an empty one so as to get a valid Markdown table // If table has no heading, add an empty one so as to get a valid Markdown table
var firstRow = node.rows.length ? node.rows[0] : null var firstRow = node.rows.length ? node.rows[0] : null
var columnCount = firstRow ? firstRow.childNodes.length : 0 var columnCount = tableColCount(node); //firstRow ? firstRow.childNodes.length : 0
var emptyHeader = '' var emptyHeader = ''
if (columnCount && !isHeadingRow(firstRow)) { if (columnCount && !isHeadingRow(firstRow)) {
emptyHeader = '|' + ' |'.repeat(columnCount) + '\n' + '|' + ' --- |'.repeat(columnCount) emptyHeader = '|' + ' |'.repeat(columnCount) + '\n' + '|' + ' --- |'.repeat(columnCount)
@ -95,12 +100,13 @@ function isFirstTbody (element) {
) )
} }
function cell (content, node) { function cell (content, node = null, index = null) {
var index = indexOf.call(node.parentNode.childNodes, node) if (index === null) index = indexOf.call(node.parentNode.childNodes, node)
var prefix = ' ' var prefix = ' '
if (index === 0) prefix = '| ' if (index === 0) prefix = '| '
let filteredContent = content.trim().replace(/[\n\r]/g, "<br>"); let filteredContent = content.trim().replace(/\n\r/g, '<br>').replace(/\n/g, "<br>");
while (filteredContent.length < 3) filteredContent += ' '; while (filteredContent.length < 3) filteredContent += ' ';
if (node) filteredContent = handleColSpan(filteredContent, node, ' ');
return prefix + filteredContent + ' |' return prefix + filteredContent + ' |'
} }
@ -124,6 +130,24 @@ function nodeParentTable(node) {
return parent; return parent;
} }
function handleColSpan(content, node, emptyChar) {
const colspan = node.getAttribute('colspan') || 1;
for (let i = 1; i < colspan; i++) {
content += ' | ' + emptyChar.repeat(3);
}
return content
}
function tableColCount(node) {
let maxColCount = 0;
for (let i = 0; i < node.rows.length; i++) {
const row = node.rows[i]
const colCount = row.childNodes.length
if (colCount > maxColCount) maxColCount = colCount
}
return maxColCount
}
export default function tables (turndownService) { export default function tables (turndownService) {
turndownService.keep(function (node) { turndownService.keep(function (node) {
return node.nodeName === 'TABLE' return node.nodeName === 'TABLE'