diff --git a/ComponentInterpolator.js b/ComponentInterpolator.js index 189871e..19627c7 100644 --- a/ComponentInterpolator.js +++ b/ComponentInterpolator.js @@ -1,98 +1,75 @@ -/* -Given: - -Ohai {this.props.user}, click here right now please! - -Pre-process it into: - - - - - -*/ +/** + * Given: + * + * Ohai {this.props.user}, click here right now please! + * + * Pre-process it into: + * + * , + * '**': , + * '***': }} + * /> + * + * Which is equivalent to: + * + * Ohai {this.props.user}, click here right now please! + * + * ... but completely localizable :) + */ 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 { string, object } = React.PropTypes; var ComponentInterpolator = React.createClass({ propTypes: { - string: string.isRequired + string: string.isRequired, + wrappers: object.isRequired }, componentWillMount() { - var textCount = this.textCount(); - var componentCount = this.componentCount(); invariant( - textCount === 0, - ' cannot have any text children' + !this.props.children, + ' cannot have any children' ); }, - textCount(node) { - node = node || this; - count = 0; - React.Children.forEach(node.props.children, (child) => { - count += typeof child === 'string' ? 1 : this.textCount(child); - }); - return count; - }, - - componentCount(node) { - node = node || this; - count = 0; - React.Children.forEach(node.props.children, (child) => { - count += typeof child === 'string' ? 0 : 1 + this.componentCount(child); - }); - return count; + inferChildren() { + var tokens = (this.props.string || '').split(/(\*+)/); + return this.interpolateComponents(tokens); }, - inferChildren(string, children) { - var tokens = (string || '').split(/(\*+)/); - return this.interpolateChildren(tokens, children); - }, - - interpolateChildren(tokens, children, eof) { - children = children instanceof Array ? children.slice() : children ? [children] : []; - var token, child, newChildren = []; + interpolateComponents(tokens, eof) { + var token, child + var children = []; + var wrappers = this.props.wrappers || {}; while (tokens.length) { token = tokens.shift(); if (token === eof) break; if (token.match(/\*/)) { - child = children.shift(); + invariant( + child = wrappers[token], + `'s string expected ${token} wrapper, none found` + ) child = cloneWithProps(child, { - key: child.props.key, - children: this.interpolateChildren(tokens, child.props.children, token) + key: token, + children: this.interpolateComponents(tokens, 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]; + children.push(child); } - return props; + return children; }, 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 }); + return React.createElement('span', {}, this.inferChildren()); } }); diff --git a/__tests__/ComponentInterpolator.test.js b/__tests__/ComponentInterpolator.test.js index aee5a3e..4418f68 100644 --- a/__tests__/ComponentInterpolator.test.js +++ b/__tests__/ComponentInterpolator.test.js @@ -9,20 +9,30 @@ var removeNoise = function(string) { describe('ComponentInterpolator', function() { it('renders', function() { - var subject = Subject({string: 'Hello World'}); + var subject = Subject({ + string: 'Hello World', + wrappers: {} + }); expect(subject.isMounted()).toEqual(true); expect(subject.getDOMNode().textContent).toEqual('Hello World'); }); it('escapes html in the string', function() { - var subject = Subject({string: 'My favorite tag is