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:
committed by
Ian Storm Taylor
parent
4d58c0035c
commit
845e284ee4
@@ -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",
|
||||
"type": "paragraph",
|
||||
|
@@ -700,6 +700,7 @@ class Content extends React.Component {
|
||||
|
||||
renderNode = (node) => {
|
||||
const { editor, renderDecorations, renderMark, renderNode, state } = this.props
|
||||
|
||||
return (
|
||||
<Node
|
||||
key={node.key}
|
||||
|
@@ -93,9 +93,13 @@ class Node extends React.Component {
|
||||
.map(child => this.renderNode(child))
|
||||
.toArray()
|
||||
|
||||
// Calcul direction of text
|
||||
const dir = node.textDir
|
||||
|
||||
// Attributes that the developer has to mix into the element in their custom
|
||||
// renderer component.
|
||||
const attributes = {
|
||||
'dir': dir !== 'ltr' ? dir : undefined,
|
||||
'data-key': node.key,
|
||||
'onDragStart': this.onDragStart
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@ import Inline from './inline'
|
||||
import Node from './node'
|
||||
import Text from './text'
|
||||
import uid from '../utils/uid'
|
||||
import bidi from '../utils/bidi'
|
||||
import Immutable, { Map, List, Record } from 'immutable'
|
||||
|
||||
/**
|
||||
@@ -110,6 +111,16 @@ class Block extends new Record(DEFAULTS) {
|
||||
.join('')
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text direction.
|
||||
*
|
||||
* @return {String} dir
|
||||
*/
|
||||
|
||||
get textDir() {
|
||||
return bidi.getDirection(this.text)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
30
lib/utils/bidi.js
Normal file
30
lib/utils/bidi.js
Normal 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
|
@@ -8,6 +8,7 @@
|
||||
"dependencies": {
|
||||
"cheerio": "^0.20.0",
|
||||
"detect-browser": "^1.3.3",
|
||||
"direction": "^0.1.5",
|
||||
"esrever": "^0.2.0",
|
||||
"immutable": "^3.8.1",
|
||||
"is-empty": "^1.0.0",
|
||||
|
4
test/rendering/fixtures/text-direction/index.js
Normal file
4
test/rendering/fixtures/text-direction/index.js
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
/**
|
||||
* Nothing, pure defaults.
|
||||
*/
|
26
test/rendering/fixtures/text-direction/input.yaml
Normal file
26
test/rendering/fixtures/text-direction/input.yaml
Normal 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"
|
23
test/rendering/fixtures/text-direction/output.html
Normal file
23
test/rendering/fixtures/text-direction/output.html
Normal 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>
|
@@ -16,6 +16,8 @@ describe('rendering', () => {
|
||||
const tests = fs.readdirSync(resolve(__dirname, './fixtures'))
|
||||
|
||||
for (const test of tests) {
|
||||
if (test[0] === '.') continue
|
||||
|
||||
it(test, () => {
|
||||
const dir = resolve(__dirname, './fixtures', test)
|
||||
const input = readMetadata.sync(resolve(dir, 'input.yaml'))
|
||||
|
Reference in New Issue
Block a user