diff --git a/examples/rich-text/state.json b/examples/rich-text/state.json index 8e7372be9..2ce81ca27 100644 --- a/examples/rich-text/state.json +++ b/examples/rich-text/state.json @@ -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", diff --git a/lib/components/content.js b/lib/components/content.js index eb8f41ece..c8e26c569 100644 --- a/lib/components/content.js +++ b/lib/components/content.js @@ -700,6 +700,7 @@ class Content extends React.Component { renderNode = (node) => { const { editor, renderDecorations, renderMark, renderNode, state } = this.props + return ( 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 } diff --git a/lib/models/block.js b/lib/models/block.js index 36398ac47..fb8142926 100644 --- a/lib/models/block.js +++ b/lib/models/block.js @@ -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) + } + } /** diff --git a/lib/utils/bidi.js b/lib/utils/bidi.js new file mode 100644 index 000000000..d6e150cf2 --- /dev/null +++ b/lib/utils/bidi.js @@ -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 diff --git a/package.json b/package.json index 3a65ec107..28bdd1acc 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/test/rendering/fixtures/text-direction/index.js b/test/rendering/fixtures/text-direction/index.js new file mode 100644 index 000000000..dbf0139ef --- /dev/null +++ b/test/rendering/fixtures/text-direction/index.js @@ -0,0 +1,4 @@ + +/** + * Nothing, pure defaults. + */ diff --git a/test/rendering/fixtures/text-direction/input.yaml b/test/rendering/fixtures/text-direction/input.yaml new file mode 100644 index 000000000..d513f7338 --- /dev/null +++ b/test/rendering/fixtures/text-direction/input.yaml @@ -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" diff --git a/test/rendering/fixtures/text-direction/output.html b/test/rendering/fixtures/text-direction/output.html new file mode 100644 index 000000000..a325e6a3e --- /dev/null +++ b/test/rendering/fixtures/text-direction/output.html @@ -0,0 +1,23 @@ + +
+
+ + Hello World + +
+
+ + مرحبا بالعالم + +
+
+ + שלום עולם + +
+
+ + Ending with ltr + +
+
diff --git a/test/rendering/index.js b/test/rendering/index.js index ee396c36d..ab9ffd57c 100644 --- a/test/rendering/index.js +++ b/test/rendering/index.js @@ -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'))