Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/text.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMax <max@nextcloud.com>2022-03-14 15:57:34 +0300
committerMax <max@nextcloud.com>2022-03-31 15:29:20 +0300
commit759f8cbc0cc4ad9c28382f384b7c84963aa9d89a (patch)
treeea3ec3af29f0dcae10d91e8e9eccca78cf8b2c2e /src
parenta62606ce6af09fb88fc18866864dc73035f108f3 (diff)
fix: handling of various table formats
Signed-off-by: Max <max@nextcloud.com>
Diffstat (limited to 'src')
-rw-r--r--src/nodes/Table.js37
-rw-r--r--src/nodes/TableBody.js8
-rw-r--r--src/nodes/TableCell.js8
-rw-r--r--src/nodes/TableHead.js6
-rw-r--r--src/nodes/TableHeader.js12
-rw-r--r--src/nodes/TableRow.js5
-rw-r--r--src/tests/fixtures/tables/handbook-caption-tbody.html34
-rw-r--r--src/tests/fixtures/tables/handbook-empty-thead-tbody.html34
-rw-r--r--src/tests/fixtures/tables/handbook-multiple-tbody.html36
-rw-r--r--src/tests/fixtures/tables/handbook-thead-tbody.html34
-rw-r--r--src/tests/fixtures/tables/handbook-with-caption.html33
-rw-r--r--src/tests/fixtures/tables/handbook.html32
-rw-r--r--src/tests/fixtures/tables/handbook.out.html34
-rw-r--r--src/tests/tables.spec.js16
14 files changed, 313 insertions, 16 deletions
diff --git a/src/nodes/Table.js b/src/nodes/Table.js
index 02441aacf..a4d93ed85 100644
--- a/src/nodes/Table.js
+++ b/src/nodes/Table.js
@@ -1,8 +1,41 @@
import { Table } from '@tiptap/extension-table'
-import { mergeAttributes } from '@tiptap/core'
+import { Node, mergeAttributes } from '@tiptap/core'
+
+/*
+ * Markdown tables do not include captions.
+ * We still need to parse them though
+ * because otherwise tiptap will try to insert their text content
+ * and put it in the top row of the table.
+ */
+const tableCaption = Node.create({
+ name: 'tableCaption',
+ content: 'inline*',
+ addAttributes() {
+ return {}
+ },
+
+ renderHTML() {
+ return ['caption']
+ },
+
+ toMarkdown(state, node) {
+ },
+
+ parseHTML() {
+ return [
+ { tag: 'table caption', priority: 90 },
+ ]
+ },
+})
export default Table.extend({
- content: 'tableHead tableBody',
+ content: 'tableCaption? tableHead tableBody',
+
+ addExtensions() {
+ return [
+ tableCaption,
+ ]
+ },
renderHTML({ HTMLAttributes }) {
return ['table', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0]
diff --git a/src/nodes/TableBody.js b/src/nodes/TableBody.js
index bf0e9b616..5a2673424 100644
--- a/src/nodes/TableBody.js
+++ b/src/nodes/TableBody.js
@@ -2,7 +2,7 @@ import { Node, mergeAttributes } from '@tiptap/core'
export default Node.create({
name: 'tableBody',
- content: 'tableRow',
+ content: 'tableRow*',
addOptions() {
return {
@@ -10,12 +10,6 @@ export default Node.create({
}
},
- parseHTML() {
- return [
- { tag: 'tbody' },
- ]
- },
-
renderHTML({ HTMLAttributes }) {
return ['tbody', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0]
},
diff --git a/src/nodes/TableCell.js b/src/nodes/TableCell.js
index b3829640f..82fa666b3 100644
--- a/src/nodes/TableCell.js
+++ b/src/nodes/TableCell.js
@@ -13,4 +13,12 @@ export default TableCell.extend({
state.write(' |')
},
+ parseHTML() {
+ return [
+ { tag: 'td' },
+ { tag: 'th' },
+ { tag: 'table thead ~ tbody th', priority: 70 },
+ { tag: 'table thead ~ tbody td', priority: 70 },
+ ]
+ },
})
diff --git a/src/nodes/TableHead.js b/src/nodes/TableHead.js
index 9fe6c94da..0cd7af788 100644
--- a/src/nodes/TableHead.js
+++ b/src/nodes/TableHead.js
@@ -39,12 +39,8 @@ export default Node.create({
},
addExtensions() {
- return [tableHeadRow]
- },
-
- parseHTML() {
return [
- { tag: 'thead' },
+ tableHeadRow,
]
},
diff --git a/src/nodes/TableHeader.js b/src/nodes/TableHeader.js
index 936ab26f2..b08f5c609 100644
--- a/src/nodes/TableHeader.js
+++ b/src/nodes/TableHeader.js
@@ -13,4 +13,16 @@ export default TableHeader.extend({
state.write(' |')
},
+ parseHTML() {
+ return [
+ { tag: 'table thead:empty ~ tbody :first-child th', priority: 80 },
+ { tag: 'table thead:empty ~ tbody :first-child td', priority: 80 },
+ { tag: 'table thead :first-child th', priority: 60 },
+ { tag: 'table thead :first-child td', priority: 60 },
+ { tag: 'table tbody :first-child th', priority: 60 },
+ { tag: 'table tbody :first-child td', priority: 60 },
+ { tag: 'table > :first-child > th', priority: 60 },
+ { tag: 'table > :first-child > td', priority: 60 },
+ ]
+ },
})
diff --git a/src/nodes/TableRow.js b/src/nodes/TableRow.js
index 915cae27b..3beb7cf06 100644
--- a/src/nodes/TableRow.js
+++ b/src/nodes/TableRow.js
@@ -11,4 +11,9 @@ export default TableRow.extend({
state.renderInline(node)
},
+ parseHTML() {
+ return [
+ { tag: 'tr', priority: 80 },
+ ]
+ },
})
diff --git a/src/tests/fixtures/tables/handbook-caption-tbody.html b/src/tests/fixtures/tables/handbook-caption-tbody.html
new file mode 100644
index 000000000..7dc9d82ea
--- /dev/null
+++ b/src/tests/fixtures/tables/handbook-caption-tbody.html
@@ -0,0 +1,34 @@
+<table id="bkmrk-section-name" style="border-collapse: collapse; width: 100%; height: 150px;" border="1">
+<caption>Testing tables
+</caption>
+<tbody>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Heading 0</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 1</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 2</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 3</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 4</strong></td>
+</tr>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Letter</strong></td>
+<td style="width: 20%; height: 29px;">a</td>
+<td style="width: 20%; height: 29px;">b</td>
+<td style="width: 20%; height: 29px;">c</td>
+<td style="width: 20%; height: 29px;">d</td>
+</tr>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Number</strong></td>
+<td style="width: 20%; height: 29px;">1</td>
+<td style="width: 20%; height: 29px;">2</td>
+<td style="width: 20%; height: 29px;">3</td>
+<td style="width: 20%; height: 29px;">4</td>
+</tr>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Square</strong></td>
+<td style="width: 20%; height: 29px;">1</td>
+<td style="width: 20%; height: 29px;">4</td>
+<td style="width: 20%; height: 29px;">9</td>
+<td style="width: 20%; height: 29px;">16</td>
+</tr>
+</tbody>
+</table>
diff --git a/src/tests/fixtures/tables/handbook-empty-thead-tbody.html b/src/tests/fixtures/tables/handbook-empty-thead-tbody.html
new file mode 100644
index 000000000..9ea8376c7
--- /dev/null
+++ b/src/tests/fixtures/tables/handbook-empty-thead-tbody.html
@@ -0,0 +1,34 @@
+<table id="bkmrk-section-name" style="border-collapse: collapse; width: 100%; height: 150px;" border="1">
+<thead>
+</thead>
+<tbody>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Heading 0</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 1</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 2</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 3</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 4</strong></td>
+</tr>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Letter</strong></td>
+<td style="width: 20%; height: 29px;">a</td>
+<td style="width: 20%; height: 29px;">b</td>
+<td style="width: 20%; height: 29px;">c</td>
+<td style="width: 20%; height: 29px;">d</td>
+</tr>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Number</strong></td>
+<td style="width: 20%; height: 29px;">1</td>
+<td style="width: 20%; height: 29px;">2</td>
+<td style="width: 20%; height: 29px;">3</td>
+<td style="width: 20%; height: 29px;">4</td>
+</tr>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Square</strong></td>
+<td style="width: 20%; height: 29px;">1</td>
+<td style="width: 20%; height: 29px;">4</td>
+<td style="width: 20%; height: 29px;">9</td>
+<td style="width: 20%; height: 29px;">16</td>
+</tr>
+</tbody>
+</table>
diff --git a/src/tests/fixtures/tables/handbook-multiple-tbody.html b/src/tests/fixtures/tables/handbook-multiple-tbody.html
new file mode 100644
index 000000000..02eb3ed07
--- /dev/null
+++ b/src/tests/fixtures/tables/handbook-multiple-tbody.html
@@ -0,0 +1,36 @@
+<table id="bkmrk-section-name" style="border-collapse: collapse; width: 100%; height: 150px;" border="1">
+<tbody>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Heading 0</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 1</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 2</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 3</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 4</strong></td>
+</tr>
+</tbody>
+<tbody>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Letter</strong></td>
+<td style="width: 20%; height: 29px;">a</td>
+<td style="width: 20%; height: 29px;">b</td>
+<td style="width: 20%; height: 29px;">c</td>
+<td style="width: 20%; height: 29px;">d</td>
+</tr>
+</tbody>
+<tbody>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Number</strong></td>
+<td style="width: 20%; height: 29px;">1</td>
+<td style="width: 20%; height: 29px;">2</td>
+<td style="width: 20%; height: 29px;">3</td>
+<td style="width: 20%; height: 29px;">4</td>
+</tr>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Square</strong></td>
+<td style="width: 20%; height: 29px;">1</td>
+<td style="width: 20%; height: 29px;">4</td>
+<td style="width: 20%; height: 29px;">9</td>
+<td style="width: 20%; height: 29px;">16</td>
+</tr>
+</tbody>
+</table>
diff --git a/src/tests/fixtures/tables/handbook-thead-tbody.html b/src/tests/fixtures/tables/handbook-thead-tbody.html
new file mode 100644
index 000000000..63b4f3157
--- /dev/null
+++ b/src/tests/fixtures/tables/handbook-thead-tbody.html
@@ -0,0 +1,34 @@
+<table id="bkmrk-section-name" style="border-collapse: collapse; width: 100%; height: 150px;" border="1">
+<thead>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Heading 0</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 1</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 2</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 3</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 4</strong></td>
+</tr>
+</thead>
+<tbody>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Letter</strong></td>
+<td style="width: 20%; height: 29px;">a</td>
+<td style="width: 20%; height: 29px;">b</td>
+<td style="width: 20%; height: 29px;">c</td>
+<td style="width: 20%; height: 29px;">d</td>
+</tr>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Number</strong></td>
+<td style="width: 20%; height: 29px;">1</td>
+<td style="width: 20%; height: 29px;">2</td>
+<td style="width: 20%; height: 29px;">3</td>
+<td style="width: 20%; height: 29px;">4</td>
+</tr>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Square</strong></td>
+<td style="width: 20%; height: 29px;">1</td>
+<td style="width: 20%; height: 29px;">4</td>
+<td style="width: 20%; height: 29px;">9</td>
+<td style="width: 20%; height: 29px;">16</td>
+</tr>
+</tbody>
+</table>
diff --git a/src/tests/fixtures/tables/handbook-with-caption.html b/src/tests/fixtures/tables/handbook-with-caption.html
new file mode 100644
index 000000000..f288b4b19
--- /dev/null
+++ b/src/tests/fixtures/tables/handbook-with-caption.html
@@ -0,0 +1,33 @@
+<table id="bkmrk-section-name" style="border-collapse: collapse; width: 100%; height: 150px;" border="1">
+<caption>test</caption>
+<tbody>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Heading 0</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 1</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 2</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 3</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 4</strong></td>
+</tr>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Letter</strong></td>
+<td style="width: 20%; height: 29px;">a</td>
+<td style="width: 20%; height: 29px;">b</td>
+<td style="width: 20%; height: 29px;">c</td>
+<td style="width: 20%; height: 29px;">d</td>
+</tr>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Number</strong></td>
+<td style="width: 20%; height: 29px;">1</td>
+<td style="width: 20%; height: 29px;">2</td>
+<td style="width: 20%; height: 29px;">3</td>
+<td style="width: 20%; height: 29px;">4</td>
+</tr>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Square</strong></td>
+<td style="width: 20%; height: 29px;">1</td>
+<td style="width: 20%; height: 29px;">4</td>
+<td style="width: 20%; height: 29px;">9</td>
+<td style="width: 20%; height: 29px;">16</td>
+</tr>
+</tbody>
+</table>
diff --git a/src/tests/fixtures/tables/handbook.html b/src/tests/fixtures/tables/handbook.html
new file mode 100644
index 000000000..f0be817ae
--- /dev/null
+++ b/src/tests/fixtures/tables/handbook.html
@@ -0,0 +1,32 @@
+<table id="bkmrk-section-name" style="border-collapse: collapse; width: 100%; height: 150px;" border="1">
+<tbody>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Heading 0</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 1</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 2</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 3</strong></td>
+<td style="width: 20%; height: 29px;"><strong>Heading 4</strong></td>
+</tr>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Letter</strong></td>
+<td style="width: 20%; height: 29px;">a</td>
+<td style="width: 20%; height: 29px;">b</td>
+<td style="width: 20%; height: 29px;">c</td>
+<td style="width: 20%; height: 29px;">d</td>
+</tr>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Number</strong></td>
+<td style="width: 20%; height: 29px;">1</td>
+<td style="width: 20%; height: 29px;">2</td>
+<td style="width: 20%; height: 29px;">3</td>
+<td style="width: 20%; height: 29px;">4</td>
+</tr>
+<tr style="height: 29px;">
+<td style="width: 20%; height: 29px;"><strong>Square</strong></td>
+<td style="width: 20%; height: 29px;">1</td>
+<td style="width: 20%; height: 29px;">4</td>
+<td style="width: 20%; height: 29px;">9</td>
+<td style="width: 20%; height: 29px;">16</td>
+</tr>
+</tbody>
+</table>
diff --git a/src/tests/fixtures/tables/handbook.out.html b/src/tests/fixtures/tables/handbook.out.html
new file mode 100644
index 000000000..ad2d26a4a
--- /dev/null
+++ b/src/tests/fixtures/tables/handbook.out.html
@@ -0,0 +1,34 @@
+<table>
+<thead>
+<tr>
+<th><strong>Heading 0</strong></th>
+<th><strong>Heading 1</strong></th>
+<th><strong>Heading 2</strong></th>
+<th><strong>Heading 3</strong></th>
+<th><strong>Heading 4</strong></th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td><strong>Letter</strong></td>
+<td>a</td>
+<td>b</td>
+<td>c</td>
+<td>d</td>
+</tr>
+<tr>
+<td><strong>Number</strong></td>
+<td>1</td>
+<td>2</td>
+<td>3</td>
+<td>4</td>
+</tr>
+<tr>
+<td><strong>Square</strong></td>
+<td>1</td>
+<td>4</td>
+<td>9</td>
+<td>16</td>
+</tr>
+</tbody>
+</table>
diff --git a/src/tests/tables.spec.js b/src/tests/tables.spec.js
index 7a347eb9e..7e0bdce33 100644
--- a/src/tests/tables.spec.js
+++ b/src/tests/tables.spec.js
@@ -4,12 +4,14 @@ import markdownit from './../markdownit'
import input from './fixtures/table.md'
import output from './fixtures/table.html'
import otherStructure from './fixtures/tableWithOtherStructure.html'
+import handbook from './fixtures/tables/handbook.html'
+import handbookOut from './fixtures/tables/handbook.out.html'
describe('Table', () => {
test('load into editor', () => {
const tiptap = editorWithContent(markdownit.render(input))
- expect(tiptap.getHTML().replaceAll('><', ">\n<")).toBe(output.replace(/\n$/, ''))
+ expect(formatHTML(tiptap.getHTML())).toBe(formatHTML(output))
})
test('serialize from editor', () => {
@@ -22,7 +24,14 @@ describe('Table', () => {
const tiptap = editorWithContent(
otherStructure.replace(/\n\s*/g,'')
)
- expect(tiptap.getHTML().replaceAll('><', ">\n<")).toBe(output.replace(/\n$/, ''))
+ expect(formatHTML(tiptap.getHTML())).toBe(formatHTML(output))
+ })
+
+ test('handle html table from handbook', () => {
+ const tiptap = editorWithContent(
+ handbook.replace(/\n\s*/g,'')
+ )
+ expect(formatHTML(tiptap.getHTML())).toBe(formatHTML(handbookOut))
})
})
@@ -34,3 +43,6 @@ function editorWithContent(content) {
})
}
+function formatHTML(html) {
+ return html.replaceAll('><', ">\n<").replace(/\n$/, '')
+}