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",
|
"kind": "block",
|
||||||
"type": "paragraph",
|
"type": "paragraph",
|
||||||
|
@@ -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}
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
@@ -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
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": {
|
"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",
|
||||||
|
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'))
|
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'))
|
||||||
|
Reference in New Issue
Block a user