From 745849023d58ca0e84024350be8e41d0997e99b2 Mon Sep 17 00:00:00 2001 From: Christopher O'Toole Date: Mon, 29 May 2023 03:10:17 -0700 Subject: [PATCH] Desktop: Fixes #6431: Preserve Table Alignment When Editing a Note With the Rich Text Editor (#8214) --- .../table_with_alignment_and_no_header.html | 19 +++++++ .../table_with_alignment_and_no_header.md | 5 ++ .../html_to_md/table_with_css_alignment.html | 26 +++++++++ .../html_to_md/table_with_css_alignment.md | 5 ++ .../html_to_md/table_with_html_alignment.html | 14 +++++ .../html_to_md/table_with_html_alignment.md | 3 + ...ltiple_alignments_keeps_most_frequent.html | 29 ++++++++++ ...multiple_alignments_keeps_most_frequent.md | 5 ++ packages/turndown-plugin-gfm/src/tables.js | 56 ++++++++++++++----- 9 files changed, 148 insertions(+), 14 deletions(-) create mode 100644 packages/app-cli/tests/html_to_md/table_with_alignment_and_no_header.html create mode 100644 packages/app-cli/tests/html_to_md/table_with_alignment_and_no_header.md create mode 100644 packages/app-cli/tests/html_to_md/table_with_css_alignment.html create mode 100644 packages/app-cli/tests/html_to_md/table_with_css_alignment.md create mode 100644 packages/app-cli/tests/html_to_md/table_with_html_alignment.html create mode 100644 packages/app-cli/tests/html_to_md/table_with_html_alignment.md create mode 100644 packages/app-cli/tests/html_to_md/table_with_multiple_alignments_keeps_most_frequent.html create mode 100644 packages/app-cli/tests/html_to_md/table_with_multiple_alignments_keeps_most_frequent.md diff --git a/packages/app-cli/tests/html_to_md/table_with_alignment_and_no_header.html b/packages/app-cli/tests/html_to_md/table_with_alignment_and_no_header.html new file mode 100644 index 000000000..4bb6d0d16 --- /dev/null +++ b/packages/app-cli/tests/html_to_md/table_with_alignment_and_no_header.html @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + +
LeftCenteredRight
LeftCenteredRight
LeftCenteredRight
\ No newline at end of file diff --git a/packages/app-cli/tests/html_to_md/table_with_alignment_and_no_header.md b/packages/app-cli/tests/html_to_md/table_with_alignment_and_no_header.md new file mode 100644 index 000000000..9640c0b8b --- /dev/null +++ b/packages/app-cli/tests/html_to_md/table_with_alignment_and_no_header.md @@ -0,0 +1,5 @@ +| | | | +| :--- | :---: | ---: | +| Left | Centered | Right | +| Left | Centered | Right | +| Left | Centered | Right | \ No newline at end of file diff --git a/packages/app-cli/tests/html_to_md/table_with_css_alignment.html b/packages/app-cli/tests/html_to_md/table_with_css_alignment.html new file mode 100644 index 000000000..b9ab86a16 --- /dev/null +++ b/packages/app-cli/tests/html_to_md/table_with_css_alignment.html @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +
Left-aligned ColumnCenter-aligned ColumnRight-aligned Column
LeftCenteredRight
LeftCenteredRight
LeftCenteredRight
\ No newline at end of file diff --git a/packages/app-cli/tests/html_to_md/table_with_css_alignment.md b/packages/app-cli/tests/html_to_md/table_with_css_alignment.md new file mode 100644 index 000000000..9ea5433a4 --- /dev/null +++ b/packages/app-cli/tests/html_to_md/table_with_css_alignment.md @@ -0,0 +1,5 @@ +| Left-aligned Column | Center-aligned Column | Right-aligned Column | +| :--- | :---: | ---: | +| Left | Centered | Right | +| Left | Centered | Right | +| Left | Centered | Right | \ No newline at end of file diff --git a/packages/app-cli/tests/html_to_md/table_with_html_alignment.html b/packages/app-cli/tests/html_to_md/table_with_html_alignment.html new file mode 100644 index 000000000..6f834f295 --- /dev/null +++ b/packages/app-cli/tests/html_to_md/table_with_html_alignment.html @@ -0,0 +1,14 @@ + + + + + + + + + + + + + +
abcdefghi
barbaz
\ No newline at end of file diff --git a/packages/app-cli/tests/html_to_md/table_with_html_alignment.md b/packages/app-cli/tests/html_to_md/table_with_html_alignment.md new file mode 100644 index 000000000..e0c93137e --- /dev/null +++ b/packages/app-cli/tests/html_to_md/table_with_html_alignment.md @@ -0,0 +1,3 @@ +| abc | defghi | +| :---: | ---: | +| bar | baz | \ No newline at end of file diff --git a/packages/app-cli/tests/html_to_md/table_with_multiple_alignments_keeps_most_frequent.html b/packages/app-cli/tests/html_to_md/table_with_multiple_alignments_keeps_most_frequent.html new file mode 100644 index 000000000..b93ec5107 --- /dev/null +++ b/packages/app-cli/tests/html_to_md/table_with_multiple_alignments_keeps_most_frequent.html @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +
Left-aligned ColumnThis header cell's text is unaligned, but a majority of the text in this column is center-aligned so the + column will be center-alignedRight-aligned Column
LeftCenteredRight
This is the only right-aligned cell in this column. This is possible if a user + edits a cell's alignment using the cell properties dialog.CenteredRight
This is the only center-aligned cell in this column. This is possible if a + user edits a cell's alignment using the cell properties dialog.CenteredRight
\ No newline at end of file diff --git a/packages/app-cli/tests/html_to_md/table_with_multiple_alignments_keeps_most_frequent.md b/packages/app-cli/tests/html_to_md/table_with_multiple_alignments_keeps_most_frequent.md new file mode 100644 index 000000000..156087c65 --- /dev/null +++ b/packages/app-cli/tests/html_to_md/table_with_multiple_alignments_keeps_most_frequent.md @@ -0,0 +1,5 @@ +| Left-aligned Column | This header cell's text is unaligned, but a majority of the text in this column is center-aligned so the column will be center-aligned | Right-aligned Column | +| :--- | :---: | ---: | +| Left | Centered | Right | +| This is the only right-aligned cell in this column. This is possible if a user edits a cell's alignment using the cell properties dialog. | Centered | Right | +| This is the only center-aligned cell in this column. This is possible if a user edits a cell's alignment using the cell properties dialog. | Centered | Right | \ No newline at end of file diff --git a/packages/turndown-plugin-gfm/src/tables.js b/packages/turndown-plugin-gfm/src/tables.js index 74f5c526d..1978e5b03 100644 --- a/packages/turndown-plugin-gfm/src/tables.js +++ b/packages/turndown-plugin-gfm/src/tables.js @@ -1,6 +1,40 @@ var indexOf = Array.prototype.indexOf var every = Array.prototype.every var rules = {} +var alignMap = { left: ':---', right: '---:', center: ':---:' }; + +function getAlignment(node) { + return node ? (node.getAttribute('align') || node.style.textAlign || '').toLowerCase() : ''; +} + +function getBorder(alignment) { + return alignment ? alignMap[alignment] : '---'; +} + +function getColumnAlignment(table, columnIndex) { + var votes = { + left: 0, + right: 0, + center: 0, + '': 0, + }; + + var align = ''; + + for (var i = 0; i < table.rows.length; ++i) { + var row = table.rows[i]; + if (columnIndex < row.childNodes.length) { + var cellAlignment = getAlignment(row.childNodes[columnIndex]); + ++votes[cellAlignment]; + + if (votes[cellAlignment] > votes[align]) { + align = cellAlignment; + } + } + } + + return align; +} rules.tableCell = { filter: ['th', 'td'], @@ -17,22 +51,13 @@ rules.tableRow = { if (tableShouldBeSkipped(parentTable)) return content; var borderCells = '' - var alignMap = { left: ':--', right: '--:', center: ':-:' } if (isHeadingRow(node)) { const colCount = tableColCount(parentTable); for (var i = 0; i < colCount; i++) { - const childNode = colCount >= node.childNodes.length ? null : node.childNodes[i]; - var border = '---' - var align = childNode ? (childNode.getAttribute('align') || '').toLowerCase() : ''; - - if (align) border = alignMap[align] || border - - if (childNode) { - borderCells += cell(border, node.childNodes[i]) - } else { - borderCells += cell(border, null, i); - } + const childNode = i < node.childNodes.length ? node.childNodes[i] : null; + var border = getBorder(getColumnAlignment(parentTable, i)); + borderCells += cell(border, childNode, i); } } return '\n' + content + (borderCells ? '\n' + borderCells : '') @@ -55,12 +80,15 @@ rules.table = { // If table has no heading, add an empty one so as to get a valid Markdown table var secondLine = content.trim().split('\n'); if (secondLine.length >= 2) secondLine = secondLine[1] - var secondLineIsDivider = secondLine.indexOf('| ---') === 0 + var secondLineIsDivider = /\| :?---/.test(secondLine); var columnCount = tableColCount(node); var emptyHeader = '' if (columnCount && !secondLineIsDivider) { - emptyHeader = '|' + ' |'.repeat(columnCount) + '\n' + '|' + ' --- |'.repeat(columnCount) + emptyHeader = '|' + ' |'.repeat(columnCount) + '\n' + '|' + for (var columnIndex = 0; columnIndex < columnCount; ++columnIndex) { + emptyHeader += ' ' + getBorder(getColumnAlignment(node, columnIndex)) + ' |'; + } } return '\n\n' + emptyHeader + content + '\n\n'