Repository: draft-js-plugins/draft-js-plugins
Pull request #2916 (2022-08-19 14:25:48)

Speed up initial opening of select
## Checklist

- [x] Fix any eslint errors that occur
- [x] Update change-log for every plugin you touch
- [x] Add/Update tests if you add/change new functionality
- [ ] Add/Update docs if you add/change functionality
- [x] Enable "Allow edits from maintainers" for this PR

## Use-case/Problem

Opening the Emoji Select or the Emoji Suggestion for the first time is extremely slow, ca. 3 seconds.
Subsequent usage is fast though.

The reason for that is, that `shortnameToUnicode` (from the `emoji-toolkit` library) uses a really huge RegEx, which is slow for the first call.

## Implementation
Instead of using this library method, we create a mapping from shortname to unicode from the same data used to build the EmojiStrategy.


BSeblu: > Wouldn't it make more sense to fix this in the `emoji-toolkit` library?

I don't think so. This plugin needs to map an emoji-name to a unicode character, which you can technically do with `emoji-toolkit`'s `shortnameToUnicode`. But that method is doing a different job. In an arbitrary string it replaces every instance of emoji-names with the corresponding  unicode character.

So is `emoji-toolkit`'s implementation of `shortnameToUnicode` inefficient? Maybe, maybe not. But I don't think it's the right tool for the job. The name `shortnameToUnicode` is in fact a bit misleading: If I haven't looked into the sources, I would have suggested that it just maps an emoji-name to a unicode character.

Patch:
diff --git a/packages/emoji/CHANGELOG.md b/packages/emoji/CHANGELOG.md
index 9d50738c..16327108 100644
--- a/packages/emoji/CHANGELOG.md
+++ b/packages/emoji/CHANGELOG.md
@@ -5,6 +5,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 
 ## To be released
 
+## 4.6.3
+
+- fix performance issue with shortname to unicode translation [#2915](https://github.com/draft-js-plugins/draft-js-plugins/issues/2915)
+
 ## 4.6.2
 
 - Autoclose emoji popover for multiple instance [#2875](https://github.com/draft-js-plugins/draft-js-plugins/issues/2875)
diff --git a/packages/emoji/package.json b/packages/emoji/package.json
index 55b4f058..9b1c1b0b 100644
--- a/packages/emoji/package.json
+++ b/packages/emoji/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@draft-js-plugins/emoji",
-  "version": "4.6.2",
+  "version": "4.6.3",
   "sideEffects": [
     "*.css"
   ],
diff --git a/packages/emoji/src/components/EmojiSelect/Popover/Entry/index.tsx b/packages/emoji/src/components/EmojiSelect/Popover/Entry/index.tsx
index cacd741e..17829088 100644
--- a/packages/emoji/src/components/EmojiSelect/Popover/Entry/index.tsx
+++ b/packages/emoji/src/components/EmojiSelect/Popover/Entry/index.tsx
@@ -1,7 +1,7 @@
-import { shortnameToUnicode } from 'emoji-toolkit';
 import PropTypes from 'prop-types';
 import React, { Component, ComponentType, ReactElement } from 'react';
 import { EmojiImageProps, EmojiPluginTheme } from '../../../../index';
+import shortnameToUnicode from '../../../../utils/shortnameToUnicode';
 
 interface EntryProps {
   mouseDown?: boolean;
diff --git a/packages/emoji/src/components/EmojiSuggestions/Entry/index.tsx b/packages/emoji/src/components/EmojiSuggestions/Entry/index.tsx
index 392a6518..fe1e9365 100644
--- a/packages/emoji/src/components/EmojiSuggestions/Entry/index.tsx
+++ b/packages/emoji/src/components/EmojiSuggestions/Entry/index.tsx
@@ -1,4 +1,3 @@
-import { shortnameToUnicode } from 'emoji-toolkit';
 import { EmojiImageProps } from 'packages/emoji/src';
 import React, {
   // PropTypes,
@@ -8,6 +7,7 @@ import React, {
   ReactElement,
 } from 'react';
 import { EmojiPluginTheme } from '../../../theme';
+import shortnameToUnicode from '../../../utils/shortnameToUnicode';
 
 interface EntryProps {
   emoji: string;
diff --git a/packages/emoji/src/modifiers/addEmoji.ts b/packages/emoji/src/modifiers/addEmoji.ts
index bc1566f3..37be4165 100644
--- a/packages/emoji/src/modifiers/addEmoji.ts
+++ b/packages/emoji/src/modifiers/addEmoji.ts
@@ -1,5 +1,5 @@
 import { Modifier, EditorState } from 'draft-js';
-import { shortnameToUnicode } from 'emoji-toolkit';
+import shortnameToUnicode from '../utils/shortnameToUnicode';
 import getSearchText from '../utils/getSearchText';
 
 // This modifier can inserted emoji to current cursor position (with replace selected fragment),
diff --git a/packages/emoji/src/utils/shortnameToUnicode.ts b/packages/emoji/src/utils/shortnameToUnicode.ts
new file mode 100644
index 00000000..8558d5b6
--- /dev/null
+++ b/packages/emoji/src/utils/shortnameToUnicode.ts
@@ -0,0 +1,10 @@
+import { toShort } from 'emoji-toolkit';
+import data from 'emojibase-data/en/compact.json';
+
+const mapShortnameToUnicode: Record<string, string> = Object.fromEntries(
+  data.map((item) => [toShort(item.unicode), item.unicode])
+);
+
+export default function shortnameToUnicode(str: string): string {
+  return mapShortnameToUnicode[str];
+}


Test patch:
diff --git a/packages/emoji/src/utils/__test__/shortnameToUnicode.test.ts b/packages/emoji/src/utils/__test__/shortnameToUnicode.test.ts
new file mode 100644
index 00000000..89ee5000
--- /dev/null
+++ b/packages/emoji/src/utils/__test__/shortnameToUnicode.test.ts
@@ -0,0 +1,15 @@
+import shortnameToUnicode from '../shortnameToUnicode';
+
+describe('shortnameToUnicode', () => {
+  it('empty shortname -> undefined', () => {
+    expect(shortnameToUnicode('')).toBeUndefined();
+  });
+
+  it('invalid shortname -> undefined', () => {
+    expect(shortnameToUnicode('obviously not an emoji name')).toBeUndefined();
+  });
+
+  it('valid shortname -> emoji', () => {
+    expect(shortnameToUnicode(':grinning:')).toBe('😀');
+  });
+});