Skip to content

Commit 8a609f8

Browse files
authored
Merge pull request #31 from lokiuz/next
0.9.0
2 parents b3bb727 + 768c2f9 commit 8a609f8

File tree

16 files changed

+804
-74
lines changed

16 files changed

+804
-74
lines changed

.babelrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"presets": ["env", "react"],
2+
"presets": ["flow", "env", "react"],
33
"plugins": ["array-includes"]
44
}

.flowconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[ignore]
2+
3+
[include]
4+
5+
[libs]
6+
7+
[lints]
8+
9+
[options]

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 0.9.0
2+
- added support for custom Decorator class and accessing contentState #30
3+
- fixed inline style key collision #29
4+
- fix unicode-aware string splitting #27
5+
16
## 0.8.0
27
- added decorator support (also added example in the README)
38
- exposed a helper to crate a style renderer as an alternative to providing inline style renderers

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ const renderers = {
8484
* Array of decorators,
8585
* Entities receive children and the entity data,
8686
* inspired by https://facebook.github.io/draft-js/docs/advanced-topics-decorators.html
87+
* it's also possible to pass a Decorator class to options instead (or additionaly)
8788
*/
8889
decorators: [
8990
{
@@ -92,6 +93,7 @@ const renderers = {
9293
strategy: linkStrategy,
9394
// component - a callback as with other renderers
9495
// decoratedText a plain string matched by the strategy
96+
// if your decorator depends on draft-js contentState you need to provide convertFromRaw in redraft options
9597
component: ({ children, decoratedText }) => <a href={decoratedText}>{children}/>,
9698
}
9799
],
@@ -184,6 +186,12 @@ const renderers = {
184186
### Joining the output
185187
`joinOutput` - used when rendering to string, joins the output and the children of all the inline and entity renderers, it expects that all renderers return strings, you still have to join the at block level (default: `false`)
186188
189+
### Using custom Decorator class
190+
`Decorator` - use this to pass a custom Decorator class that matches the [DraftDecoratorType](https://github.com/facebook/draft-js/blob/master/src/model/decorators/DraftDecoratorType.js).
191+
192+
### Accessing contentState
193+
`convertFromRaw` - pass the draft-js convertFromRaw to provide the contentState object to both the components in your decorators and the custom Decorator class getDecorations method.
194+
187195
### Creating the ContentBlock
188196
`createContentBlock` - a function that receives a block and returns a draft-js ContentBlock, if not provided when using decorators redraft will create a ContentBlock stub with only some basic ContentBlock functionality
189197

benchmarks/emoji.js

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// A benchmark for different methods/libs for string decoding
2+
// As per #27 Array.from is faulty on react-native but its still here for refference
3+
const now = require('performance-now');
4+
const forEach = require('lodash/forEach');
5+
const min = require('lodash/min');
6+
const range = require('lodash/range');
7+
const runes = require('runes');
8+
const punycode = require('punycode');
9+
const chalk = require('chalk');
10+
11+
// 20 chars
12+
const chars = [
13+
'a',
14+
'b',
15+
'c',
16+
'd',
17+
'e',
18+
'f',
19+
'g',
20+
'h',
21+
'i',
22+
'j',
23+
'k',
24+
'l',
25+
'#',
26+
'1',
27+
'2',
28+
'3',
29+
'?',
30+
'!',
31+
'@',
32+
' ',
33+
];
34+
35+
// 10 emojis
36+
const emojis = [
37+
'💙',
38+
'😺',
39+
'🎉',
40+
'💣',
41+
'✔️',
42+
'💯',
43+
'⚛️',
44+
'💩',
45+
'🚀',
46+
'🍵',
47+
];
48+
49+
// Generate a random constant lenght string from a given charcter pool
50+
const makeString = (length, pool) => {
51+
let string = '';
52+
for (let i = 0; i < length; i++) {
53+
const index = Math.floor(Math.random() * 10000) % pool.length;
54+
string += pool[index];
55+
}
56+
return string;
57+
};
58+
59+
// Get input array with random strings
60+
const getInput = pool => {
61+
const times = range(0, 10000);
62+
const strings = [];
63+
forEach(times, () => {
64+
strings.push(makeString(50, pool));
65+
});
66+
return strings;
67+
};
68+
69+
// Run a cb on each string from input array and return the time diff
70+
const emojiBench = ({ cb, input, label }) => {
71+
const arr = [];
72+
const start = now();
73+
forEach(input, (string) => {
74+
arr.push(cb(string));
75+
});
76+
const time = now() - start;
77+
console.log(`[${chalk.yellow(label)}]: ${time}`);
78+
return time;
79+
};
80+
81+
// Define tested methods
82+
// In case of punycode it's required to also decode.
83+
// To be fair other test will concat back to string as well.
84+
const tests = [
85+
{
86+
cb: string => Array.from(string).join(''),
87+
label: 'Array.from',
88+
},
89+
{
90+
cb: string => runes(string).join(''),
91+
label: 'runes',
92+
},
93+
{
94+
cb: string => punycode.ucs2.encode(punycode.ucs2.decode(string)),
95+
label: 'punycode',
96+
},
97+
];
98+
99+
// Executes a single batch of tests, and adds some colors :)
100+
const batch = (input, label) => {
101+
console.log(`\nRunning: ${chalk.green(label)}`);
102+
const results = tests.map(test =>
103+
emojiBench(Object.assign({}, test, { input }))
104+
);
105+
const winner = min(results);
106+
console.log(
107+
`Best time ${chalk.green(winner)} - ${tests[results.indexOf(winner)].label}`
108+
);
109+
};
110+
111+
// Run test benchmark
112+
console.log(
113+
`--- Emoji benchmark running on ${chalk.bold.yellow(process.title)} ${chalk.bold.green(process.version)} ---`
114+
);
115+
116+
// 0 - 10
117+
batch(getInput(emojis), 'Random strings with 100% emojis');
118+
// 10 - 10
119+
batch(getInput([...chars.slice(0, 10), ...emojis]), 'Random strings with 1/2 emojis');
120+
// 20 - 10
121+
batch(getInput([...chars, ...emojis]), 'Random strings with 1/3 emojis');
122+
// 40 - 10
123+
batch(getInput([...chars, ...emojis, ...chars]), 'Random strings with 1/5 emojis');
124+
// 40 - 10
125+
batch(getInput(chars), 'Random strings with no emojis');

benchmarks/package-lock.json

Lines changed: 62 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

benchmarks/package.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "redraft-benchmarks",
3+
"version": "0.8.1",
4+
"description": "",
5+
"main": "index.js",
6+
"scripts": {
7+
"emoji": "node emoji.js"
8+
},
9+
"private": true,
10+
"repository": {
11+
"type": "git",
12+
"url": "https://github.com/lokiuz/redraft.git"
13+
},
14+
"author": "",
15+
"license": "ISC",
16+
"dependencies": {
17+
"chalk": "^1.1.3",
18+
"lodash": "^4.17.4",
19+
"performance-now": "^2.1.0",
20+
"punycode": "^2.1.0",
21+
"runes": "^0.4.0"
22+
}
23+
}

package.json

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "redraft",
3-
"version": "0.8.0",
3+
"version": "0.9.0",
44
"description": "Renders the result of Draft.js convertToRaw using provided callbacks, works well with React",
55
"main": "./lib/index.js",
66
"scripts": {
@@ -22,26 +22,30 @@
2222
"author": "",
2323
"license": "MIT",
2424
"devDependencies": {
25-
"babel-cli": "^6.6.5",
25+
"babel-cli": "^6.26.0",
2626
"babel-core": "^6.7.2",
2727
"babel-eslint": "^7.0.0",
2828
"babel-plugin-array-includes": "^2.0.3",
2929
"babel-preset-env": "^1.2.1",
30+
"babel-preset-flow": "^6.23.0",
3031
"babel-preset-react": "^6.23.0",
3132
"babel-register": "^6.16.3",
3233
"chai": "^3.5.0",
33-
"draft-js": "^0.10.0",
34+
"draft-js": "^0.10.4",
3435
"eslint": "^3.7.1",
3536
"eslint-config-airbnb": "^11.2.0",
3637
"eslint-plugin-import": "^1.16.0",
3738
"eslint-plugin-jsx-a11y": "^2.2.3",
3839
"eslint-plugin-react": "^6.4.1",
40+
"flow-bin": "^0.57.3",
3941
"linkify-it": "^2.0.3",
4042
"mocha": "^3.0.2",
4143
"react": "^15.4.2",
4244
"react-dom": "^15.4.2",
4345
"rimraf": "^2.5.2",
4446
"tlds": "^1.183.0"
4547
},
46-
"dependencies": {}
48+
"dependencies": {
49+
"punycode": "^2.1.0"
50+
}
4751
}

src/ContentNode.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@ class ContentNode {
88
this.end = typeof props.end !== 'undefined' ? props.end : null;
99
this.entity = typeof props.entity !== 'undefined' ? props.entity : null;
1010
this.decorator = typeof props.decorator !== 'undefined' ? props.decorator : null;
11+
this.decoratorProps = props.decoratorProps || null;
1112
this.decoratedText = typeof props.decoratedText !== 'undefined' ? props.decoratedText : null;
13+
this.contentState = props.contentState;
1214
this.style = props.style || null;
1315
this.styles = props.styles || null;
16+
this.block = props.block || {};
1417
}
1518

1619
getCurrentContent() {
@@ -34,7 +37,7 @@ class ContentNode {
3437
}
3538

3639
pushContent(string, stack = [], flat = false) {
37-
// we can just concat strings in case when both the pushed item
40+
// we can just concat strings when both the pushed item
3841
// and the last element of the content array is a string
3942
if (!stack || stack.length < 1) {
4043
if (typeof string === 'string' && typeof this.getCurrentContent() === 'string') {
@@ -44,7 +47,7 @@ class ContentNode {
4447
}
4548
return this;
4649
}
47-
// hnadle flat structure
50+
// handle flat structure
4851
if (flat) {
4952
this.handleFlatPush(string, stack);
5053
return this;

0 commit comments

Comments
 (0)