Browse Source

Reformat, update versions

master
Joe Attardi 4 years ago
parent
commit
8df244815c
  1. 4
      README.md
  2. 4457
      emoji-test.txt
  3. 10
      index.d.ts
  4. 170
      scripts/processEmojiData.js
  5. 7
      src/emoji.test.ts
  6. 4
      src/emoji.ts
  7. 5
      src/emojiContainer.test.ts
  8. 8
      src/recent.ts
  9. 5
      src/search.ts
  10. 18
      src/types.ts
  11. 22
      src/variantPopup.ts

4
README.md

@ -70,11 +70,13 @@ Creates an Emoji Button emoji picker.
* `autoFocusSearch`: (boolean, default: `true`) Whether or not to auto-focus the search field when the picker is shown.
* `emojiVersion`: (string, default: `'12.1'`) The Emoji version to use. This determines which emojis are available. Supported versions are:
* `0.0`
* `1.0`
* `2.0`
* `3.0`
* `4.0`
* `5.0`
* `11.0`
* `12.0`
* `12.1`
* `position`: The position to display the picker relative to the reference element. Valid values are:

4457
emoji-test.txt

File diff suppressed because it is too large

10
index.d.ts

@ -47,7 +47,15 @@ declare namespace EmojiButton {
| 'left-start'
| 'left-end';
export type EmojiVersion = '0.0' | '2.0' | '4.0' | '5.0' | '11.0' | '12.1';
export type EmojiVersion =
| '1.0'
| '2.0'
| '3.0'
| '4.0'
| '5.0'
| '11.0'
| '12.0'
| '12.1';
export type I18NCategory =
| 'recents'

170
scripts/processEmojiData.js

@ -1,62 +1,142 @@
const { writeFileSync } = require('fs');
const fs = require('fs');
const readline = require('readline');
const rawData = require('emoji-datasource');
function getEmoji(unified) {
const chars = unified.split('-');
const codePoints = chars.map(char => parseInt(char, 16));
return String.fromCodePoint(...codePoints);
}
const DATA_LINE_REGEX = /((?:[0-9A-F]+ ?)+)\s+;.+#.+E([0-9.]+) ([\w\s:,-]+)/;
const EMOJI_WITH_MODIFIER_REGEX = /([a-z]+): ([a-z -]+)/;
const EMOJI_WITH_SKIN_TONE_AND_MODIFIER_REGEX = /([a-z]+): ([a-z -]+), ([a-z ]+)/;
const categoryKeys = {
'Smileys & Emotion': 'smileys',
'People & Body': 'smileys',
'People & Body': 'people',
'Animals & Nature': 'animals',
'Food & Drink': 'food',
Activities: 'activities',
'Travel & Places': 'travel',
Objects: 'objects',
Symbols: 'symbols',
Flags: 'flags',
'Skin Tones': 'skinTones'
'Activities': 'activities',
'Objects': 'objects',
'Symbols': 'symbols',
'Flags': 'flags'
};
const smileysCount = rawData.filter(e => e.category === 'Smileys & Emotion').length;
rawData.filter(e => e.category === 'People & Body').forEach(e => e.sort_order += smileysCount);
const BLACKLIST = [
'light skin tone',
'medium-light skin tone',
'medium skin tone',
'medium-dark skin tone',
'dark skin tone',
'red hair',
'white hair',
'curly hair',
'bald'
];
const categories = [];
const MODIFIER_SUBSTITUTIONS = {
'bald': 'no hair'
};
rawData.sort((e1, e2) => e1.sort_order - e2.sort_order);
const stream = fs.createReadStream('emoji-test.txt');
const newEmojiData = rawData.map(emojiItem => {
let categoryIndex = categories.indexOf(emojiItem.category);
if (categoryIndex < 0) {
categories.push(emojiItem.category);
categoryIndex = categories.length - 1;
}
const interface = readline.createInterface(stream);
let currentGroup;
let currentSubgroup;
let categoryIndex;
const newData = {
n: emojiItem.short_names,
e: getEmoji(emojiItem.unified),
c: categoryIndex,
ver: emojiItem.added_in
};
if (emojiItem.skin_variations) {
newData.v = {};
Object.keys(emojiItem.skin_variations).forEach(variation => {
newData.v[variation] = {
k: `${emojiItem.short_names[0]}-${variation}`,
n: emojiItem.short_names[0],
e: getEmoji(emojiItem.skin_variations[variation].unified)
};
});
const data = {
categories: [],
emoji: []
};
interface.on('line', line => {
if (line.startsWith('# group:')) {
currentGroup = line.slice('# group: '.length);
if (currentGroup !== 'Component') {
data.categories.push(categoryKeys[currentGroup]);
categoryIndex = data.categories.length - 1;
}
} else if (line.startsWith('# subgroup:')) {
currentSubgroup = line.slice('# subgroup: '.length);
} else if (!line.startsWith('#') && currentGroup !== 'Component') {
const matcher = DATA_LINE_REGEX.exec(line);
if (matcher) {
const sequence = matcher[1].trim();
const emoji = getEmoji(sequence);
let name = matcher[3];
let version = matcher[2];
console.log(version);
if (version === '0.6' || version === '0.7') {
version = '1.0';
}
if (currentSubgroup === 'person') {
const modifierMatcher = EMOJI_WITH_MODIFIER_REGEX.exec(name);
const skinToneMatcher = EMOJI_WITH_SKIN_TONE_AND_MODIFIER_REGEX.exec(name);
if (skinToneMatcher) {
name = skinToneMatcher[1] + ' with ' + substituteModifier(skinToneMatcher[3]) + ': ' + skinToneMatcher[2];
} else if (modifierMatcher) {
if (!modifierMatcher[2].includes('skin tone')) {
name = modifierMatcher[1] + ' with ' + substituteModifier(modifierMatcher[2]);
}
}
}
data.emoji.push({ sequence, emoji, category: categoryIndex, name, variations: [], version });
}
}
});
return newData;
interface.on('close', () => {
stream.close();
let toDelete = [];
const emojisWithVariationSelector = data.emoji.filter(emoji => emoji.sequence.includes('FE0F'));
emojisWithVariationSelector.forEach(emoji => {
const baseEmoji = data.emoji.find(e => e.sequence === emoji.sequence.replace(' FE0F', ''));
toDelete.push(baseEmoji);
});
data.emoji = data.emoji.filter(e => !toDelete.includes(e));
toDelete = [];
BLACKLIST.forEach(name => toDelete.push(data.emoji.find(e => e.name === name)));
const emojisWithVariations = data.emoji.filter(emoji => emoji.name.includes(':') && !emoji.name.startsWith('family'));
emojisWithVariations.forEach(emoji => {
const baseName = emoji.name.split(':')[0];
const baseEmoji = data.emoji.find(e => e.name === baseName);
if (baseEmoji) {
baseEmoji.variations.push(emoji.emoji);
toDelete.push(emoji);
}
});
// Cleanup
data.emoji = data.emoji.filter(e => !toDelete.includes(e));
data.emoji.forEach(emoji => {
delete emoji.sequence;
if (!emoji.variations.length) {
delete emoji.variations;
}
});
fs.writeFileSync('emoji.js', `export default ${JSON.stringify(data)}`);
});
writeFileSync(
'src/data/emoji.js',
`export default { categories: ${JSON.stringify(categories.map(category => categoryKeys[category]))}, emojiData: ${JSON.stringify(newEmojiData)}}`
);
function getEmoji(sequence) {
const chars = sequence.split(' ');
const codePoints = chars.map(char => parseInt(char, 16));
return String.fromCodePoint(...codePoints);
}
function substituteModifier(name) {
const substitutions = Object.keys(MODIFIER_SUBSTITUTIONS);
for (let i = 0; i < substitutions.length; i++) {
const substitution = substitutions[i];
if (name.includes(substitution)) {
return name.replace(substitution, MODIFIER_SUBSTITUTIONS[substitution]);
}
}
return name;
}

7
src/emoji.test.ts

@ -6,7 +6,12 @@ import { Emoji } from './emoji';
describe('Emoji', () => {
let events;
const testEmoji = { emoji: '😄', name: 'smile', category: 0, version: '11.0' };
const testEmoji = {
emoji: '😄',
name: 'smile',
category: 0,
version: '11.0'
};
const options = { showRecents: true };
beforeEach(() => (events = new Emitter()));

4
src/emoji.ts

@ -4,7 +4,7 @@ import { EMOJI, HIDE_PREVIEW, SHOW_PREVIEW } from './events';
import { save } from './recent';
import { createElement } from './util';
import { EmojiButtonOptions, EmojiRecord, EmojiVariation } from './types';
import { EmojiButtonOptions, EmojiRecord } from './types';
const CLASS_EMOJI = 'emoji-picker__emoji';
@ -12,7 +12,7 @@ export class Emoji {
private emojiButton: HTMLElement;
constructor(
private emoji: EmojiRecord | EmojiVariation,
private emoji: EmojiRecord,
private showVariants: boolean,
private showPreview: boolean,
private events: Emitter,

5
src/emojiContainer.test.ts

@ -4,7 +4,10 @@ import { EmojiContainer } from './emojiContainer';
describe('EmojiContainer', () => {
test('should render all the given emojis', () => {
const emojis = [{ emoji: '⚡️', version: '12.1' }, { emoji: '👍', version: '12.1' }];
const emojis = [
{ emoji: '⚡️', version: '12.1', name: 'zap', category: 0 },
{ emoji: '👍', version: '12.1', name: 'thumbs up', category: 0 }
];
const events = new Emitter();

8
src/recent.ts

@ -22,10 +22,10 @@ export function save(
localStorage.setItem(
LOCAL_STORAGE_KEY,
JSON.stringify(
[recent, ...recents.filter((r: RecentEmoji) => r.key !== recent.key)].slice(
0,
options.recentsCount
)
[
recent,
...recents.filter((r: RecentEmoji) => r.key !== recent.key)
].slice(0, options.recentsCount)
)
);
}

5
src/search.ts

@ -170,7 +170,10 @@ export class Search {
this.events.emit(HIDE_TABS);
const searchResults = this.emojiData.filter(
emoji => emoji.name.toLowerCase().indexOf(this.searchField.value.toLowerCase()) >= 0
emoji =>
emoji.name
.toLowerCase()
.indexOf(this.searchField.value.toLowerCase()) >= 0
);
this.events.emit(HIDE_PREVIEW);

18
src/types.ts

@ -13,12 +13,6 @@ export interface EmojiData {
emojiData: EmojiRecord[];
}
export interface EmojiVariation {
key: string;
name: string;
emoji: string;
}
export interface RecentEmoji {
key: string;
name: string;
@ -26,7 +20,7 @@ export interface RecentEmoji {
}
export interface EmojiEventData {
emoji: EmojiRecord | EmojiVariation;
emoji: EmojiRecord;
showVariants: boolean;
button: HTMLElement;
}
@ -49,7 +43,15 @@ export interface EmojiButtonOptions {
export type EmojiTheme = 'dark' | 'light' | 'auto';
export type EmojiVersion = '0.0' | '2.0' | '4.0' | '5.0' | '11.0' | '12.1';
export type EmojiVersion =
| '1.0'
| '2.0'
| '3.0'
| '4.0'
| '5.0'
| '11.0'
| '12.0'
| '12.1';
export type I18NCategory =
| 'recents'

22
src/variantPopup.ts

@ -6,7 +6,7 @@ import { createElement } from './util';
import { HIDE_VARIANT_POPUP } from './events';
import { times } from './icons';
import { EmojiRecord, EmojiButtonOptions, EmojiVariation } from './types';
import { EmojiRecord, EmojiButtonOptions } from './types';
const CLASS_OVERLAY = 'emoji-picker__variant-overlay';
const CLASS_POPUP = 'emoji-picker__variant-popup';
@ -56,11 +56,21 @@ export class VariantPopup {
new Emoji(this.emoji, false, false, this.events, this.options).render()
);
(this.emoji.variations || []).forEach((variation, index) => this.popup.appendChild(new Emoji({
name: this.emoji.name,
emoji: variation,
key: this.emoji.name + index
}, false, false, this.events, this.options).render()));
(this.emoji.variations || []).forEach((variation, index) =>
this.popup.appendChild(
new Emoji(
{
name: this.emoji.name,
emoji: variation,
key: this.emoji.name + index
},
false,
false,
this.events,
this.options
).render()
)
);
const firstEmoji = this.popup.querySelector(
'.emoji-picker__emoji'

Loading…
Cancel
Save