@petrican/react-interpolate-component
Version:
Fork - A component for React that renders elements into a format string containing replacement fields
88 lines (65 loc) • 2.18 kB
JavaScript
;
var React = require('react');
var invariant = require('invariant');
var except = require('except');
var extend = require('object-assign');
var createReactClass = require('create-react-class');
function isString(object) {
return Object.prototype.toString.call(object) === '[object String]';
}
var REGEXP = /\%\((.+?)\)s/;
var OMITTED_PROPS = ['children', 'format', 'component', 'unsafe', 'with'];
var Interpolate = createReactClass({
displayName: 'Interpolate',
getDefaultProps: function() {
return { component: 'span' };
},
render: function() {
var format = this.props.children;
var parent = this.props.component;
var unsafe = this.props.unsafe === true;
var interpolations = extend({}, this.props, this.props.with);
var props = except(this.props, OMITTED_PROPS);
var matches = [];
var children = [];
if (!isString(format)) {
format = this.props.format;
}
invariant(isString(format), 'Interpolate expects either a format string as only child or a `format` prop with a string value');
if (unsafe) {
var content = format.split(REGEXP).reduce(function(memo, match, index) {
var html;
if (index % 2 === 0) {
html = match;
} else {
html = interpolations[match];
matches.push(match);
}
if (React.isValidElement(html)) {
throw new Error('cannot interpolate a React component into unsafe text');
}
memo += html;
return memo;
}, '');
props.dangerouslySetInnerHTML = { __html: content };
} else {
format.split(REGEXP).reduce(function(memo, match, index) {
var child;
if (index % 2 === 0) {
if (match.length === 0) {
return memo;
}
child = match;
} else {
child = interpolations[match];
matches.push(match);
}
memo.push(child);
return memo;
}, children);
}
props = except(props, matches);
return React.createElement.apply(this, [parent, props].concat(children));
}
});
module.exports = Interpolate;