From 4f337b9804118e795d785175395c49f9988e6c75 Mon Sep 17 00:00:00 2001 From: taichi221228 Date: Thu, 2 Nov 2023 17:30:27 +0900 Subject: [PATCH 01/17] Rename emoji_utils.js to TS --- .../emoji/{emoji_utils.js => emoji_utils.ts} | 96 +++++++++++-------- 1 file changed, 54 insertions(+), 42 deletions(-) rename app/javascript/mastodon/features/emoji/{emoji_utils.js => emoji_utils.ts} (72%) diff --git a/app/javascript/mastodon/features/emoji/emoji_utils.js b/app/javascript/mastodon/features/emoji/emoji_utils.ts similarity index 72% rename from app/javascript/mastodon/features/emoji/emoji_utils.js rename to app/javascript/mastodon/features/emoji/emoji_utils.ts index c13d2505670..9ff12308d07 100644 --- a/app/javascript/mastodon/features/emoji/emoji_utils.js +++ b/app/javascript/mastodon/features/emoji/emoji_utils.ts @@ -1,6 +1,9 @@ // This code is largely borrowed from: // https://github.com/missive/emoji-mart/blob/5f2ffcc/src/utils/index.js +/* eslint-disable */ +// @ts-nocheck + import * as data from './emoji_mart_data_light'; const buildSearch = (data) => { @@ -32,52 +35,52 @@ const buildSearch = (data) => { const _String = String; -const stringFromCodePoint = _String.fromCodePoint || function () { - let MAX_SIZE = 0x4000; - let codeUnits = []; - let highSurrogate; - let lowSurrogate; - let index = -1; - let length = arguments.length; - if (!length) { - return ''; - } - let result = ''; - while (++index < length) { - let codePoint = Number(arguments[index]); - if ( - !isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity` - codePoint < 0 || // not a valid Unicode code point - codePoint > 0x10FFFF || // not a valid Unicode code point - Math.floor(codePoint) !== codePoint // not an integer - ) { - throw RangeError('Invalid code point: ' + codePoint); +const stringFromCodePoint = + _String.fromCodePoint || + function () { + let MAX_SIZE = 0x4000; + let codeUnits = []; + let highSurrogate; + let lowSurrogate; + let index = -1; + let length = arguments.length; + if (!length) { + return ''; } - if (codePoint <= 0xFFFF) { // BMP code point - codeUnits.push(codePoint); - } else { // Astral code point; split in surrogate halves - // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae - codePoint -= 0x10000; - highSurrogate = (codePoint >> 10) + 0xD800; - lowSurrogate = (codePoint % 0x400) + 0xDC00; - codeUnits.push(highSurrogate, lowSurrogate); + let result = ''; + while (++index < length) { + let codePoint = Number(arguments[index]); + if ( + !isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity` + codePoint < 0 || // not a valid Unicode code point + codePoint > 0x10ffff || // not a valid Unicode code point + Math.floor(codePoint) !== codePoint // not an integer + ) { + throw RangeError('Invalid code point: ' + codePoint); + } + if (codePoint <= 0xffff) { + // BMP code point + codeUnits.push(codePoint); + } else { + // Astral code point; split in surrogate halves + // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + codePoint -= 0x10000; + highSurrogate = (codePoint >> 10) + 0xd800; + lowSurrogate = (codePoint % 0x400) + 0xdc00; + codeUnits.push(highSurrogate, lowSurrogate); + } + if (index + 1 === length || codeUnits.length > MAX_SIZE) { + result += String.fromCharCode.apply(null, codeUnits); + codeUnits.length = 0; + } } - if (index + 1 === length || codeUnits.length > MAX_SIZE) { - result += String.fromCharCode.apply(null, codeUnits); - codeUnits.length = 0; - } - } - return result; -}; - + return result; + }; const _JSON = JSON; const COLONS_REGEX = /^(?::([^:]+):)(?::skin-tone-(\d):)?$/; -const SKINS = [ - '1F3FA', '1F3FB', '1F3FC', - '1F3FD', '1F3FE', '1F3FF', -]; +const SKINS = ['1F3FA', '1F3FB', '1F3FC', '1F3FD', '1F3FE', '1F3FF']; function unifiedToNative(unified) { let unicodes = unified.split('-'), @@ -87,7 +90,16 @@ function unifiedToNative(unified) { } function sanitize(emoji) { - let { name, short_names, skin_tone, skin_variations, emoticons, unified, custom, imageUrl } = emoji, + let { + name, + short_names, + skin_tone, + skin_variations, + emoticons, + unified, + custom, + imageUrl, + } = emoji, id = emoji.id || short_names[0], colons = `:${id}:`; @@ -206,7 +218,7 @@ function intersect(a, b) { const uniqA = uniq(a); const uniqB = uniq(b); - return uniqA.filter(item => uniqB.indexOf(item) >= 0); + return uniqA.filter((item) => uniqB.indexOf(item) >= 0); } function deepMerge(a, b) { From 6d873032de0fb6d77ef1793bf6b8e1f9b3e83ed9 Mon Sep 17 00:00:00 2001 From: taichi221228 Date: Wed, 24 Apr 2024 09:53:56 +0900 Subject: [PATCH 02/17] Add '@ts-expect-error' to suppress TypeScript errors --- .../mastodon/features/emoji/emoji_utils.ts | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/app/javascript/mastodon/features/emoji/emoji_utils.ts b/app/javascript/mastodon/features/emoji/emoji_utils.ts index 9ff12308d07..43e9ef01f7b 100644 --- a/app/javascript/mastodon/features/emoji/emoji_utils.ts +++ b/app/javascript/mastodon/features/emoji/emoji_utils.ts @@ -2,22 +2,26 @@ // https://github.com/missive/emoji-mart/blob/5f2ffcc/src/utils/index.js /* eslint-disable */ -// @ts-nocheck import * as data from './emoji_mart_data_light'; +// @ts-expect-error const buildSearch = (data) => { + // @ts-expect-error const search = []; + // @ts-expect-error let addToSearch = (strings, split) => { if (!strings) { return; } (Array.isArray(strings) ? strings : [strings]).forEach((string) => { + // @ts-expect-error (split ? string.split(/[-|_|\s]+/) : [string]).forEach((s) => { s = s.toLowerCase(); + // @ts-expect-error if (search.indexOf(s) === -1) { search.push(s); } @@ -30,6 +34,7 @@ const buildSearch = (data) => { addToSearch(data.keywords, false); addToSearch(data.emoticons, false); + // @ts-expect-error return search.join(','); }; @@ -82,13 +87,16 @@ const _JSON = JSON; const COLONS_REGEX = /^(?::([^:]+):)(?::skin-tone-(\d):)?$/; const SKINS = ['1F3FA', '1F3FB', '1F3FC', '1F3FD', '1F3FE', '1F3FF']; +// @ts-expect-error function unifiedToNative(unified) { let unicodes = unified.split('-'), + // @ts-expect-error codePoints = unicodes.map((u) => `0x${u}`); return stringFromCodePoint.apply(null, codePoints); } +// @ts-expect-error function sanitize(emoji) { let { name, @@ -130,9 +138,11 @@ function sanitize(emoji) { } function getSanitizedData() { + // @ts-expect-error return sanitize(getData(...arguments)); } +// @ts-expect-error function getData(emoji, skin, set) { let emojiData = {}; @@ -167,45 +177,60 @@ function getData(emoji, skin, set) { if (!Object.keys(emojiData).length) { emojiData = emoji; + // @ts-expect-error emojiData.custom = true; + // @ts-expect-error if (!emojiData.search) { + // @ts-expect-error emojiData.search = buildSearch(emoji); } } + // @ts-expect-error emojiData.emoticons = emojiData.emoticons || []; + // @ts-expect-error emojiData.variations = emojiData.variations || []; + // @ts-expect-error if (emojiData.skin_variations && skin > 1 && set) { emojiData = JSON.parse(_JSON.stringify(emojiData)); let skinKey = SKINS[skin - 1], + // @ts-expect-error variationData = emojiData.skin_variations[skinKey]; + // @ts-expect-error if (!variationData.variations && emojiData.variations) { + // @ts-expect-error delete emojiData.variations; } if (variationData[`has_img_${set}`]) { + // @ts-expect-error emojiData.skin_tone = skin; for (let k in variationData) { let v = variationData[k]; + // @ts-expect-error emojiData[k] = v; } } } + // @ts-expect-error if (emojiData.variations && emojiData.variations.length) { emojiData = JSON.parse(_JSON.stringify(emojiData)); + // @ts-expect-error emojiData.unified = emojiData.variations.shift(); } return emojiData; } +// @ts-expect-error function uniq(arr) { + // @ts-expect-error return arr.reduce((acc, item) => { if (acc.indexOf(item) === -1) { acc.push(item); @@ -214,13 +239,16 @@ function uniq(arr) { }, []); } +// @ts-expect-error function intersect(a, b) { const uniqA = uniq(a); const uniqB = uniq(b); + // @ts-expect-error return uniqA.filter((item) => uniqB.indexOf(item) >= 0); } +// @ts-expect-error function deepMerge(a, b) { let o = {}; @@ -236,6 +264,7 @@ function deepMerge(a, b) { value = deepMerge(originalValue, value); } + // @ts-expect-error o[key] = value; } From 47b82ee7c82937e9fca5c2e97304bc237035e4c4 Mon Sep 17 00:00:00 2001 From: taichi221228 Date: Wed, 24 Apr 2024 09:55:00 +0900 Subject: [PATCH 03/17] Refactor buildSearch function in emoji_utils.ts The buildSearch function has been refactored for better coding practices. More explicit typings and declaration were used, and the logic related to array search has been simplified for better readability. The 'eslint-disable' comment line was moved to a more appropriate location after these changes. --- .../mastodon/features/emoji/emoji_utils.ts | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/app/javascript/mastodon/features/emoji/emoji_utils.ts b/app/javascript/mastodon/features/emoji/emoji_utils.ts index 43e9ef01f7b..bdb8e301dec 100644 --- a/app/javascript/mastodon/features/emoji/emoji_utils.ts +++ b/app/javascript/mastodon/features/emoji/emoji_utils.ts @@ -1,28 +1,25 @@ // This code is largely borrowed from: // https://github.com/missive/emoji-mart/blob/5f2ffcc/src/utils/index.js -/* eslint-disable */ +import type { Emoji } from 'emoji-mart/dist-es/utils/data'; import * as data from './emoji_mart_data_light'; -// @ts-expect-error -const buildSearch = (data) => { - // @ts-expect-error - const search = []; +type Data = Pick; - // @ts-expect-error - let addToSearch = (strings, split) => { +const buildSearch = (data: Data) => { + const search: string[] = []; + + const addToSearch = (strings: Data[keyof Data], split: boolean) => { if (!strings) { return; } (Array.isArray(strings) ? strings : [strings]).forEach((string) => { - // @ts-expect-error (split ? string.split(/[-|_|\s]+/) : [string]).forEach((s) => { s = s.toLowerCase(); - // @ts-expect-error - if (search.indexOf(s) === -1) { + if (!search.includes(s)) { search.push(s); } }); @@ -34,10 +31,11 @@ const buildSearch = (data) => { addToSearch(data.keywords, false); addToSearch(data.emoticons, false); - // @ts-expect-error return search.join(','); }; +/* eslint-disable */ + const _String = String; const stringFromCodePoint = From 1c4cf654d7fbc5246220563a49749049b46e76ee Mon Sep 17 00:00:00 2001 From: taichi221228 Date: Wed, 24 Apr 2024 10:00:13 +0900 Subject: [PATCH 04/17] Remove unnecessary stringFromCodePoint function polyfill in emoji_utils Removed the unnecessary stringFromCodePoint function polyfill from the emoji_utils.ts file. Instead, we use the built-in JavaScript function String.fromCodePoint to simplify the code. --- .../mastodon/features/emoji/emoji_utils.ts | 46 +------------------ 1 file changed, 1 insertion(+), 45 deletions(-) diff --git a/app/javascript/mastodon/features/emoji/emoji_utils.ts b/app/javascript/mastodon/features/emoji/emoji_utils.ts index bdb8e301dec..e1c8bbda084 100644 --- a/app/javascript/mastodon/features/emoji/emoji_utils.ts +++ b/app/javascript/mastodon/features/emoji/emoji_utils.ts @@ -36,50 +36,6 @@ const buildSearch = (data: Data) => { /* eslint-disable */ -const _String = String; - -const stringFromCodePoint = - _String.fromCodePoint || - function () { - let MAX_SIZE = 0x4000; - let codeUnits = []; - let highSurrogate; - let lowSurrogate; - let index = -1; - let length = arguments.length; - if (!length) { - return ''; - } - let result = ''; - while (++index < length) { - let codePoint = Number(arguments[index]); - if ( - !isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity` - codePoint < 0 || // not a valid Unicode code point - codePoint > 0x10ffff || // not a valid Unicode code point - Math.floor(codePoint) !== codePoint // not an integer - ) { - throw RangeError('Invalid code point: ' + codePoint); - } - if (codePoint <= 0xffff) { - // BMP code point - codeUnits.push(codePoint); - } else { - // Astral code point; split in surrogate halves - // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae - codePoint -= 0x10000; - highSurrogate = (codePoint >> 10) + 0xd800; - lowSurrogate = (codePoint % 0x400) + 0xdc00; - codeUnits.push(highSurrogate, lowSurrogate); - } - if (index + 1 === length || codeUnits.length > MAX_SIZE) { - result += String.fromCharCode.apply(null, codeUnits); - codeUnits.length = 0; - } - } - return result; - }; - const _JSON = JSON; const COLONS_REGEX = /^(?::([^:]+):)(?::skin-tone-(\d):)?$/; @@ -91,7 +47,7 @@ function unifiedToNative(unified) { // @ts-expect-error codePoints = unicodes.map((u) => `0x${u}`); - return stringFromCodePoint.apply(null, codePoints); + return String.fromCodePoint(...codePoints); } // @ts-expect-error From 3c7ccb2e622f176d5ae66c6f0d447a17ad73cb00 Mon Sep 17 00:00:00 2001 From: taichi221228 Date: Wed, 24 Apr 2024 10:01:27 +0900 Subject: [PATCH 05/17] Refactor unifiedToNative function in emoji_utils The unifiedToNative function in emoji_utils.ts has been refactored for cleaner coding practices. Lint disabling has been moved to a different part of the code, and type checking has been revised to specify that the input unified is of type Emoji['unified']. The function's variables have been updated to const for better securities against undesired changes. --- .../mastodon/features/emoji/emoji_utils.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/app/javascript/mastodon/features/emoji/emoji_utils.ts b/app/javascript/mastodon/features/emoji/emoji_utils.ts index e1c8bbda084..3dc193b2abb 100644 --- a/app/javascript/mastodon/features/emoji/emoji_utils.ts +++ b/app/javascript/mastodon/features/emoji/emoji_utils.ts @@ -34,22 +34,20 @@ const buildSearch = (data: Data) => { return search.join(','); }; -/* eslint-disable */ - const _JSON = JSON; const COLONS_REGEX = /^(?::([^:]+):)(?::skin-tone-(\d):)?$/; const SKINS = ['1F3FA', '1F3FB', '1F3FC', '1F3FD', '1F3FE', '1F3FF']; -// @ts-expect-error -function unifiedToNative(unified) { - let unicodes = unified.split('-'), - // @ts-expect-error - codePoints = unicodes.map((u) => `0x${u}`); +function unifiedToNative(unified: Emoji['unified']) { + const unicodes = unified?.split('-') ?? []; + const codePoints = unicodes.map((u) => +`0x${u}`); return String.fromCodePoint(...codePoints); } +/* eslint-disable */ + // @ts-expect-error function sanitize(emoji) { let { From 2236a16d55fb0803aae90aba5916bd2a65e8b49b Mon Sep 17 00:00:00 2001 From: taichi221228 Date: Wed, 24 Apr 2024 10:04:33 +0900 Subject: [PATCH 06/17] Refactor and improve emoji sanitization function The emoji sanitization function has been refactored for better handling of emoji variations. New types have been imported from 'emoji-mart', allowing for a more precise type assignment for the emoji input and output. Bound checking operations have been adjusted to better accommodate and handle custom emojis and skin variations. --- .../mastodon/features/emoji/emoji_utils.ts | 45 ++++++++++++------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/app/javascript/mastodon/features/emoji/emoji_utils.ts b/app/javascript/mastodon/features/emoji/emoji_utils.ts index 3dc193b2abb..a4b93d1a82b 100644 --- a/app/javascript/mastodon/features/emoji/emoji_utils.ts +++ b/app/javascript/mastodon/features/emoji/emoji_utils.ts @@ -1,6 +1,12 @@ // This code is largely borrowed from: // https://github.com/missive/emoji-mart/blob/5f2ffcc/src/utils/index.js +import type { + BaseEmoji, + CustomEmoji, + EmojiSkin, + PickerProps, +} from 'emoji-mart'; import type { Emoji } from 'emoji-mart/dist-es/utils/data'; import * as data from './emoji_mart_data_light'; @@ -46,22 +52,27 @@ function unifiedToNative(unified: Emoji['unified']) { return String.fromCodePoint(...codePoints); } -/* eslint-disable */ +function sanitize( + emoji: BaseEmoji & + CustomEmoji & + Pick & + Pick & { skin_tone?: EmojiSkin }, +): + | BaseEmoji + | (Omit & Pick) { + const { + name = '', + short_names = [], + skin_tone, + skin_variations, + emoticons = [], + unified = '', + custom, + imageUrl, + } = emoji; + const id = emoji.id || short_names[0]; -// @ts-expect-error -function sanitize(emoji) { - let { - name, - short_names, - skin_tone, - skin_variations, - emoticons, - unified, - custom, - imageUrl, - } = emoji, - id = emoji.id || short_names[0], - colons = `:${id}:`; + let colons = `:${id}:`; if (custom) { return { @@ -84,11 +95,13 @@ function sanitize(emoji) { colons, emoticons, unified: unified.toLowerCase(), - skin: skin_tone || (skin_variations ? 1 : null), + skin: skin_tone ?? (skin_variations ? 1 : null), native: unifiedToNative(unified), }; } +/* eslint-disable */ + function getSanitizedData() { // @ts-expect-error return sanitize(getData(...arguments)); From a603a353d40937f81149ca0734887fe0fd554676 Mon Sep 17 00:00:00 2001 From: taichi221228 Date: Wed, 24 Apr 2024 10:22:32 +0900 Subject: [PATCH 07/17] Add comments for `skin_tone` in emoji_utils.ts This commit adds detailed comments explaining the usage of `skin_tone` in emoji_utils.ts, noting its absence in the type definition link and the need for a separate type with DefinitelyTyped. It also highlights potential mismatch issues between versions of `@types/emoji-mart` and `emoji-mart`, given they have different maintainers and packages. --- app/javascript/mastodon/features/emoji/emoji_utils.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/javascript/mastodon/features/emoji/emoji_utils.ts b/app/javascript/mastodon/features/emoji/emoji_utils.ts index a4b93d1a82b..98d8e9f3207 100644 --- a/app/javascript/mastodon/features/emoji/emoji_utils.ts +++ b/app/javascript/mastodon/features/emoji/emoji_utils.ts @@ -52,6 +52,12 @@ function unifiedToNative(unified: Emoji['unified']) { return String.fromCodePoint(...codePoints); } +/* + * `skin_tone` is used [here]{@link node_modules/emoji-mart/dist-es/utils/index.js#19}, but is not found in the [type definition]{@link node_modules/@types/emoji-mart/dist-es/utils/emoji-index/nimble-emoji-index.d.ts}. + * `emoji-mart` does not come with a built-in type, so you need to add a separate type with DefinitelyTyped. + * The type and implementation have different maintainers and packages, so the installed versions of `@types/emoji-mart` and `emoji-mart` may not match. + */ + function sanitize( emoji: BaseEmoji & CustomEmoji & From d6015029e230e15371b3357a4d714764b5b1ae81 Mon Sep 17 00:00:00 2001 From: taichi221228 Date: Thu, 2 May 2024 11:22:49 +0900 Subject: [PATCH 08/17] Refactor emoji utils in mastodon features The refactoring of emoji utilities in the mastodon feature has been done to enhance readability and maintenance of the code. The types and functions involved in sanitizing and getting data have been clarified, including the introduction of an interface for skin tones. Additionally, erroneous typescript comments have been removed and the emojis type has been exported for further use. --- .../features/emoji/emoji_mart_data_light.ts | 2 +- .../mastodon/features/emoji/emoji_utils.ts | 99 +++++++++++-------- 2 files changed, 57 insertions(+), 44 deletions(-) diff --git a/app/javascript/mastodon/features/emoji/emoji_mart_data_light.ts b/app/javascript/mastodon/features/emoji/emoji_mart_data_light.ts index ffca1f8b063..e59b612b8d1 100644 --- a/app/javascript/mastodon/features/emoji/emoji_mart_data_light.ts +++ b/app/javascript/mastodon/features/emoji/emoji_mart_data_light.ts @@ -8,7 +8,7 @@ import type { Search, ShortCodesToEmojiData } from './emoji_compressed'; import emojiCompressed from './emoji_compressed'; import { unicodeToUnifiedName } from './unicode_to_unified_name'; -type Emojis = { +export type Emojis = { [key in NonNullable]: { native: BaseEmoji['native']; search: Search; diff --git a/app/javascript/mastodon/features/emoji/emoji_utils.ts b/app/javascript/mastodon/features/emoji/emoji_utils.ts index 98d8e9f3207..cd9bffc20da 100644 --- a/app/javascript/mastodon/features/emoji/emoji_utils.ts +++ b/app/javascript/mastodon/features/emoji/emoji_utils.ts @@ -7,7 +7,7 @@ import type { EmojiSkin, PickerProps, } from 'emoji-mart'; -import type { Emoji } from 'emoji-mart/dist-es/utils/data'; +import type { Emoji, SkinVariation } from 'emoji-mart/dist-es/utils/data'; import * as data from './emoji_mart_data_light'; @@ -58,11 +58,16 @@ function unifiedToNative(unified: Emoji['unified']) { * The type and implementation have different maintainers and packages, so the installed versions of `@types/emoji-mart` and `emoji-mart` may not match. */ +interface SkinTone { + skin_tone?: EmojiSkin; +} + function sanitize( emoji: BaseEmoji & CustomEmoji & Pick & - Pick & { skin_tone?: EmojiSkin }, + Pick & + SkinTone, ): | BaseEmoji | (Omit & Pick) { @@ -106,25 +111,45 @@ function sanitize( }; } -/* eslint-disable */ - -function getSanitizedData() { - // @ts-expect-error - return sanitize(getData(...arguments)); +function getSanitizedData( + ...args: [ + emoji: BaseEmoji | string, + skin: EmojiSkin | null, + set?: + | 'apple' + | 'google' + | 'twitter' + | 'facebook' + | 'emojione' + | 'messenger', + ] +) { + return sanitize(getData(...args)); } -// @ts-expect-error -function getData(emoji, skin, set) { - let emojiData = {}; +function getData( + emoji: BaseEmoji | string, + skin: EmojiSkin | null, + set?: 'apple' | 'google' | 'twitter' | 'facebook' | 'emojione' | 'messenger', +) { + /* eslint-disable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return */ + /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ + let emojiData: any = {}; if (typeof emoji === 'string') { - let matches = emoji.match(COLONS_REGEX); + const matches = emoji.match(COLONS_REGEX); if (matches) { emoji = matches[1]; - if (matches[2]) { - skin = parseInt(matches[2]); + const int = parseInt(matches[2]); + const isValid = (value: number): value is EmojiSkin => + ([1, 2, 3, 4, 5, 6] satisfies EmojiSkin[]).some( + (skin) => skin === value, + ); + + if (isValid(int)) { + skin = int; } } @@ -142,63 +167,51 @@ function getData(emoji, skin, set) { if (Object.hasOwn(data.emojis, emoji.id)) { emojiData = data.emojis[emoji.id]; - skin = skin || emoji.skin; + skin = skin ?? emoji.skin; } } - if (!Object.keys(emojiData).length) { + if (!Object.keys(emojiData).length && typeof emoji === 'object') { emojiData = emoji; - // @ts-expect-error emojiData.custom = true; - // @ts-expect-error if (!emojiData.search) { - // @ts-expect-error emojiData.search = buildSearch(emoji); } } - // @ts-expect-error emojiData.emoticons = emojiData.emoticons || []; - // @ts-expect-error emojiData.variations = emojiData.variations || []; - // @ts-expect-error - if (emojiData.skin_variations && skin > 1 && set) { - emojiData = JSON.parse(_JSON.stringify(emojiData)); - - let skinKey = SKINS[skin - 1], - // @ts-expect-error - variationData = emojiData.skin_variations[skinKey]; - - // @ts-expect-error - if (!variationData.variations && emojiData.variations) { - // @ts-expect-error - delete emojiData.variations; - } + if (emojiData.skin_variations && skin && skin > 1 && set) { + const skinKey = SKINS[skin - 1]; + const variationData = emojiData.skin_variations[skinKey]; if (variationData[`has_img_${set}`]) { - // @ts-expect-error emojiData.skin_tone = skin; - for (let k in variationData) { - let v = variationData[k]; - // @ts-expect-error - emojiData[k] = v; + for (const k in variationData) { + type K = keyof typeof emojiData; + emojiData[k as K] = variationData[k as keyof SkinVariation]; } } } - // @ts-expect-error - if (emojiData.variations && emojiData.variations.length) { - emojiData = JSON.parse(_JSON.stringify(emojiData)); - // @ts-expect-error + if (emojiData.variations.length) { emojiData.unified = emojiData.variations.shift(); } - return emojiData; + return emojiData as BaseEmoji & + CustomEmoji & + Pick & + Pick & + SkinTone; + + /* eslint-enable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return */ } +/* eslint-disable */ + // @ts-expect-error function uniq(arr) { // @ts-expect-error From ca30b5b3eff27ad83a7d1c50a9cb5fd851fae385 Mon Sep 17 00:00:00 2001 From: taichi221228 Date: Thu, 2 May 2024 11:25:55 +0900 Subject: [PATCH 09/17] Remove unused JSON constant from emoji utilities The unused constant `_JSON` was removed from the `emoji_utils.ts` file. This decluttering enhances the manageability and readability of the code. --- app/javascript/mastodon/features/emoji/emoji_utils.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/javascript/mastodon/features/emoji/emoji_utils.ts b/app/javascript/mastodon/features/emoji/emoji_utils.ts index cd9bffc20da..cd1b463a0a8 100644 --- a/app/javascript/mastodon/features/emoji/emoji_utils.ts +++ b/app/javascript/mastodon/features/emoji/emoji_utils.ts @@ -40,8 +40,6 @@ const buildSearch = (data: Data) => { return search.join(','); }; -const _JSON = JSON; - const COLONS_REGEX = /^(?::([^:]+):)(?::skin-tone-(\d):)?$/; const SKINS = ['1F3FA', '1F3FB', '1F3FC', '1F3FD', '1F3FE', '1F3FF']; From 5735e09738fb05cbebffcd23c1fc083bba6b6b7f Mon Sep 17 00:00:00 2001 From: taichi221228 Date: Thu, 2 May 2024 13:22:56 +0900 Subject: [PATCH 10/17] Refactor emoji utilities by introducing type aliases This commit introduces type aliases to the emoji utilities in JavaScript code, specifically `RawEmoji` and `GetDataArgs`. These changes help to simplify function signatures. By extracting complex types into separate type aliases, the code readability has been improved significantly. --- .../mastodon/features/emoji/emoji_utils.ts | 44 +++++++------------ 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/app/javascript/mastodon/features/emoji/emoji_utils.ts b/app/javascript/mastodon/features/emoji/emoji_utils.ts index cd1b463a0a8..bf5605ebe7a 100644 --- a/app/javascript/mastodon/features/emoji/emoji_utils.ts +++ b/app/javascript/mastodon/features/emoji/emoji_utils.ts @@ -60,12 +60,14 @@ interface SkinTone { skin_tone?: EmojiSkin; } +type RawEmoji = BaseEmoji & + CustomEmoji & + Pick & + Pick & + SkinTone; + function sanitize( - emoji: BaseEmoji & - CustomEmoji & - Pick & - Pick & - SkinTone, + emoji: RawEmoji, ): | BaseEmoji | (Omit & Pick) { @@ -109,27 +111,17 @@ function sanitize( }; } -function getSanitizedData( - ...args: [ - emoji: BaseEmoji | string, - skin: EmojiSkin | null, - set?: - | 'apple' - | 'google' - | 'twitter' - | 'facebook' - | 'emojione' - | 'messenger', - ] -) { - return sanitize(getData(...args)); -} - -function getData( +type GetDataArgs = [ emoji: BaseEmoji | string, skin: EmojiSkin | null, set?: 'apple' | 'google' | 'twitter' | 'facebook' | 'emojione' | 'messenger', -) { +]; + +function getSanitizedData(...args: GetDataArgs) { + return sanitize(getData(...args)); +} + +function getData(...[emoji, skin, set]: GetDataArgs) { /* eslint-disable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return */ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ let emojiData: any = {}; @@ -199,11 +191,7 @@ function getData( emojiData.unified = emojiData.variations.shift(); } - return emojiData as BaseEmoji & - CustomEmoji & - Pick & - Pick & - SkinTone; + return emojiData as RawEmoji; /* eslint-enable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return */ } From 5a23b7ed4f8fe819de33012e639356d0998ac2df Mon Sep 17 00:00:00 2001 From: taichi221228 Date: Thu, 2 May 2024 13:36:19 +0900 Subject: [PATCH 11/17] Added clarifying comment to emoji_utils.ts function A comment has been added to the 'getData' function in emoji_utils.ts to clarify that the source code version does not match that of DefinitelyTyped. The note also highlights the challenges in maintaining type consistency due to outdated and non-existing properties. --- app/javascript/mastodon/features/emoji/emoji_utils.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/javascript/mastodon/features/emoji/emoji_utils.ts b/app/javascript/mastodon/features/emoji/emoji_utils.ts index bf5605ebe7a..2c56ad76fed 100644 --- a/app/javascript/mastodon/features/emoji/emoji_utils.ts +++ b/app/javascript/mastodon/features/emoji/emoji_utils.ts @@ -122,6 +122,10 @@ function getSanitizedData(...args: GetDataArgs) { } function getData(...[emoji, skin, set]: GetDataArgs) { + /* + The version of [the referenced source code]{@link https://github.com/missive/emoji-mart/blob/5f2ffcc/src/utils/index.js} does not match that of DefinitelyTyped. + It is also old, and non-existent properties have been added or removed, making it difficult to achieve type consistency. + */ /* eslint-disable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return */ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ let emojiData: any = {}; From 33bd4e67e9c7014d69487228aef353a38260666c Mon Sep 17 00:00:00 2001 From: taichi221228 Date: Thu, 2 May 2024 13:37:22 +0900 Subject: [PATCH 12/17] Refactor `uniq` function for TS compliance and efficiency improvements This commit refactors the `uniq` function found in the emoji utilities to accept an explicitly defined array as an argument, improving overall TypeScript compliance. It also replaces the `.indexOf` method with the more efficient `.includes` method for better performance. --- app/javascript/mastodon/features/emoji/emoji_utils.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/app/javascript/mastodon/features/emoji/emoji_utils.ts b/app/javascript/mastodon/features/emoji/emoji_utils.ts index 2c56ad76fed..41745318352 100644 --- a/app/javascript/mastodon/features/emoji/emoji_utils.ts +++ b/app/javascript/mastodon/features/emoji/emoji_utils.ts @@ -200,25 +200,22 @@ function getData(...[emoji, skin, set]: GetDataArgs) { /* eslint-enable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return */ } -/* eslint-disable */ - -// @ts-expect-error -function uniq(arr) { - // @ts-expect-error +function uniq(arr: []) { return arr.reduce((acc, item) => { - if (acc.indexOf(item) === -1) { + if (!acc.includes(item)) { acc.push(item); } return acc; }, []); } +/* eslint-disable */ + // @ts-expect-error function intersect(a, b) { const uniqA = uniq(a); const uniqB = uniq(b); - // @ts-expect-error return uniqA.filter((item) => uniqB.indexOf(item) >= 0); } From 78248aea26de5d2c242c401c373bda8bdcec4b20 Mon Sep 17 00:00:00 2001 From: taichi221228 Date: Thu, 2 May 2024 13:38:48 +0900 Subject: [PATCH 13/17] Refactor intersect function in emoji_utils.ts This commit refactors the intersect function in the emoji_utils.ts file. The `a` and `b` parameters are more explicitly defined as empty arrays, and the indexOf method is replaced with the includes method for better readability and performance. Additionally, the placement of the eslint-disable directive has been adjusted to improve linting results. --- app/javascript/mastodon/features/emoji/emoji_utils.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/javascript/mastodon/features/emoji/emoji_utils.ts b/app/javascript/mastodon/features/emoji/emoji_utils.ts index 41745318352..ce30e711ade 100644 --- a/app/javascript/mastodon/features/emoji/emoji_utils.ts +++ b/app/javascript/mastodon/features/emoji/emoji_utils.ts @@ -209,16 +209,15 @@ function uniq(arr: []) { }, []); } -/* eslint-disable */ - -// @ts-expect-error -function intersect(a, b) { +function intersect(a: [], b: []) { const uniqA = uniq(a); const uniqB = uniq(b); - return uniqA.filter((item) => uniqB.indexOf(item) >= 0); + return uniqA.filter((item) => uniqB.includes(item)); } +/* eslint-disable */ + // @ts-expect-error function deepMerge(a, b) { let o = {}; From bee50d831c50df68156a774061d2447fc584fe7b Mon Sep 17 00:00:00 2001 From: taichi221228 Date: Thu, 2 May 2024 15:37:11 +0900 Subject: [PATCH 14/17] Remove deepMerge function from emoji_utils The deepMerge function was removed from the emoji_utils file. This function was not used in the code and was deemed unnecessary, hence it was removed. Also, with its removal, the corresponding import was deleted. --- .../mastodon/features/emoji/emoji_utils.ts | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/app/javascript/mastodon/features/emoji/emoji_utils.ts b/app/javascript/mastodon/features/emoji/emoji_utils.ts index ce30e711ade..d717f5b85f7 100644 --- a/app/javascript/mastodon/features/emoji/emoji_utils.ts +++ b/app/javascript/mastodon/features/emoji/emoji_utils.ts @@ -216,31 +216,6 @@ function intersect(a: [], b: []) { return uniqA.filter((item) => uniqB.includes(item)); } -/* eslint-disable */ - -// @ts-expect-error -function deepMerge(a, b) { - let o = {}; - - for (let key in a) { - let originalValue = a[key], - value = originalValue; - - if (Object.hasOwn(b, key)) { - value = b[key]; - } - - if (typeof value === 'object') { - value = deepMerge(originalValue, value); - } - - // @ts-expect-error - o[key] = value; - } - - return o; -} - // https://github.com/sonicdoe/measure-scrollbar function measureScrollbar() { const div = document.createElement('div'); @@ -263,7 +238,6 @@ export { getSanitizedData, uniq, intersect, - deepMerge, unifiedToNative, measureScrollbar, }; From 2bcd355289316a4c164d0b3c213e6c53b81974c1 Mon Sep 17 00:00:00 2001 From: taichi221228 Date: Thu, 2 May 2024 15:39:52 +0900 Subject: [PATCH 15/17] Add comments for improving code modularity in emoji_utils.ts New comments were added in the 'emoji_utils.ts' file to suggest separating the general array operations from the emoji-related functions into different files. This aims to increase the readability and maintainability of the code. --- app/javascript/mastodon/features/emoji/emoji_utils.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/javascript/mastodon/features/emoji/emoji_utils.ts b/app/javascript/mastodon/features/emoji/emoji_utils.ts index d717f5b85f7..f33ffea833e 100644 --- a/app/javascript/mastodon/features/emoji/emoji_utils.ts +++ b/app/javascript/mastodon/features/emoji/emoji_utils.ts @@ -200,6 +200,7 @@ function getData(...[emoji, skin, set]: GetDataArgs) { /* eslint-enable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return */ } +// TODO: General array operations not related to emojis. Consider separating them into separate files. function uniq(arr: []) { return arr.reduce((acc, item) => { if (!acc.includes(item)) { @@ -209,6 +210,7 @@ function uniq(arr: []) { }, []); } +// TODO: General array operations not related to emojis. Consider separating them into separate files. function intersect(a: [], b: []) { const uniqA = uniq(a); const uniqB = uniq(b); From 28b4212206e8589241a54dc3187568edaf822b5e Mon Sep 17 00:00:00 2001 From: taichi221228 Date: Thu, 2 May 2024 15:40:06 +0900 Subject: [PATCH 16/17] Remove measureScrollbar function from emoji_utils The measureScrollbar function has been deleted from the emoji_utils.ts file. This simplifies the module export list by removing a function that was unnecessary or out of context. --- .../mastodon/features/emoji/emoji_utils.ts | 26 +------------------ 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/app/javascript/mastodon/features/emoji/emoji_utils.ts b/app/javascript/mastodon/features/emoji/emoji_utils.ts index f33ffea833e..21de5cd3fc0 100644 --- a/app/javascript/mastodon/features/emoji/emoji_utils.ts +++ b/app/javascript/mastodon/features/emoji/emoji_utils.ts @@ -218,28 +218,4 @@ function intersect(a: [], b: []) { return uniqA.filter((item) => uniqB.includes(item)); } -// https://github.com/sonicdoe/measure-scrollbar -function measureScrollbar() { - const div = document.createElement('div'); - - div.style.width = '100px'; - div.style.height = '100px'; - div.style.overflow = 'scroll'; - div.style.position = 'absolute'; - div.style.top = '-9999px'; - - document.body.appendChild(div); - const scrollbarWidth = div.offsetWidth - div.clientWidth; - document.body.removeChild(div); - - return scrollbarWidth; -} - -export { - getData, - getSanitizedData, - uniq, - intersect, - unifiedToNative, - measureScrollbar, -}; +export { getData, getSanitizedData, uniq, intersect, unifiedToNative }; From 8585e26aae7f3d73e236beb9efe38b1d621406c3 Mon Sep 17 00:00:00 2001 From: taichi221228 Date: Thu, 2 May 2024 15:54:22 +0900 Subject: [PATCH 17/17] Remove no-unsafe-return rule from eslint-disable in emoji_utils.ts Removed the no-unsafe-return rule from the eslint-disable and eslint-enable comments in the emoji_utils.ts file, as it is no longer required. This helps to improve code readability and reduces unnecessary complexity. --- app/javascript/mastodon/features/emoji/emoji_utils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/javascript/mastodon/features/emoji/emoji_utils.ts b/app/javascript/mastodon/features/emoji/emoji_utils.ts index 21de5cd3fc0..1f3fb024057 100644 --- a/app/javascript/mastodon/features/emoji/emoji_utils.ts +++ b/app/javascript/mastodon/features/emoji/emoji_utils.ts @@ -126,7 +126,7 @@ function getData(...[emoji, skin, set]: GetDataArgs) { The version of [the referenced source code]{@link https://github.com/missive/emoji-mart/blob/5f2ffcc/src/utils/index.js} does not match that of DefinitelyTyped. It is also old, and non-existent properties have been added or removed, making it difficult to achieve type consistency. */ - /* eslint-disable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return */ + /* eslint-disable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access */ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ let emojiData: any = {}; @@ -197,7 +197,7 @@ function getData(...[emoji, skin, set]: GetDataArgs) { return emojiData as RawEmoji; - /* eslint-enable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return */ + /* eslint-enable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access */ } // TODO: General array operations not related to emojis. Consider separating them into separate files.