feat: add trimEmojiData util function

This commit is contained in:
Nolan Lawson 2020-06-20 14:06:19 -07:00
parent 665a630913
commit fa590877de
9 changed files with 93 additions and 22 deletions

3
.gitignore vendored
View File

@ -122,6 +122,9 @@ dist
/picker.d.ts
/database.d.ts
/shared.d.ts
/trimEmojiData.js
/trimEmojiData.cjs
/trimEmojiData.d.ts
/docs-tmp
/ts-tmp

View File

@ -610,14 +610,7 @@ The reason for this is that `Picker` automatically registers itself as a custom
### Data source and JSON format
`emoji-picker-element` requires the _full_ [emojibase-data](https://github.com/milesj/emojibase) JSON file, not the "compact" one. If you would like to trim the JSON file down even further, then you can modify the JSON to only contain these keys:
```json
[
"annotation", "emoji", "emoticon", "group",
"order", "shortcodes", "skins", "tags", "version"
]
```
`emoji-picker-element` requires the _full_ [emojibase-data](https://github.com/milesj/emojibase) JSON file, not the "compact" one (e.g. `emojibase-data/en/data.json`, not `emojibase-data/en/compact.json`).
You can fetch the emoji JSON file from wherever you want. However, it's recommended that your server expose an `ETag` header if so, `emoji-picker-element` can avoid re-downloading the entire JSON file over and over again. Instead, it will fire off a `HEAD` request and just check the `ETag`.
@ -625,6 +618,23 @@ If the server hosting the JSON file is not the same as the one containing the em
Unfortunately [Safari does not currently support `Access-Control-Allow-Headers`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers#Browser_compatibility), meaning that the `ETag` header will not be available cross-origin. In that case, `emoji-picker-element` will fall back to the less performant option. If you want to avoid this, host the JSON file on the same server as your web app.
### Trimming the emojibase data
If you are hosting the JSON file yourself and would like it to be as small as possible, then you can use the utility `trimEmojiData` function:
```js
import trimEmojiData from 'emoji-picker-element/trimEmojiData.js';
import emojiBaseData from 'emojibase-data/en/data.json';
const trimmedData = trimEmojiData(emojiBaseData);
```
Or if your version of Node doesn't support ES modules:
```js
const trimEmojiData = require('emoji-picker-element/trimEmojiData.cjs');
```
### Offline-first
`emoji-picker-element` uses a "stale while revalidate" strategy to update emoji data. In other words, it will use any existing data it finds in IndexedDB, and lazily update via the `dataSource` in case that data has changed. This means it will work [offline-first](http://offlinefirst.org/) the second time it runs.

View File

@ -10,6 +10,7 @@
"database.js*",
"index.js*",
"picker.js*",
"trimEmojiData.*",
"*.d.ts"
],
"scripts": {
@ -104,7 +105,9 @@
"ignore": [
"/database.js",
"/index.js",
"/picker.js"
"/picker.js",
"/trimEmojiData.js",
"/trimEmojiData.cjs"
],
"global": [
"btoa",

View File

@ -55,14 +55,23 @@ const entryPoints = [
{
input: './src/database/Database.js',
output: './database.js'
},
{
input: './src/trimEmojiData.js',
output: './trimEmojiData.js'
},
{
input: './src/trimEmojiData.js',
output: './trimEmojiData.cjs',
format: 'cjs'
}
]
export default entryPoints.map(({ input, output }) => ({
export default entryPoints.map(({ input, output, format = 'es' }) => ({
...baseConfig,
input,
output: {
format: 'es',
format,
file: output,
sourcemap: dev
}

View File

@ -1,13 +1,4 @@
const requiredKeys = [
'annotation',
'emoji',
'emoticon',
'group',
'order',
'shortcodes',
'tags',
'version'
]
import { requiredKeys } from './requiredKeys'
export function assertEmojiBaseData (emojiBaseData) {
if (!emojiBaseData ||

View File

@ -0,0 +1,10 @@
export const requiredKeys = [
'annotation',
'emoji',
'emoticon',
'group',
'order',
'shortcodes',
'tags',
'version'
]

18
src/trimEmojiData.js Normal file
View File

@ -0,0 +1,18 @@
import { assertEmojiBaseData } from './database/utils/assertEmojiBaseData'
import { requiredKeys } from './database/utils/requiredKeys'
const optionalKeys = ['skins', 'emoticon']
const allKeys = [...requiredKeys, ...optionalKeys]
export default function trimEmojiData (emojiBaseData) {
assertEmojiBaseData(emojiBaseData)
return emojiBaseData.map(emoji => {
const res = {}
for (const key of allKeys) {
if (key in emoji) {
res[key] = emoji[key]
}
}
return res
})
};

View File

@ -0,0 +1,10 @@
import {Emoji} from "./shared";
/**
* Given an array of emoji (e.g. emojibase-data/en/data.json), extract out only the data
* needed for emoji-picker-element, resulting in a smaller object.
* @param emojiBaseData
*/
export default function trimEmojiData(emojiBaseData: Emoji[]): Emoji[] {
return []
}

View File

@ -1,8 +1,9 @@
import Database from '../../../src/database/Database'
import {
basicAfterEach, basicBeforeEach, ALL_EMOJI, ALL_EMOJI_MISCONFIGURED_ETAG,
ALL_EMOJI_NO_ETAG, tick, mockFrenchDataSource, FR_EMOJI
ALL_EMOJI_NO_ETAG, tick, mockFrenchDataSource, FR_EMOJI, truncatedEmoji
} from '../shared'
import trimEmojiData from '../../../src/trimEmojiData'
describe('database tests', () => {
beforeEach(basicBeforeEach)
@ -180,4 +181,20 @@ describe('database tests', () => {
await closePromise
await db1.delete()
})
test('basic trimEmojiData test', async () => {
const trimmed = trimEmojiData(truncatedEmoji)
const dataSource = 'trimmed.js'
fetch.get(dataSource, () => new Response(JSON.stringify(trimmed), { headers: { ETag: 'W/trim' } }))
fetch.head(dataSource, () => new Response(null, { headers: { ETag: 'W/trim' } }))
const db = new Database({ dataSource })
const emojis = await db.getEmojiBySearchQuery('face')
expect(emojis.length).toBe(28)
const thumbsUp = await db.getEmojiBySearchQuery('+1')
expect(thumbsUp[0].skins).toHaveLength(5)
const gleeful = await db.getEmojiBySearchQuery('gleeful')
expect(gleeful[0].emoticon).toEqual(':D')
await db.delete()
})
})