Consume @matrix-org/emojibase-bindings (#11433)
This commit is contained in:
parent
4e4016dffc
commit
d4571aef68
11 changed files with 22 additions and 136 deletions
|
@ -29,6 +29,7 @@ import { Optional } from "matrix-events-sdk";
|
|||
import _Linkify from "linkify-react";
|
||||
import escapeHtml from "escape-html";
|
||||
import GraphemeSplitter from "graphemer";
|
||||
import { getEmojiFromUnicode } from "@matrix-org/emojibase-bindings";
|
||||
|
||||
import {
|
||||
_linkifyElement,
|
||||
|
@ -39,7 +40,6 @@ import {
|
|||
import { IExtendedSanitizeOptions } from "./@types/sanitize-html";
|
||||
import SettingsStore from "./settings/SettingsStore";
|
||||
import { tryTransformPermalinkToLocalHref } from "./utils/permalinks/Permalinks";
|
||||
import { getEmojiFromUnicode } from "./emoji";
|
||||
import { mediaFromMxc } from "./customisations/Media";
|
||||
import { stripHTMLReply, stripPlainReply } from "./utils/Reply";
|
||||
import { PERMITTED_URL_SCHEMES } from "./utils/UrlUtils";
|
||||
|
|
|
@ -22,6 +22,7 @@ import React from "react";
|
|||
import { uniq, sortBy, uniqBy, ListIteratee } from "lodash";
|
||||
import EMOTICON_REGEX from "emojibase-regex/emoticon";
|
||||
import { Room } from "matrix-js-sdk/src/matrix";
|
||||
import { EMOJI, Emoji, getEmojiFromUnicode } from "@matrix-org/emojibase-bindings";
|
||||
|
||||
import { _t } from "../languageHandler";
|
||||
import AutocompleteProvider from "./AutocompleteProvider";
|
||||
|
@ -29,7 +30,6 @@ import QueryMatcher from "./QueryMatcher";
|
|||
import { PillCompletion } from "./Components";
|
||||
import { ICompletion, ISelectionRange } from "./Autocompleter";
|
||||
import SettingsStore from "../settings/SettingsStore";
|
||||
import { EMOJI, IEmoji, getEmojiFromUnicode } from "../emoji";
|
||||
import { TimelineRenderingType } from "../contexts/RoomContext";
|
||||
import * as recent from "../emojipicker/recent";
|
||||
import { filterBoolean } from "../utils/arrays";
|
||||
|
@ -41,7 +41,7 @@ const LIMIT = 20;
|
|||
const EMOJI_REGEX = new RegExp("(" + EMOTICON_REGEX.source + "|(?:^|\\s):[+-\\w]*:?)$", "g");
|
||||
|
||||
interface ISortedEmoji {
|
||||
emoji: IEmoji;
|
||||
emoji: Emoji;
|
||||
_orderBy: number;
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ function colonsTrimmed(str: string): string {
|
|||
export default class EmojiProvider extends AutocompleteProvider {
|
||||
public matcher: QueryMatcher<ISortedEmoji>;
|
||||
public nameMatcher: QueryMatcher<ISortedEmoji>;
|
||||
private readonly recentlyUsed: IEmoji[];
|
||||
private readonly recentlyUsed: Emoji[];
|
||||
|
||||
public constructor(room: Room, renderingType?: TimelineRenderingType) {
|
||||
super({ commandRegex: EMOJI_REGEX, renderingType });
|
||||
|
|
|
@ -16,10 +16,10 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React, { RefObject } from "react";
|
||||
import { DATA_BY_CATEGORY, Emoji as IEmoji } from "@matrix-org/emojibase-bindings";
|
||||
|
||||
import { CATEGORY_HEADER_HEIGHT, EMOJI_HEIGHT, EMOJIS_PER_ROW } from "./EmojiPicker";
|
||||
import LazyRenderList from "../elements/LazyRenderList";
|
||||
import { DATA_BY_CATEGORY, IEmoji } from "../../../emoji";
|
||||
import Emoji from "./Emoji";
|
||||
import { ButtonEvent } from "../elements/AccessibleButton";
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from "react";
|
||||
import { Emoji as IEmoji } from "@matrix-org/emojibase-bindings";
|
||||
|
||||
import { IEmoji } from "../../../emoji";
|
||||
import { ButtonEvent } from "../elements/AccessibleButton";
|
||||
import { RovingAccessibleButton } from "../../../accessibility/RovingTabIndex";
|
||||
|
||||
|
|
|
@ -16,10 +16,10 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React, { Dispatch } from "react";
|
||||
import { DATA_BY_CATEGORY, getEmojiFromUnicode, Emoji as IEmoji } from "@matrix-org/emojibase-bindings";
|
||||
|
||||
import { _t } from "../../../languageHandler";
|
||||
import * as recent from "../../../emojipicker/recent";
|
||||
import { DATA_BY_CATEGORY, getEmojiFromUnicode, IEmoji } from "../../../emoji";
|
||||
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
|
||||
import Header from "./Header";
|
||||
import Search from "./Search";
|
||||
|
|
|
@ -16,11 +16,10 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from "react";
|
||||
|
||||
import { IEmoji } from "../../../emoji";
|
||||
import { Emoji } from "@matrix-org/emojibase-bindings";
|
||||
|
||||
interface IProps {
|
||||
emoji: IEmoji;
|
||||
emoji: Emoji;
|
||||
}
|
||||
|
||||
class Preview extends React.PureComponent<IProps> {
|
||||
|
|
|
@ -16,9 +16,9 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from "react";
|
||||
import { getEmojiFromUnicode, Emoji as IEmoji } from "@matrix-org/emojibase-bindings";
|
||||
|
||||
import { _t } from "../../../languageHandler";
|
||||
import { getEmojiFromUnicode, IEmoji } from "../../../emoji";
|
||||
import Emoji from "./Emoji";
|
||||
import { ButtonEvent } from "../elements/AccessibleButton";
|
||||
import Toolbar from "../../../accessibility/Toolbar";
|
||||
|
|
|
@ -19,6 +19,7 @@ import React, { createRef, ClipboardEvent, SyntheticEvent } from "react";
|
|||
import { Room, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||
import EMOTICON_REGEX from "emojibase-regex/emoticon";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { EMOTICON_TO_EMOJI } from "@matrix-org/emojibase-bindings";
|
||||
|
||||
import EditorModel from "../../../editor/model";
|
||||
import HistoryManager from "../../../editor/history";
|
||||
|
@ -36,7 +37,6 @@ import { parseEvent, parsePlainTextMessage } from "../../../editor/deserialize";
|
|||
import { renderModel } from "../../../editor/render";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import { IS_MAC, Key } from "../../../Keyboard";
|
||||
import { EMOTICON_TO_EMOJI } from "../../../emoji";
|
||||
import { CommandCategories, CommandMap, parseCommandString } from "../../../SlashCommands";
|
||||
import Range from "../../../editor/range";
|
||||
import MessageComposerFormatBar, { Formatting } from "./MessageComposerFormatBar";
|
||||
|
|
120
src/emoji.ts
120
src/emoji.ts
|
@ -1,120 +0,0 @@
|
|||
/*
|
||||
Copyright 2019 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import EMOJIBASE from "emojibase-data/en/compact.json";
|
||||
import SHORTCODES from "emojibase-data/en/shortcodes/iamcal.json";
|
||||
import { CompactEmoji } from "emojibase";
|
||||
|
||||
export interface IEmoji extends Omit<CompactEmoji, "shortcodes"> {
|
||||
// We generate a shortcode based on the label if none exist in the dataset
|
||||
shortcodes: string[];
|
||||
}
|
||||
|
||||
// The unicode is stored without the variant selector
|
||||
const UNICODE_TO_EMOJI = new Map<string, IEmoji>(); // not exported as gets for it are handled by getEmojiFromUnicode
|
||||
export const EMOTICON_TO_EMOJI = new Map<string, IEmoji>();
|
||||
|
||||
export const getEmojiFromUnicode = (unicode: string): IEmoji | undefined =>
|
||||
UNICODE_TO_EMOJI.get(stripVariation(unicode));
|
||||
|
||||
const isRegionalIndicator = (x: string): boolean => {
|
||||
// First verify that the string is a single character. We use Array.from
|
||||
// to make sure we count by characters, not UTF-8 code units.
|
||||
return (
|
||||
Array.from(x).length === 1 &&
|
||||
// Next verify that the character is within the code point range for
|
||||
// regional indicators.
|
||||
// http://unicode.org/charts/PDF/Unicode-6.0/U60-1F100.pdf
|
||||
x >= "\u{1f1e6}" &&
|
||||
x <= "\u{1f1ff}"
|
||||
);
|
||||
};
|
||||
|
||||
const EMOJIBASE_GROUP_ID_TO_CATEGORY = [
|
||||
"people", // smileys
|
||||
"people", // actually people
|
||||
"control", // modifiers and such, not displayed in picker
|
||||
"nature",
|
||||
"foods",
|
||||
"places",
|
||||
"activity",
|
||||
"objects",
|
||||
"symbols",
|
||||
"flags",
|
||||
];
|
||||
|
||||
export const DATA_BY_CATEGORY: Record<string, IEmoji[]> = {
|
||||
people: [],
|
||||
nature: [],
|
||||
foods: [],
|
||||
places: [],
|
||||
activity: [],
|
||||
objects: [],
|
||||
symbols: [],
|
||||
flags: [],
|
||||
};
|
||||
|
||||
// Store various mappings from unicode/emoticon/shortcode to the Emoji objects
|
||||
export const EMOJI: IEmoji[] = EMOJIBASE.map((emojiData) => {
|
||||
// If there's ever a gap in shortcode coverage, we fudge it by
|
||||
// filling it in with the emoji's CLDR annotation
|
||||
const shortcodeData = SHORTCODES[emojiData.hexcode] ?? [emojiData.label.toLowerCase().replace(/\W+/g, "_")];
|
||||
|
||||
const emoji: IEmoji = {
|
||||
...emojiData,
|
||||
// Homogenize shortcodes by ensuring that everything is an array
|
||||
shortcodes: typeof shortcodeData === "string" ? [shortcodeData] : shortcodeData,
|
||||
};
|
||||
|
||||
// We manually include regional indicators in the symbols group, since
|
||||
// Emojibase intentionally leaves them uncategorized
|
||||
const categoryId =
|
||||
EMOJIBASE_GROUP_ID_TO_CATEGORY[emoji.group!] ?? (isRegionalIndicator(emoji.unicode) ? "symbols" : null);
|
||||
|
||||
if (DATA_BY_CATEGORY.hasOwnProperty(categoryId)) {
|
||||
DATA_BY_CATEGORY[categoryId].push(emoji);
|
||||
}
|
||||
|
||||
// Add mapping from unicode to Emoji object
|
||||
// The 'unicode' field that we use in emojibase has either
|
||||
// VS15 or VS16 appended to any characters that can take
|
||||
// variation selectors. Which one it appends depends
|
||||
// on whether emojibase considers their type to be 'text' or
|
||||
// 'emoji'. We therefore strip any variation chars from strings
|
||||
// both when building the map and when looking up.
|
||||
UNICODE_TO_EMOJI.set(stripVariation(emoji.unicode), emoji);
|
||||
|
||||
if (emoji.emoticon) {
|
||||
// Add mapping from emoticon to Emoji object
|
||||
Array.isArray(emoji.emoticon)
|
||||
? emoji.emoticon.forEach((x) => EMOTICON_TO_EMOJI.set(x, emoji))
|
||||
: EMOTICON_TO_EMOJI.set(emoji.emoticon, emoji);
|
||||
}
|
||||
|
||||
return emoji;
|
||||
});
|
||||
|
||||
/**
|
||||
* Strips variation selectors from the end of given string
|
||||
* NB. Skin tone modifiers are not variation selectors:
|
||||
* this function does not touch them. (Should it?)
|
||||
*
|
||||
* @param {string} str string to strip
|
||||
* @returns {string} stripped string
|
||||
*/
|
||||
function stripVariation(str: string): string {
|
||||
return str.replace(/[\uFE00-\uFE0F]$/, "");
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue