diff --git a/.gitignore b/.gitignore
index 1a93bf0..cd454ee 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,7 @@ lib
.DS_Store
.log
data/raw/
+
+# IDE
.vscode
+.idea/
\ No newline at end of file
diff --git a/src/__tests__/__snapshots__/index-test.js.snap b/src/__tests__/__snapshots__/index-test.js.snap
index 0f12d22..38c9227 100644
--- a/src/__tests__/__snapshots__/index-test.js.snap
+++ b/src/__tests__/__snapshots__/index-test.js.snap
@@ -201,6 +201,39 @@ exports[`Emoji emoji with a single codepoint 1`] = `
`;
+exports[`Emoji force unicode on img-supported emoji services 1`] = `
+
+ Hello World!
+
+ ๐
+
+ <- should be unicode โ
+
+ ๐ฎ
+
+ ctocat: <- should be image on GitHub
+
+`;
+
exports[`Emoji four emoji should not add onlyEmojiClassName 1`] = `
@@ -641,6 +674,39 @@ exports[`Emojione emoji with a single codepoint 1`] = `
`;
+exports[`Emojione force unicode on img-supported emoji services 1`] = `
+
+ Hello World!
+
+ ๐
+
+ <- should be unicode โ
+
+ ๐ฎ
+
+ ctocat: <- should be image on GitHub
+
+`;
+
exports[`Emojione four emoji should not add onlyEmojiClassName 1`] = `
@@ -1080,6 +1146,39 @@ exports[`EmojioneV4 emoji with a single codepoint 1`] = `
`;
+exports[`EmojioneV4 force unicode on img-supported emoji services 1`] = `
+
+ Hello World!
+
+ ๐
+
+ <- should be unicode โ
+
+ ๐ฎ
+
+ ctocat: <- should be image on GitHub
+
+`;
+
exports[`EmojioneV4 four emoji should not add onlyEmojiClassName 1`] = `
@@ -1316,13 +1415,13 @@ exports[`EmojioneV4 with svg prop 1`] = `
`;
-exports[`Twemoji a mixture of emoji syntax 1`] = `
+exports[`GitHub a mixture of emoji syntax 1`] = `
`;
-exports[`Twemoji aliases containing underscores 1`] = `
+exports[`GitHub aliases containing underscores 1`] = `
`;
-exports[`Twemoji aliases with skin tone modifiers 1`] = `
+exports[`GitHub aliases with skin tone modifiers 1`] = `
Say hello to
`;
-exports[`Twemoji ascii aliases 1`] = `
+exports[`GitHub ascii aliases 1`] = `
That\'s awesome
`;
-exports[`Twemoji composed emojis containing U+200D and U+FE0F chars 1`] = `
+exports[`GitHub composed emojis containing U+200D and U+FE0F chars 1`] = `
`;
-exports[`Twemoji does nothing to unknown aliases 1`] = `
+exports[`GitHub does nothing to unknown aliases 1`] = `
An :unknown: alias
`;
-exports[`Twemoji emoji with a multiple codepoints 1`] = `
+exports[`GitHub emoji with a multiple codepoints 1`] = `
Great work
`;
-exports[`Twemoji emoji with a single codepoint 1`] = `
+exports[`GitHub emoji with a single codepoint 1`] = `
This
+
+`;
+
+exports[`GitHub force unicode on img-supported emoji services 1`] = `
+
+ Hello World!
+
+ ๐
+
+ <- should be unicode
+
+
+
+ <- should be image on GitHub
+
+`;
+
+exports[`GitHub four emoji should not add onlyEmojiClassName 1`] = `
+
+
+
+
+
+
+`;
+
+exports[`GitHub just emoji should add onlyEmojiClassName 1`] = `
+
+
+
+`;
+
+exports[`GitHub just emoticon should add onlyEmojiClassName 1`] = `
+
+
+
+`;
+
+exports[`GitHub simple aliases 1`] = `
+
+ This
+
+ is nice
+
+
+`;
+
+exports[`GitHub strings with no emoji 1`] = `
+
+ Just some words
+
+`;
+
+exports[`GitHub three emoji should add onlyEmojiClassName 1`] = `
+
+
+
+
+
+`;
+
+exports[`GitHub with size prop 1`] = `
+
+ This
+
+ is
+
+
+`;
+
+exports[`GitHub with svg prop 1`] = `
+
+ This
+
+ is
+
+
+`;
+
+exports[`Twemoji a mixture of emoji syntax 1`] = `
+
+
+ This is a selection of
+
+ emoji
+
+
+
+
+`;
+
+exports[`Twemoji aliases containing underscores 1`] = `
+
+
+ wow
+
+`;
+
+exports[`Twemoji aliases with skin tone modifiers 1`] = `
+
+ Say hello to
+
+
+`;
+
+exports[`Twemoji ascii aliases 1`] = `
+
+ That\'s awesome
+
+
+`;
+
+exports[`Twemoji composed emojis containing U+200D and U+FE0F chars 1`] = `
+
+
+
+`;
+
+exports[`Twemoji does nothing to unknown aliases 1`] = `
+
+ An :unknown: alias
+
+`;
+
+exports[`Twemoji emoji with a multiple codepoints 1`] = `
+
+ Great work
+
+
+
+
+`;
+
+exports[`Twemoji emoji with a single codepoint 1`] = `
+
+ This
+
+ is
+
+
+`;
+
+exports[`Twemoji force unicode on img-supported emoji services 1`] = `
+
+ Hello World!
+
+ ๐
+
+ <- should be unicode โ
+
+ ๐ฎ
+
+ ctocat: <- should be image on GitHub
`;
diff --git a/src/__tests__/index-test.js b/src/__tests__/index-test.js
index d445934..f15a0e6 100644
--- a/src/__tests__/index-test.js
+++ b/src/__tests__/index-test.js
@@ -1,8 +1,14 @@
import React from "react";
-import Emoji, { Twemoji, Emojione, EmojioneV4, toArray } from "../../src/index";
+import Emoji, {
+ Twemoji,
+ Emojione,
+ EmojioneV4,
+ GitHub,
+ toArray,
+} from "../../src/index";
import renderer from "react-test-renderer";
-[Emoji, Twemoji, Emojione, EmojioneV4].forEach(Component => {
+[Emoji, Twemoji, Emojione, EmojioneV4, GitHub].forEach(Component => {
describe(Component.name, () => {
test("strings with no emoji", () => {
const component = renderer.create();
@@ -121,6 +127,17 @@ import renderer from "react-test-renderer";
let tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
+
+ test("force unicode on img-supported emoji services", () => {
+ const component = renderer.create(
+
+ );
+ let tree = component.toJSON();
+ expect(tree).toMatchSnapshot();
+ });
});
});
diff --git a/src/aliasRegex.js b/src/aliasRegex.js
index b3a70b8..a1b8655 100644
--- a/src/aliasRegex.js
+++ b/src/aliasRegex.js
@@ -10,7 +10,10 @@ const names = flatten(
Object.keys(asciiAliases).map(name => {
return asciiAliases[name].map(escapeStringToBeUsedInRegExp);
})
-).sort().reverse().join("|"); // reverse sort for most specific match
+)
+ .sort()
+ .reverse()
+ .join("|"); // reverse sort for most specific match
const edgeCases = [startOfURL].join("|");
diff --git a/src/index.js b/src/index.js
index ea063a6..837b91d 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,6 +1,7 @@
import React from "react";
import PropTypes from "prop-types";
-import Emoji from "./renderer";
+import Emoji, { optionsType } from "./renderer";
+
export { toArray } from "./renderer";
let protocol = "https";
@@ -28,7 +29,7 @@ export function Twemoji({ svg, options, ...rest }) {
Twemoji.propTypes = {
text: PropTypes.string,
- options: PropTypes.object,
+ options: optionsType,
svg: PropTypes.bool,
};
@@ -49,7 +50,7 @@ export function Emojione({ svg, options, ...rest }) {
Emojione.propTypes = {
text: PropTypes.string,
- options: PropTypes.object,
+ options: optionsType,
svg: PropTypes.bool,
};
@@ -70,9 +71,48 @@ export function EmojioneV4({ size, options, ...rest }) {
EmojioneV4.propTypes = {
text: PropTypes.string,
- options: PropTypes.object,
+ options: optionsType,
size: PropTypes.oneOf([32, 64, 128]),
};
EmojioneV4.defaultProps = {
size: 64,
};
+
+export function GitHub({ options, forceUnicode, ...rest }) {
+ options = {
+ protocol,
+ baseUrl: `//github.githubassets.com/images/icons/emoji/unicode/`,
+ customUrl: `//github.githubassets.com/images/icons/emoji/`,
+ ext: "png",
+ customAliases: [
+ "atom",
+ "basecamp",
+ "basecampy",
+ "bowtie",
+ "electron",
+ "feelsgood",
+ "finnadie",
+ "goberserk",
+ "godmode",
+ "hurtrealbad",
+ "neckbeard",
+ "octocat",
+ "rage1",
+ "rage2",
+ "rage3",
+ "rage4",
+ "shipit",
+ "suspect",
+ "trollface",
+ ],
+ forceUnicode: !!forceUnicode,
+ ...options,
+ };
+ return ;
+}
+
+GitHub.propTypes = {
+ text: PropTypes.string,
+ options: optionsType,
+ forceUnicode: PropTypes.bool,
+};
diff --git a/src/renderer.js b/src/renderer.js
index 120d3a3..1019917 100644
--- a/src/renderer.js
+++ b/src/renderer.js
@@ -34,7 +34,8 @@ export function toArray(text, options = {}) {
const protocol = normalizeProtocol(options.protocol);
function replaceUnicodeEmoji(match, i) {
- if (!options.baseUrl) {
+ const isUnicode = !match.startsWith(":");
+ if (!options.baseUrl || (options.forceUnicode && isUnicode)) {
return (
{match}
@@ -42,16 +43,20 @@ export function toArray(text, options = {}) {
);
}
- let codepoint = unicodeToCodepoint(match, removeHelperCharacters);
-
// if Emojione we don't want to add helper characters in the URL
const removeHelperCharacters = options.emojione;
+ let codepoint = unicodeToCodepoint(match, removeHelperCharacters);
+
if (removeHelperCharacters) {
codepoint = codepoint.replace(/-200d/g, "").replace(/-fe0f/g, "");
}
-
const separator = options.size ? "/" : "";
- const src = `${protocol}${options.baseUrl}${options.size}${separator}${codepoint}.${options.ext}`;
+ const src = `${protocol}${
+ isUnicode ? options.baseUrl : options.customUrl
+ }${options.size || ""}${separator}${
+ // slice removes colons from custom emoji alias e.g :electron:->electron
+ isUnicode ? codepoint : match.slice(1, -1)
+ }.${options.ext}`;
return (
pos) {
// text between matches
textWithEmoji.push(text.slice(pos, match.index));
@@ -100,7 +111,23 @@ export function toArray(text, options = {}) {
return textWithEmoji.join("");
}
- return replace(replaceAliases(text), unicodeEmojiRegex, replaceUnicodeEmoji);
+ const customAliases = options.customAliases || [];
+ // adds custom aliases to the regex to detect. e.g GitHub's :electron: which isn't part of the unicode standard.
+ const modifiedRegex =
+ customAliases.length > 0
+ ? new RegExp(
+ // slice here removes the /.../g on regex tags
+ `${unicodeEmojiRegex.toString().slice(1, -2)}|:(${customAliases.join(
+ "|"
+ )}):`,
+ "g"
+ )
+ : unicodeEmojiRegex;
+ return replace(
+ replaceAliases(text, options),
+ modifiedRegex,
+ replaceUnicodeEmoji
+ );
}
export default function Emoji({
@@ -131,15 +158,19 @@ export default function Emoji({
);
}
-
+export const optionsType = PropTypes.shape({
+ baseUrl: PropTypes.string,
+ customUrl: PropTypes.string,
+ size: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
+ ext: PropTypes.string,
+ // image props
+ props: PropTypes.object,
+ className: PropTypes.string,
+ customAliases: PropTypes.arrayOf(PropTypes.string),
+ forceUnicode: PropTypes.bool,
+});
Emoji.propTypes = {
text: PropTypes.string,
- props: PropTypes.object,
onlyEmojiClassName: PropTypes.string,
- options: PropTypes.shape({
- baseUrl: PropTypes.string,
- size: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
- ext: PropTypes.string,
- className: PropTypes.string,
- }),
+ options: optionsType,
};