forked from jenseng/react-i18nliner
-
Notifications
You must be signed in to change notification settings - Fork 2
/
ComponentInterpolator.js
99 lines (83 loc) · 2.52 KB
/
ComponentInterpolator.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/*
Given:
<Translate>Ohai {this.props.user}, click <Link>here</Link> right <b>now <i>please</i></b>!</Translate>
Pre-process it into:
<ComponentInterpolator string={I18n.t("Ohai, %{user}, click *here* right ***now **please** ***", {user: this.props.user})">
<Link />
<b><i /></b>
</ComponentInterpolator>
*/
var React = require('react');
var cloneWithProps = require('react/lib/cloneWithProps');
var invariant = require('react/lib/invariant');
var { string } = React.PropTypes;
var OWN_PROPS = ['defaultValue', 'translateKey', 'children'];
var ComponentInterpolator = React.createClass({
propTypes: {
string: string.isRequired
},
componentWillMount() {
var textCount = this.textCount();
var componentCount = this.componentCount();
invariant(
textCount === 0,
'<ComponentInterpolator> cannot have any text children'
);
},
textCount(node) {
node = node || this;
count = 0;
React.Children.forEach(node.props.children, function(child) {
count += typeof child === 'string' ? 1 : this.textCount(child);
});
return count;
},
componentCount(node) {
node = node || this;
count = 0;
React.Children.forEach(node.props.children, function(child) {
count += typeof child === 'string' ? 0 : 1 + this.componentCount(child);
});
return count;
},
inferChildren(string, children) {
var tokens = (string || '').split(/(\*+)/);
return this.interpolateChildren(tokens, children);
},
interpolateChildren(tokens, children, eof) {
var token, child, newChildren = [];
while (tokens.length) {
token = tokens.shift();
if (token === eof) break;
if (token.match(/\*/)) {
child = children.shift();
child = cloneWithProps(child, {
key: child.key,
children: this.interpolateChildren(tokens, child.children, token)
});
}
else {
child = token;
}
newChildren.push(child);
}
return newChildren;
},
extraProps() {
var props = {};
for (var key in this.props) {
if (OWN_PROPS.indexOf(key) === -1)
props[key] = this.props[key];
}
return props;
},
render() {
var options = this.extraProps();
var translateKey = this.props.translateKey;
var defaultValue = this.props.defaultValue || this.props.children;
options.defaultValue = defaultValue;
var children = this.inferChildren(this.props.string, this.props.children);
return React.createElement('span', {}, children);
}
});
module.exports = ComponentInterpolator;