Implement ascii emoji tab completion

When a fully plaintext, ascii emoji is typed like ";-)", pressing tab will suggest emojione to replace it with based off of the meta data provided by emojione.

e.g. the aliases_ascii for `😃` are [":D",":-D","=D"] so typing ":D *tab*" will insert a real 😃
pull/21833/head
Luke Barnard 2017-06-29 11:29:55 +01:00
parent 8912400675
commit 982b009b90
4 changed files with 29 additions and 8 deletions

View File

@ -5,13 +5,17 @@ const fs = require('fs');
const output = Object.keys(EMOJI_DATA).map( const output = Object.keys(EMOJI_DATA).map(
(key) => { (key) => {
const datum = EMOJI_DATA[key]; const datum = EMOJI_DATA[key];
return { const newDatum = {
name: datum.name, name: datum.name,
shortname: datum.shortname, shortname: datum.shortname,
category: datum.category, category: datum.category,
emoji_order: datum.emoji_order, emoji_order: datum.emoji_order,
}; };
}, if (datum.aliases_ascii.length > 0) {
newDatum.aliases_ascii = datum.aliases_ascii;
}
return newDatum;
}
); );
// Write to a file in src. Changes should be checked into git. This file is copied by // Write to a file in src. Changes should be checked into git. This file is copied by

View File

@ -18,7 +18,7 @@ limitations under the License.
import React from 'react'; import React from 'react';
import { _t } from '../languageHandler'; import { _t } from '../languageHandler';
import AutocompleteProvider from './AutocompleteProvider'; import AutocompleteProvider from './AutocompleteProvider';
import {emojioneList, shortnameToImage, shortnameToUnicode} from 'emojione'; import {emojioneList, shortnameToImage, shortnameToUnicode, asciiRegexp} from 'emojione';
import FuzzyMatcher from './FuzzyMatcher'; import FuzzyMatcher from './FuzzyMatcher';
import sdk from '../index'; import sdk from '../index';
import {PillCompletion} from './Components'; import {PillCompletion} from './Components';
@ -40,7 +40,8 @@ const CATEGORY_ORDER = [
'modifier', 'modifier',
]; ];
const EMOJI_REGEX = /:\w*:?/g; // Match for ":wink:" or ascii-style ";-)" provided by emojione
const EMOJI_REGEX = new RegExp('(:\\w*:?|' + asciiRegexp + ')', 'g');
const EMOJI_SHORTNAMES = Object.keys(EmojiData).map((key) => EmojiData[key]).sort( const EMOJI_SHORTNAMES = Object.keys(EmojiData).map((key) => EmojiData[key]).sort(
(a, b) => { (a, b) => {
if (a.category === b.category) { if (a.category === b.category) {
@ -52,6 +53,7 @@ const EMOJI_SHORTNAMES = Object.keys(EmojiData).map((key) => EmojiData[key]).sor
return { return {
name: a.name, name: a.name,
shortname: a.shortname, shortname: a.shortname,
aliases_ascii: a.aliases_ascii ? a.aliases_ascii.join(' ') : '',
}; };
}); });
@ -61,7 +63,9 @@ export default class EmojiProvider extends AutocompleteProvider {
constructor() { constructor() {
super(EMOJI_REGEX); super(EMOJI_REGEX);
this.matcher = new FuzzyMatcher(EMOJI_SHORTNAMES, { this.matcher = new FuzzyMatcher(EMOJI_SHORTNAMES, {
keys: ['shortname', 'name'], keys: ['aliases_ascii', 'shortname', 'name'],
// For matching against ascii equivalents
shouldMatchWordsOnly: false,
}); });
} }

View File

@ -63,6 +63,12 @@ export default class QueryMatcher {
this.options = options; this.options = options;
this.keys = options.keys; this.keys = options.keys;
this.setObjects(objects); this.setObjects(objects);
// By default, we remove any non-alphanumeric characters ([^A-Za-z0-9_]) from the
// query and the value being queried before matching
if (this.options.shouldMatchWordsOnly === undefined) {
this.options.shouldMatchWordsOnly = true;
}
} }
setObjects(objects: Array<Object>) { setObjects(objects: Array<Object>) {
@ -70,9 +76,16 @@ export default class QueryMatcher {
} }
match(query: String): Array<Object> { match(query: String): Array<Object> {
query = query.toLowerCase().replace(/[^\w]/g, ''); query = query.toLowerCase();
if (this.options.shouldMatchWordsOnly) {
query = query.replace(/[^\w]/g, '');
}
const results = _sortedUniq(_sortBy(_flatMap(this.keyMap.keys, (key) => { const results = _sortedUniq(_sortBy(_flatMap(this.keyMap.keys, (key) => {
return key.toLowerCase().replace(/[^\w]/g, '').indexOf(query) >= 0 ? this.keyMap.objectMap[key] : []; let resultKey = key.toLowerCase();
if (this.options.shouldMatchWordsOnly) {
resultKey = resultKey.replace(/[^\w]/g, '');
}
return resultKey.indexOf(query) !== -1 ? this.keyMap.objectMap[key] : [];
}), (candidate) => this.keyMap.priorityMap.get(candidate))); }), (candidate) => this.keyMap.priorityMap.get(candidate)));
return results; return results;
} }

File diff suppressed because one or more lines are too long