diff --git a/example/main.jsx b/example/main.jsx index 3fcb296..1afa141 100644 --- a/example/main.jsx +++ b/example/main.jsx @@ -1,7 +1,7 @@ import 'babel-core/polyfill'; import React from 'react'; import ReactDOM from 'react-dom'; -import ReactEmojiMixin from '../src/react-emoji'; +import ReactEmoji, { ReactEmojiMixin, emojify } from '../src/react-emoji'; let App = React.createClass({ getDefaultProps() { @@ -17,7 +17,30 @@ let App = React.createClass({ render() { return (
-
{ this.emojify(this.props.text) }
+
+ + {this.props.text} + +
+
+ + {"Hello World"} + +
+
+ +
+
+ +
+
+ {this.props.text} +
+ {this.props.text} +
+
+
+
{ emojify(this.props.text) }
{ this.emojify(this.props.text, {emojiType: 'emojione'}) }
{ this.emojify(this.props.text, {useEmoticon: false}) }
diff --git a/src/react-emoji.js b/src/react-emoji.js index 9dc30a8..fbdb7c0 100644 --- a/src/react-emoji.js +++ b/src/react-emoji.js @@ -6,6 +6,75 @@ import assign from 'object-assign'; import compact from 'lodash.compact'; let ReactEmoji = () => { + const ReactEmojiPropTypes = { + useEmoticon: React.PropTypes.bool, + emojiType: React.PropTypes.string, + host: React.PropTypes.string, + path: React.PropTypes.string, + ext: React.PropTypes.string, + singleEmoji: React.PropTypes.bool, + strict: React.PropTypes.bool, + children: React.PropTypes.any, + }; + + const ReactEmojiComponent = React.createClass({ + displayName: "ReactEmoji", + + propTypes: ReactEmojiPropTypes, + + render() { + let emojifiedChildren = this.emojifyChildrenText(this.props.children, this.getOptionsFromProps()); + + if (!emojifiedChildren) return null; + + // support for a wrapper, instead of the span we provide + if (emojifiedChildren.length === 1 && React.isValidElement(emojifiedChildren[0])) { + return emojifiedChildren[0]; + } else { + return ( + + {emojifiedChildren} + + ); + } + }, + + getOptionsFromProps() { + let options = {}; + let attributes = assign({}, this.props); + + for (let key in ReactEmojiPropTypes) { + options[key] = this.props[key]; + delete attributes[key]; + } + + options.attributes = attributes; + return options; + }, + + cloneAndEmojifyChild(child, options) { + return React.cloneElement(child, {}, this.emojifyChildrenText(child.props.children, options)); + }, + + // traverse and emojify the child nodes + emojifyChildrenText(children, options) { + return React.Children.map(children, (child) => { + if (isString(child)) { + return emojify(child, options); + } else if (React.isValidElement(child)) { + return this.cloneAndEmojifyChild(child, options); + } else { + return child; + } + }); + } + + }); + + let isString = (obj) => { + return toString.call(obj) === '[object String]'; + }; + let getEscapedKeys = (hash) => { return Object.keys(hash) .map(x => escapeStringRegexp(x)) @@ -96,17 +165,29 @@ let ReactEmoji = () => { ); }; + let emojify = (text, options = {}) => { + if (!text) return null; + options = buildOptions(options); + if (options.singleEmoji) { + return emojifyTextToSingleEmoji(text, options); + } else { + return emojifyText(text, options); + } + }; + return { - emojify(text, options = {}) { - if (!text) return null; - options = buildOptions(options); - if (options.singleEmoji) { - return emojifyTextToSingleEmoji(text, options); - } else { - return emojifyText(text, options); - } - }, + ReactEmojiComponent: ReactEmojiComponent, + + emojify: emojify, }; }; -export default ReactEmoji(); +let { ReactEmojiComponent, emojify } = ReactEmoji(); + +export { emojify } + +export var ReactEmojiMixin = { + emojify: emojify +}; + +export { ReactEmojiComponent as default } diff --git a/test/react-emoji-test.js b/test/react-emoji-test.js index c5c3097..231d4b0 100644 --- a/test/react-emoji-test.js +++ b/test/react-emoji-test.js @@ -3,7 +3,7 @@ import ReactDOM from "react-dom"; import assert from 'power-assert'; import TestUtils from 'react-addons-test-utils'; -import ReactEmojiMixin from "../src/react-emoji"; +import {ReactEmojiMixin} from "../src/react-emoji"; let SampleComponent = React.createClass({ getDefaultProps() {