Skip to content

Commit 2e14db6

Browse files
authored
Merge pull request #7515 from nextcloud/backport/7513/stable31
[stable31] Further TextDirection improvements
2 parents 289e7d6 + 0c856f9 commit 2e14db6

File tree

10 files changed

+89
-39
lines changed

10 files changed

+89
-39
lines changed

src/extensions/Keymap.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ const Keymap = Extension.create({
2020
emit('text:keyboard:outline')
2121
return true
2222
},
23+
/**
24+
* <Backspace>
25+
* Allows to undo input rules after they got automatically applied
26+
*/
27+
Backspace: () => this.editor.commands.undoInputRule(),
2328
}
2429
},
2530

src/extensions/RichText.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,15 @@ export default Extension.create({
116116
TrailingNode,
117117
TextDirection.configure({
118118
types: [
119+
'blockquote',
120+
'callout',
121+
'detailsSummary',
119122
'heading',
120-
'paragraph',
121123
'listItem',
124+
'paragraph',
125+
'tableCell',
126+
'tableHeader',
122127
'taskItem',
123-
'blockquote',
124128
],
125129
}),
126130
]

src/extensions/TextDirection.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,13 @@
33
* SPDX-License-Identifier: MIT
44
*/
55

6-
import { Extension } from '@tiptap/core'
7-
import { Plugin, PluginKey } from '@tiptap/pm/state'
6+
import {
7+
Extension,
8+
combineTransactionSteps,
9+
findChildrenInRange,
10+
getChangedRanges,
11+
} from '@tiptap/core'
12+
import { Plugin, PluginKey, Transaction } from '@tiptap/pm/state'
813

914
const RTL = '\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC'
1015
const LTR = 'A-Za-z\u00C0-\u00D6\u00D8-\u00F6'
@@ -53,11 +58,21 @@ function TextDirectionPlugin({ types }: { types: string[] }) {
5358
}
5459

5560
let modified = false
56-
const tr = newState.tr
61+
const { tr } = newState
62+
const transform = combineTransactionSteps(
63+
oldState.doc,
64+
transactions as Transaction[],
65+
)
66+
const changes = getChangedRanges(transform)
67+
5768
tr.setMeta('addToHistory', false)
5869

59-
newState.doc.descendants((node, pos) => {
60-
if (types.includes(node.type.name)) {
70+
changes.forEach(({ newRange }) => {
71+
const nodes = findChildrenInRange(newState.doc, newRange, (node) =>
72+
types.includes(node.type.name),
73+
)
74+
75+
nodes.forEach(({ node, pos }) => {
6176
if (node.attrs.dir !== null && node.textContent.length > 0) {
6277
return
6378
}
@@ -73,7 +88,7 @@ function TextDirectionPlugin({ types }: { types: string[] }) {
7388
tr.addStoredMark(mark)
7489
}
7590
modified = true
76-
}
91+
})
7792
})
7893

7994
return modified ? tr : null

src/nodes/Callout.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<NodeViewWrapper data-text-el="callout"
77
class="callout"
88
:class="`callout--${type}`"
9+
:dir="dir"
910
as="div">
1011
<component :is="icon" class="callout__icon" />
1112
<NodeViewContent class="callout__content" />
@@ -41,7 +42,10 @@ export default {
4142
return ICONS_MAP[this.type] || Info
4243
},
4344
type() {
44-
return this.node?.attrs?.type || 'info'
45+
return this.node.attrs.type || 'info'
46+
},
47+
dir() {
48+
return this.node.attrs.dir || ''
4549
},
4650
},
4751
}

src/nodes/DetailsView.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ div.details {
8787
8888
.details-container {
8989
width: 100%;
90-
margin-right: 12px;
90+
margin-inline-end: 12px;
9191
}
9292
9393
:deep(summary) {

src/nodes/Table/TableCellView.vue

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
-->
55

66
<template>
7-
<NodeViewWrapper data-text-el="table-cell" as="td" :style="textAlign">
7+
<NodeViewWrapper data-text-el="table-cell"
8+
as="td"
9+
:dir="dir"
10+
:style="textAlign">
811
<div class="container">
912
<NodeViewContent class="content" />
1013
<NcActions v-if="isEditable"
@@ -74,6 +77,9 @@ export default {
7477
textAlign() {
7578
return { 'text-align': this.node.attrs.textAlign }
7679
},
80+
dir() {
81+
return this.node.attrs.dir || ''
82+
},
7783
},
7884
beforeMount() {
7985
this.isEditable = this.editor.isEditable

src/nodes/Table/TableHeaderView.vue

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
-->
55

66
<template>
7-
<NodeViewWrapper data-text-el="table-header" as="th" :style="textAlign">
7+
<NodeViewWrapper data-text-el="table-header"
8+
as="th"
9+
:dir="dir"
10+
:style="textAlign">
811
<div>
912
<NodeViewContent class="content" />
1013
<NcActions v-if="isEditable"
@@ -124,6 +127,9 @@ export default {
124127
textAlign() {
125128
return { 'text-align': this.node.attrs.textAlign }
126129
},
130+
dir() {
131+
return this.node.attrs.dir || ''
132+
},
127133
},
128134
beforeMount() {
129135
this.isEditable = this.editor.isEditable

src/tests/fixtures/tables/handbook/handbook.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@
1212
<td style="width: 20%; height: 29px;">a</td>
1313
<td style="width: 20%; height: 29px;">b</td>
1414
<td style="width: 20%; height: 29px;">c</td>
15-
<td style="width: 20%; height: 29px;">d</td>
15+
<td style="width: 20%; height: 29px;">ب</td>
1616
</tr>
1717
<tr style="height: 29px;">
1818
<td style="width: 20%; height: 29px;"><strong>Number</strong></td>
1919
<td style="width: 20%; height: 29px;">1</td>
20-
<td style="width: 20%; height: 29px;">2</td>
20+
<td style="width: 20%; height: 29px;">٢</td>
2121
<td style="width: 20%; height: 29px;">3</td>
2222
<td style="width: 20%; height: 29px;">4</td>
2323
</tr>

src/tests/fixtures/tables/handbook/handbook.out.html

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
<div class="table-wrapper" style="overflow-x: auto;">
22
<table>
33
<tr>
4-
<th><strong>Heading 0</strong></th>
5-
<th><strong>Heading 1</strong></th>
6-
<th><strong>Heading 2</strong></th>
7-
<th><strong>Heading 3</strong></th>
8-
<th><strong>Heading 4</strong></th>
4+
<th dir="ltr"><strong>Heading 0</strong></th>
5+
<th dir="ltr"><strong>Heading 1</strong></th>
6+
<th dir="ltr"><strong>Heading 2</strong></th>
7+
<th dir="ltr"><strong>Heading 3</strong></th>
8+
<th dir="ltr"><strong>Heading 4</strong></th>
99
</tr>
1010
<tr>
11-
<td><strong>Letter</strong></td>
12-
<td>a</td>
13-
<td>b</td>
14-
<td>c</td>
15-
<td>d</td>
11+
<td dir="ltr"><strong>Letter</strong></td>
12+
<td dir="ltr">a</td>
13+
<td dir="ltr">b</td>
14+
<td dir="ltr">c</td>
15+
<td dir="rtl">ب</td>
1616
</tr>
1717
<tr>
18-
<td><strong>Number</strong></td>
18+
<td dir="ltr"><strong>Number</strong></td>
1919
<td>1</td>
20-
<td>2</td>
20+
<td dir="rtl">٢</td>
2121
<td>3</td>
2222
<td>4</td>
2323
</tr>
2424
<tr>
25-
<td><strong>Square</strong></td>
25+
<td dir="ltr"><strong>Square</strong></td>
2626
<td>1</td>
2727
<td>4</td>
2828
<td>9</td>

src/tests/nodes/Table.spec.js

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,19 @@ describe('Table', () => {
3131
expectDocument(tiptap.state.doc,
3232
table(
3333
thead(
34-
th({ textAlign: 'center' }, 'heading'),
35-
th({ textAlign: 'right' }, 'heading 2'),
36-
th('heading 3'),
34+
th({ dir: 'ltr', textAlign: 'center' }, 'heading'),
35+
th({ dir: 'ltr', textAlign: 'right' }, 'heading 2'),
36+
th({ dir: 'ltr' }, 'heading 3'),
3737
),
3838
tr(
39-
td({ textAlign: 'center' }, 'center'),
40-
td({ textAlign: 'right' }, 'right'),
41-
td('left cell ', br({ syntax: 'html' }), 'with line break'),
39+
td({ dir: 'ltr', textAlign: 'center' }, 'center'),
40+
td({ dir: 'ltr', textAlign: 'right' }, 'right'),
41+
td(
42+
{ dir: 'ltr' },
43+
'left cell ',
44+
br({ syntax: 'html' }),
45+
'with line break',
46+
),
4247
),
4348
),
4449
)
@@ -50,14 +55,19 @@ describe('Table', () => {
5055
expectDocument(tiptap.state.doc,
5156
table(
5257
thead(
53-
th({ textAlign: 'center' }, 'heading'),
54-
th({ textAlign: 'right' }, 'heading 2'),
55-
th('heading 3'),
58+
th({ dir: 'ltr', textAlign: 'center' }, 'heading'),
59+
th({ dir: 'ltr', textAlign: 'right' }, 'heading 2'),
60+
th({ dir: 'ltr' }, 'heading 3'),
5661
),
5762
tr(
58-
td({ textAlign: 'center' }, 'center'),
59-
td({ textAlign: 'right' }, 'right'),
60-
td('left cell ', br({ syntax: ' ' }), 'with line break'),
63+
td({ dir: 'ltr', textAlign: 'center' }, 'center'),
64+
td({ dir: 'ltr', textAlign: 'right' }, 'right'),
65+
td(
66+
{ dir: 'ltr' },
67+
'left cell ',
68+
br({ syntax: ' ' }),
69+
'with line break',
70+
),
6171
),
6272
),
6373
)

0 commit comments

Comments
 (0)