mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-18 09:35:20 +02:00
Desktop: Make table in HTML format horizontally scrollable (#11198)
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
This commit is contained in:
parent
dc445579da
commit
c7e3a31ed8
@ -1 +1 @@
|
||||
<table><tbody><tr><td>Left side of the main table</td><td><b>Nested Table</b><table><tbody><tr><td>nested table C1</td><td>nested table C2</td></tr><tr><td>nested table</td><td>nested table</td></tr></tbody></table></td></tr></tbody></table>
|
||||
<div class="joplin-table-wrapper"><table><tbody><tr><td>Left side of the main table</td><td><b>Nested Table</b><table><tbody><tr><td>nested table C1</td><td>nested table C2</td></tr><tr><td>nested table</td><td>nested table</td></tr></tbody></table></td></tr></tbody></table></div>
|
@ -1 +1 @@
|
||||
<table><thead><tr><th>A</th><th>B</th></tr></thead><tbody><tr><td><blockquote><p>Finally, from so little sleeping and so much reading, his brain dried up and he went completely out of his mind.</p><p>- Miguel de Cervantes</p></blockquote></td><td>d</td></tr></tbody></table>
|
||||
<div class="joplin-table-wrapper"><table><thead><tr><th>A</th><th>B</th></tr></thead><tbody><tr><td><blockquote><p>Finally, from so little sleeping and so much reading, his brain dried up and he went completely out of his mind.</p><p>- Miguel de Cervantes</p></blockquote></td><td>d</td></tr></tbody></table></div>
|
@ -1 +1 @@
|
||||
<table><thead><tr><th>Code</th><th>Description</th></tr><tr><td><pre><code>const test = "hello";</code></pre></td><td>abcd</td></tr><tr><td><pre><code>const test = "hello";</code></pre></td><td>abcd</td></tr></thead></table>
|
||||
<div class="joplin-table-wrapper"><table><thead><tr><th>Code</th><th>Description</th></tr><tr><td><pre><code>const test = "hello";</code></pre></td><td>abcd</td></tr><tr><td><pre><code>const test = "hello";</code></pre></td><td>abcd</td></tr></thead></table></div>
|
@ -1 +1 @@
|
||||
<table class="jop-noMdConv"><thead class="jop-noMdConv"><tr class="jop-noMdConv"><th class="jop-noMdConv">Code</th><th class="jop-noMdConv">Description</th></tr><tr class="jop-noMdConv"><td class="jop-noMdConv"><pre class="jop-noMdConv"><code class="">const test = "hello";</code></pre></td><td class="jop-noMdConv">abcda</td></tr><tr class="jop-noMdConv"><td class="jop-noMdConv"><pre class="jop-noMdConv"><code class="">const test = "hello";</code></pre></td><td class="jop-noMdConv">abcd</td></tr></thead></table>
|
||||
<div class="joplin-table-wrapper"><table class="jop-noMdConv"><thead class="jop-noMdConv"><tr class="jop-noMdConv"><th class="jop-noMdConv">Code</th><th class="jop-noMdConv">Description</th></tr><tr class="jop-noMdConv"><td class="jop-noMdConv"><pre class="jop-noMdConv"><code class="">const test = "hello";</code></pre></td><td class="jop-noMdConv">abcda</td></tr><tr class="jop-noMdConv"><td class="jop-noMdConv"><pre class="jop-noMdConv"><code class="">const test = "hello";</code></pre></td><td class="jop-noMdConv">abcd</td></tr></thead></table></div>
|
@ -1,10 +1,10 @@
|
||||
<table class="jop-noMdConv"><thead class="jop-noMdConv"><tr class="jop-noMdConv"><th class="jop-noMdConv">Code</th><th class="jop-noMdConv">Description</th></tr><tr class="jop-noMdConv"><td class="jop-noMdConv"><pre class="jop-noMdConv"><code class="">const test = "hello";
|
||||
<!-- -->
|
||||
<div class="joplin-table-wrapper"><table class="jop-noMdConv"><thead class="jop-noMdConv"><tr class="jop-noMdConv"><th class="jop-noMdConv">Code</th><th class="jop-noMdConv">Description</th></tr><tr class="jop-noMdConv"><td class="jop-noMdConv"><pre class="jop-noMdConv"><code class="">const test = "hello";
|
||||
|
||||
// Another line
|
||||
console.log('Test...');
|
||||
<!-- -->
|
||||
|
||||
// Blank lines
|
||||
<!-- -->
|
||||
<!-- -->
|
||||
<!-- -->
|
||||
// Should not break things.</code></pre></td><td class="jop-noMdConv">abcda</td></tr><tr class="jop-noMdConv"><td class="jop-noMdConv"><pre class="jop-noMdConv"><code class="">const test = "hello";</code></pre></td><td class="jop-noMdConv">abcd</td></tr></thead></table>
|
||||
|
||||
|
||||
|
||||
// Should not break things.</code></pre></td><td class="jop-noMdConv">abcda</td></tr><tr class="jop-noMdConv"><td class="jop-noMdConv"><pre class="jop-noMdConv"><code class="">const test = "hello";</code></pre></td><td class="jop-noMdConv">abcd</td></tr></thead></table></div>
|
@ -1 +1 @@
|
||||
<table><thead><tr><th>A</th><th>B</th></tr></thead><tbody><tr><td><h1>Testing</h1><p>hello</p></td><td>d</td></tr></tbody></table>
|
||||
<div class="joplin-table-wrapper"><table><thead><tr><th>A</th><th>B</th></tr></thead><tbody><tr><td><h1>Testing</h1><p>hello</p></td><td>d</td></tr></tbody></table></div>
|
@ -1 +1 @@
|
||||
<table><thead><tr><th>A</th><th>B</th></tr></thead><tbody><tr><td>One line<hr>Two line</td><td>d</td></tr></tbody></table>
|
||||
<div class="joplin-table-wrapper"><table><thead><tr><th>A</th><th>B</th></tr></thead><tbody><tr><td>One line<hr>Two line</td><td>d</td></tr></tbody></table></div>
|
@ -1 +1 @@
|
||||
<table border="1" style="border-collapse: collapse; width: 100%;" data-mce-selected="1"><tbody><tr><td style="width: 50.0518%;">Header 1</td><td style="width: 50.0518%;">Header 2</td></tr><tr><td style="width: 50.0518%;"><br></td><td style="width: 50.0518%;"><ul><li>Check 1</li><li>Check 2</li></ul></td></tr></tbody></table>
|
||||
<div class="joplin-table-wrapper"><table border="1" style="border-collapse: collapse; width: 100%;" data-mce-selected="1"><tbody><tr><td style="width: 50.0518%;">Header 1</td><td style="width: 50.0518%;">Header 2</td></tr><tr><td style="width: 50.0518%;"><br></td><td style="width: 50.0518%;"><ul><li>Check 1</li><li>Check 2</li></ul></td></tr></tbody></table></div>
|
@ -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<div class="joplin-table-wrapper">${html}</div>\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;
|
||||
|
Loading…
Reference in New Issue
Block a user