From c7e3a31ed80723bd99030afa9e9a7c9fd3cb1739 Mon Sep 17 00:00:00 2001 From: wljince007 Date: Fri, 13 Dec 2024 20:57:23 +0800 Subject: [PATCH] Desktop: Make table in HTML format horizontally scrollable (#11198) Co-authored-by: Laurent Cozic --- .../html_to_md/preserve_nested_tables.md | 2 +- .../tests/html_to_md/table_with_blockquote.md | 2 +- .../tests/html_to_md/table_with_code_1.md | 2 +- .../tests/html_to_md/table_with_code_2.md | 2 +- .../tests/html_to_md/table_with_code_3.md | 14 ++-- .../tests/html_to_md/table_with_heading.md | 2 +- .../app-cli/tests/html_to_md/table_with_hr.md | 2 +- .../tests/html_to_md/table_with_list.md | 2 +- packages/turndown-plugin-gfm/src/tables.js | 80 +++++++++++++------ 9 files changed, 70 insertions(+), 38 deletions(-) diff --git a/packages/app-cli/tests/html_to_md/preserve_nested_tables.md b/packages/app-cli/tests/html_to_md/preserve_nested_tables.md index 4c3d10dde..bb36e1b69 100644 --- a/packages/app-cli/tests/html_to_md/preserve_nested_tables.md +++ b/packages/app-cli/tests/html_to_md/preserve_nested_tables.md @@ -1 +1 @@ -
Left side of the main tableNested Table
nested table C1nested table C2
nested tablenested table
\ No newline at end of file +
Left side of the main tableNested Table
nested table C1nested table C2
nested tablenested table
\ No newline at end of file diff --git a/packages/app-cli/tests/html_to_md/table_with_blockquote.md b/packages/app-cli/tests/html_to_md/table_with_blockquote.md index 87cfdc5f2..a9b79103a 100644 --- a/packages/app-cli/tests/html_to_md/table_with_blockquote.md +++ b/packages/app-cli/tests/html_to_md/table_with_blockquote.md @@ -1 +1 @@ -
AB

Finally, from so little sleeping and so much reading, his brain dried up and he went completely out of his mind.

- Miguel de Cervantes

d
\ No newline at end of file +
AB

Finally, from so little sleeping and so much reading, his brain dried up and he went completely out of his mind.

- Miguel de Cervantes

d
\ No newline at end of file diff --git a/packages/app-cli/tests/html_to_md/table_with_code_1.md b/packages/app-cli/tests/html_to_md/table_with_code_1.md index 6f0bfbaa0..972505e42 100644 --- a/packages/app-cli/tests/html_to_md/table_with_code_1.md +++ b/packages/app-cli/tests/html_to_md/table_with_code_1.md @@ -1 +1 @@ -
CodeDescription
const test = "hello";
abcd
const test = "hello";
abcd
\ No newline at end of file +
CodeDescription
const test = "hello";
abcd
const test = "hello";
abcd
\ No newline at end of file diff --git a/packages/app-cli/tests/html_to_md/table_with_code_2.md b/packages/app-cli/tests/html_to_md/table_with_code_2.md index 0bf437036..b079415b3 100644 --- a/packages/app-cli/tests/html_to_md/table_with_code_2.md +++ b/packages/app-cli/tests/html_to_md/table_with_code_2.md @@ -1 +1 @@ -
CodeDescription
const test = "hello";
abcda
const test = "hello";
abcd
\ No newline at end of file +
CodeDescription
const test = "hello";
abcda
const test = "hello";
abcd
\ No newline at end of file diff --git a/packages/app-cli/tests/html_to_md/table_with_code_3.md b/packages/app-cli/tests/html_to_md/table_with_code_3.md index b62d11465..0a006b493 100644 --- a/packages/app-cli/tests/html_to_md/table_with_code_3.md +++ b/packages/app-cli/tests/html_to_md/table_with_code_3.md @@ -1,10 +1,10 @@ -
CodeDescription
const test = "hello";
-
+
CodeDescription
const test = "hello";
+
 // Another line
 console.log('Test...');
-
+
 // Blank lines
-
-
-
-// Should not break things.
abcda
const test = "hello";
abcd
\ No newline at end of file + + + +// Should not break things.
abcda
const test = "hello";
abcd
\ No newline at end of file diff --git a/packages/app-cli/tests/html_to_md/table_with_heading.md b/packages/app-cli/tests/html_to_md/table_with_heading.md index 9db794178..025640377 100644 --- a/packages/app-cli/tests/html_to_md/table_with_heading.md +++ b/packages/app-cli/tests/html_to_md/table_with_heading.md @@ -1 +1 @@ -
AB

Testing

hello

d
\ No newline at end of file +
AB

Testing

hello

d
\ No newline at end of file diff --git a/packages/app-cli/tests/html_to_md/table_with_hr.md b/packages/app-cli/tests/html_to_md/table_with_hr.md index ae56fd6f2..8ce533b02 100644 --- a/packages/app-cli/tests/html_to_md/table_with_hr.md +++ b/packages/app-cli/tests/html_to_md/table_with_hr.md @@ -1 +1 @@ -
AB
One line
Two line
d
\ No newline at end of file +
AB
One line
Two line
d
\ No newline at end of file diff --git a/packages/app-cli/tests/html_to_md/table_with_list.md b/packages/app-cli/tests/html_to_md/table_with_list.md index 933cf5fb8..7025daa22 100644 --- a/packages/app-cli/tests/html_to_md/table_with_list.md +++ b/packages/app-cli/tests/html_to_md/table_with_list.md @@ -1 +1 @@ -
Header 1Header 2

  • Check 1
  • Check 2
\ No newline at end of file +
Header 1Header 2

  • Check 1
  • Check 2
\ 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 c5469d4f2..7bdc0ed36 100644 --- a/packages/turndown-plugin-gfm/src/tables.js +++ b/packages/turndown-plugin-gfm/src/tables.js @@ -4,6 +4,7 @@ var rules = {} var alignMap = { left: ':---', right: '---:', center: ':---:' }; let isCodeBlock_ = null; +let options_ = null; // We need to cache the result of tableShouldBeSkipped() as it is expensive. // Caching it means we went from about 9000 ms for rendering down to 90 ms. @@ -72,36 +73,57 @@ rules.tableRow = { } rules.table = { - // Only convert tables that can result in valid Markdown - // Other tables are kept as HTML using `keep` (see below). filter: function (node, options) { - return node.nodeName === 'TABLE' && !tableShouldBeHtml(node, options); + return node.nodeName === 'TABLE'; }, replacement: function (content, node) { - if (tableShouldBeSkipped(node)) return content; - - // Ensure there are no blank lines - content = content.replace(/\n+/g, '\n') - - // 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 = /\| :?---/.test(secondLine); - - var columnCount = tableColCount(node); - var emptyHeader = '' - if (columnCount && !secondLineIsDivider) { - emptyHeader = '|' + ' |'.repeat(columnCount) + '\n' + '|' - for (var columnIndex = 0; columnIndex < columnCount; ++columnIndex) { - emptyHeader += ' ' + getBorder(getColumnAlignment(node, columnIndex)) + ' |'; + // Only convert tables that can result in valid Markdown + // Other tables are kept as HTML using `keep` (see below). + if (tableShouldBeHtml(node, options_)) { + let html = node.outerHTML; + let divParent = nodeParentDiv(node) + // Make table in HTML format horizontally scrollable by give table a div parent, so the width of the table is limited to the screen width. + // see https://github.com/laurent22/joplin/pull/10161 + // test cases: + // packages/app-cli/tests/html_to_md/preserve_nested_tables.html + // packages/app-cli/tests/html_to_md/table_with_blockquote.html + // packages/app-cli/tests/html_to_md/table_with_code_1.html + // packages/app-cli/tests/html_to_md/table_with_code_2.html + // packages/app-cli/tests/html_to_md/table_with_code_3.html + // packages/app-cli/tests/html_to_md/table_with_heading.html + // packages/app-cli/tests/html_to_md/table_with_hr.html + // packages/app-cli/tests/html_to_md/table_with_list.html + if (divParent === null || !divParent.classList.contains('joplin-table-wrapper')){ + return `\n\n
${html}
\n\n`; + } else { + return html } - } + } else { + if (tableShouldBeSkipped(node)) return content; - const captionContent = node.caption ? node.caption.textContent || '' : ''; - const caption = captionContent ? `${captionContent}\n\n` : ''; - const tableContent = `${emptyHeader}${content}`.trimStart(); - return `\n\n${caption}${tableContent}\n\n`; + // Ensure there are no blank lines + content = content.replace(/\n+/g, '\n') + + // 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 = /\| :?---/.test(secondLine); + + var columnCount = tableColCount(node); + var emptyHeader = '' + if (columnCount && !secondLineIsDivider) { + emptyHeader = '|' + ' |'.repeat(columnCount) + '\n' + '|' + for (var columnIndex = 0; columnIndex < columnCount; ++columnIndex) { + emptyHeader += ' ' + getBorder(getColumnAlignment(node, columnIndex)) + ' |'; + } + } + + const captionContent = node.caption ? node.caption.textContent || '' : ''; + const caption = captionContent ? `${captionContent}\n\n` : ''; + const tableContent = `${emptyHeader}${content}`.trimStart(); + return `\n\n${caption}${tableContent}\n\n`; + } } } @@ -232,6 +254,15 @@ function tableShouldBeSkipped_(tableNode) { return false; } +function nodeParentDiv(node) { + let parent = node.parentNode; + while (parent.nodeName !== 'DIV') { + parent = parent.parentNode; + if (!parent) return null; + } + return parent; +} + function nodeParentTable(node) { let parent = node.parentNode; while (parent.nodeName !== 'TABLE') { @@ -261,6 +292,7 @@ function tableColCount(node) { export default function tables (turndownService) { isCodeBlock_ = turndownService.isCodeBlock; + options_ = turndownService.options; turndownService.keep(function (node) { if (node.nodeName === 'TABLE' && tableShouldBeHtml(node, turndownService.options)) return true;