1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-12 10:14:02 +02:00

Add RTL support (#204)

* Add property textAlignment for the whole editor

* textAlignment should be set on Content

* Add basic for directionMap in State

* Add RTL to example

* Use setDocument for updating direction map when inserting blocks

* Remove debug log

* Only add 'dir' to node when is not default value

* Prevent tests from failing because of .DS_Store on OSX

* Add tests for rtl rendering

* Fix rendering tests

* Fix test for rendering "text-direction"

* Remove textAlignment prop on editor

* Don't use a directionMap but directly a "textDir" on nodes

* Remove .setDocument from State
This commit is contained in:
Samy Pessé
2016-07-29 20:25:07 +02:00
committed by Ian Storm Taylor
parent 4d58c0035c
commit 845e284ee4
10 changed files with 122 additions and 0 deletions

View File

@@ -81,6 +81,26 @@
} }
] ]
}, },
{
"kind": "block",
"type": "paragraph",
"nodes": [
{
"kind": "text",
"text": "It support both LTR (English) and RTL (Arabic, Hebrew) edition:"
}
]
},
{
"kind": "block",
"type": "paragraph",
"nodes": [
{
"kind": "text",
"text": "مرحبا بالعالم"
}
]
},
{ {
"kind": "block", "kind": "block",
"type": "paragraph", "type": "paragraph",

View File

@@ -700,6 +700,7 @@ class Content extends React.Component {
renderNode = (node) => { renderNode = (node) => {
const { editor, renderDecorations, renderMark, renderNode, state } = this.props const { editor, renderDecorations, renderMark, renderNode, state } = this.props
return ( return (
<Node <Node
key={node.key} key={node.key}

View File

@@ -93,9 +93,13 @@ class Node extends React.Component {
.map(child => this.renderNode(child)) .map(child => this.renderNode(child))
.toArray() .toArray()
// Calcul direction of text
const dir = node.textDir
// Attributes that the developer has to mix into the element in their custom // Attributes that the developer has to mix into the element in their custom
// renderer component. // renderer component.
const attributes = { const attributes = {
'dir': dir !== 'ltr' ? dir : undefined,
'data-key': node.key, 'data-key': node.key,
'onDragStart': this.onDragStart 'onDragStart': this.onDragStart
} }

View File

@@ -15,6 +15,7 @@ import Inline from './inline'
import Node from './node' import Node from './node'
import Text from './text' import Text from './text'
import uid from '../utils/uid' import uid from '../utils/uid'
import bidi from '../utils/bidi'
import Immutable, { Map, List, Record } from 'immutable' import Immutable, { Map, List, Record } from 'immutable'
/** /**
@@ -110,6 +111,16 @@ class Block extends new Record(DEFAULTS) {
.join('') .join('')
} }
/**
* Get the text direction.
*
* @return {String} dir
*/
get textDir() {
return bidi.getDirection(this.text)
}
} }
/** /**

30
lib/utils/bidi.js Normal file
View File

@@ -0,0 +1,30 @@
import direction from 'direction'
import { Map } from 'immutable'
let cache = {}
/**
* Get direction of a text
* @param {String} text
* @return {String} dir?
*/
function getDirection(text) {
if (cache[text]) {
return cache[text]
}
let dir = direction(text)
if (dir === 'neutral') {
return
}
return dir
}
const bidi = {
getDirection
}
export default bidi

View File

@@ -8,6 +8,7 @@
"dependencies": { "dependencies": {
"cheerio": "^0.20.0", "cheerio": "^0.20.0",
"detect-browser": "^1.3.3", "detect-browser": "^1.3.3",
"direction": "^0.1.5",
"esrever": "^0.2.0", "esrever": "^0.2.0",
"immutable": "^3.8.1", "immutable": "^3.8.1",
"is-empty": "^1.0.0", "is-empty": "^1.0.0",

View File

@@ -0,0 +1,4 @@
/**
* Nothing, pure defaults.
*/

View File

@@ -0,0 +1,26 @@
nodes:
- kind: block
type: default
nodes:
- kind: text
ranges:
- text: "Hello World"
- kind: block
type: default
nodes:
- kind: text
ranges:
- text: "مرحبا بالعالم"
- kind: block
type: default
nodes:
- kind: text
ranges:
- text: "שלום עולם"
- kind: block
type: default
nodes:
- kind: text
ranges:
- text: "Ending with ltr"

View File

@@ -0,0 +1,23 @@
<div contenteditable="true">
<div style="position:relative;">
<span>
<span>Hello World</span>
</span>
</div>
<div dir="rtl" style="position:relative;">
<span>
<span>مرحبا بالعالم</span>
</span>
</div>
<div dir="rtl" style="position:relative;">
<span>
<span>שלום עולם</span>
</span>
</div>
<div style="position:relative;">
<span>
<span>Ending with ltr</span>
</span>
</div>
</div>

View File

@@ -16,6 +16,8 @@ describe('rendering', () => {
const tests = fs.readdirSync(resolve(__dirname, './fixtures')) const tests = fs.readdirSync(resolve(__dirname, './fixtures'))
for (const test of tests) { for (const test of tests) {
if (test[0] === '.') continue
it(test, () => { it(test, () => {
const dir = resolve(__dirname, './fixtures', test) const dir = resolve(__dirname, './fixtures', test)
const input = readMetadata.sync(resolve(dir, 'input.yaml')) const input = readMetadata.sync(resolve(dir, 'input.yaml'))