Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .babelrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"presets": ["es2015", "react", "stage-2"],
"presets": ["es2015", "react", "stage-1"]
}
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@

## Features

* Switchble emoji assets ([twemoji](https://github.com/twitter/twemoji) or [Emoji One](https://github.com/Ranks/emojione))
* Switchable emoji assets ([twemoji](https://github.com/twitter/twemoji) or [Emoji One](https://github.com/Ranks/emojione))
* Supports emoticons such as `:) :(`
* Custom emoji dictionary can be given, pointing to image URLs

## Compatible React Versions

Expand Down Expand Up @@ -69,6 +70,7 @@ ext | asset ext. svg or png are available | svg | String
attributes | Attributes such as className or onClick | {width: '20px', height: '20px'} | Object
singleEmoji | Show single emoji (either of annotation or emoticon), use this option if input is limited to render single emoji, this is slightly faster | false | Boolean
strict | Throw an error if annotation is not in dict, it's handy if emoji input is not from end user | false | Boolean
customDict | Object to use as custom emoji dictionary. Values are image URLs for each key. | {} | Object

## Tips

Expand Down
4 changes: 2 additions & 2 deletions dist/react-emoji.js

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@
},
"homepage": "https://github.com/banyan/react-emoji",
"devDependencies": {
"babel-core": "^4.7.8",
"babel-core": "^6.24.1",
"babel-jest": "^19.0.0",
"babel-loader": "^4.1.0",
"babel-loader": "^6.4.1",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
"babel-preset-stage-1": "^6.24.1",
"enzyme": "^2.8.0",
"enzyme-to-json": "^1.5.0",
"eslint": "^3.19.0",
Expand All @@ -60,7 +60,7 @@
"react-addons-test-utils": "~0.14.1",
"react-dom": "~0.14.1",
"react-hot-loader": "^1.2.3",
"webpack": "^1.7.2",
"webpack": "^1.15.0",
"webpack-dev-server": "^1.7.0"
},
"dependencies": {
Expand Down
2 changes: 1 addition & 1 deletion src/ReactEmojiComponent.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
import { emojify } from './index'
import emojify from './emojify'

const isString = (obj) => typeof(obj) === 'string'

Expand Down
40 changes: 28 additions & 12 deletions src/emojify.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,45 @@ const buildOptions = options => ({
width: '20px',
height: '20px',
...options.attributes
}
},
customDict: options.customDict || {}
})

// Use negated lookahead for `:/`, refs: https://github.com/banyan/react-emoji/issues/1
const specialEmoticons = { ':/': '1f615' }
const specialEmoticonsRegex = '\\:\\/(?!\\/)'

const emojiWithEmoticons = {
delimiter: new RegExp(`(:(?:${getEscapedKeys(annotations)}):|${getEscapedKeys(emoticons)}|${specialEmoticonsRegex})`, 'g'),
dict: {
const emojiWithEmoticons = (customDict) => {
const annotationsPlusCustom = {
...annotations,
...emoticons,
...specialEmoticons,
...customDict
}
return {
delimiter: new RegExp(`(:(?:${getEscapedKeys(annotationsPlusCustom)}):|${getEscapedKeys(emoticons)}|${specialEmoticonsRegex})`, 'g'),
dict: {
...annotationsPlusCustom,
...emoticons,
...specialEmoticons
}
}
}

const emojiWithoutEmoticons = {
delimiter: new RegExp(`(:(?:${getEscapedKeys(annotations)}):)`, 'g'),
dict: annotations,
const emojiWithoutEmoticons = (customDict) => {
const annotationsPlusCustom = {
...annotations,
...customDict
}
return {
delimiter: new RegExp(`(:(?:${getEscapedKeys(annotationsPlusCustom)}):)`, 'g'),
dict: annotationsPlusCustom
}
}

const buildImageUrl = (hex, options) => {
if (options.host) {
if (hex.startsWith('http')) {
// came as a URL from a custom dictionary
return hex
} else if (options.host) {
return compact([options.host, options.path, `${hex}.${options.ext}`]).join('/')
} else if (options.emojiType === 'twemoji') {
return `https://twemoji.maxcdn.com/${options.ext}/${hex}.${options.ext}`
Expand All @@ -60,7 +76,7 @@ const getKey = (key) => {
}

const emojifyTextToSingleEmoji = (text, options) => {
const { dict } = options.useEmoticon ? emojiWithEmoticons : emojiWithoutEmoticons
const { dict } = options.useEmoticon ? emojiWithEmoticons(options.customDict) : emojiWithoutEmoticons(options.customDict)
const hex = dict[getKey(text)]
if (!!options.strict && !hex) throw new Error(`Could not find emoji: ${text}.`)
if (!hex) return text
Expand All @@ -74,7 +90,7 @@ const emojifyTextToSingleEmoji = (text, options) => {
}

const emojifyText = (text, options) => {
const { delimiter, dict } = options.useEmoticon ? emojiWithEmoticons : emojiWithoutEmoticons
const { delimiter, dict } = options.useEmoticon ? emojiWithEmoticons(options.customDict) : emojiWithoutEmoticons(options.customDict)
return compact(
text.split(delimiter).map((word, index) => {
const match = word.match(delimiter)
Expand Down
25 changes: 25 additions & 0 deletions test/__snapshots__/react-emoji.test.jsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,31 @@ exports[`renders :smile: annotation with ReactEmoji 1`] = `
</ReactEmoji>
`;

exports[`renders custom emoji 1`] = `
<SampleComponent
options={
Object {
"customDict": Object {
"batman": "https://my.custom.server.com/batman.jpg",
},
}
}
text="foo :batman: bar"
>
<div>
<span>
foo
<img
height="20px"
src="https://my.custom.server.com/batman.jpg"
width="20px"
/>
bar
</span>
</div>
</SampleComponent>
`;

exports[`renders multiple emoticon and annotation 1`] = `
<SampleComponent
options={Object {}}
Expand Down
15 changes: 15 additions & 0 deletions test/react-emoji.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -260,4 +260,19 @@ describe('emojify', () => {
expect(wrapper).toMatchSnapshot('renders multiple emoticon and annotation')
})
})

context('custom emoji', () => {
it('renders from custom dictionary', () => {
const customDict = {
batman: "https://my.custom.server.com/batman.jpg"
};
const wrapper = mount(
<SampleComponent
text="foo :batman: bar"
options={{ customDict: customDict }}
/>,
)
expect(wrapper).toMatchSnapshot('renders custom emoji')
})
})
})
12 changes: 8 additions & 4 deletions webpack.production.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ var webpack = require('webpack');
* This is the Webpack configuration file for production.
*/
module.exports = {
entry: "./src/react-emoji",
entry: "./src/index.js",

output: {
library: 'ReactEmoji',
Expand All @@ -25,9 +25,13 @@ module.exports = {
],

module: {
loaders: [
{ test: /\.jsx?$/, exclude: /node_modules/, loader: "babel-loader" }
]
loaders: [{
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['react', 'es2015', 'stage-1']
}
}]
},

resolve: {
Expand Down