UNPKG

@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
'use strict'; 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;