Files
upstream-rocketchat/apps/meteor/client/lib/customEmoji.ts
upstream-mirror 30810eecd7
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Code scanning - action / CodeQL-Build (push) Failing after 2s
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
2026-09-16 01:21:02 +05:00

136 lines
4.7 KiB
TypeScript

import type { IEmoji } from '@rocket.chat/core-typings';
import { escapeRegExp } from '@rocket.chat/tools';
import { emoji, removeFromRecent, replaceEmojiInRecent } from './emoji';
import { getURL } from './getURL';
const isSetNotNull = (fn: () => unknown) => {
let value;
try {
value = fn();
} catch (e) {
value = null;
}
return value !== null && value !== undefined;
};
export const updateEmojiCustom = (emojiData: IEmoji) => {
const previousExists = isSetNotNull(() => emojiData.previousName);
const currentAliases = isSetNotNull(() => emojiData.aliases);
if (previousExists && isSetNotNull(() => emoji.list[`:${emojiData.previousName}:`].aliases)) {
for (const alias of emoji.list[`:${emojiData.previousName}:`].aliases ?? []) {
delete emoji.list[`:${alias}:`];
const aliasIndex = emoji.packages.emojiCustom.list?.indexOf(`:${alias}:`) ?? -1;
if (aliasIndex !== -1) {
emoji.packages.emojiCustom.list?.splice(aliasIndex, 1);
}
}
}
if (previousExists && emojiData.name !== emojiData.previousName) {
const arrayIndex = emoji.packages.emojiCustom.emojisByCategory.rocket.indexOf(emojiData.previousName);
if (arrayIndex !== -1) {
emoji.packages.emojiCustom.emojisByCategory.rocket.splice(arrayIndex, 1);
}
const arrayIndexList = emoji.packages.emojiCustom.list?.indexOf(`:${emojiData.previousName}:`) ?? -1;
if (arrayIndexList !== -1) {
emoji.packages.emojiCustom.list?.splice(arrayIndexList, 1);
}
delete emoji.list[`:${emojiData.previousName}:`];
}
const categoryIndex = emoji.packages.emojiCustom.emojisByCategory.rocket.indexOf(`${emojiData.name}`);
if (categoryIndex === -1) {
emoji.packages.emojiCustom.emojisByCategory.rocket.push(`${emojiData.name}`);
emoji.packages.emojiCustom.list?.push(`:${emojiData.name}:`);
}
// Don't inherit fields from a native emoji being overridden (e.g. its unicode), or the pick would output the native emoji
// TODO: Fix the IEmoji type and standardize the emoji packs types
emoji.list[`:${emojiData.name}:`] = {
...emojiData,
emojiPackage: 'emojiCustom',
} as unknown as (typeof emoji.list)[keyof typeof emoji.list];
if (currentAliases) {
for (const alias of emojiData.aliases) {
emoji.packages.emojiCustom.list?.push(`:${alias}:`);
emoji.list[`:${alias}:`] = {
emojiPackage: 'emojiCustom',
aliasOf: emojiData.name,
};
}
}
if (previousExists) {
replaceEmojiInRecent({ oldEmoji: emojiData.previousName, newEmoji: emojiData.name });
}
emoji.dispatchUpdate();
};
export const deleteEmojiCustom = (emojiData: IEmoji) => {
delete emoji.list[`:${emojiData.name}:`];
const arrayIndex = emoji.packages.emojiCustom.emojisByCategory.rocket.indexOf(emojiData.name);
if (arrayIndex !== -1) {
emoji.packages.emojiCustom.emojisByCategory.rocket.splice(arrayIndex, 1);
}
const arrayIndexList = emoji.packages.emojiCustom.list?.indexOf(`:${emojiData.name}:`) ?? -1;
if (arrayIndexList !== -1) {
emoji.packages.emojiCustom.list?.splice(arrayIndexList, 1);
}
if (emojiData.aliases) {
for (const alias of emojiData.aliases) {
delete emoji.list[`:${alias}:`];
const aliasIndex = emoji.packages.emojiCustom.list?.indexOf(`:${alias}:`) ?? -1;
if (aliasIndex !== -1) {
emoji.packages.emojiCustom.list?.splice(aliasIndex, 1);
}
}
}
removeFromRecent(emojiData.name, emoji.packages.base.emojisByCategory.recent);
emoji.dispatchUpdate();
};
const getEmojiUrlFromName = (name: string, extension: string, etag?: string) => {
if (!name) {
return;
}
return getURL(`/emoji-custom/${encodeURIComponent(name)}.${extension}${etag ? `?etag=${etag}` : ''}`);
};
export const customRender = (html: string) => {
const emojisMatchGroup = emoji.packages.emojiCustom.list?.map(escapeRegExp).join('|');
if (emojisMatchGroup !== emoji.packages.emojiCustom._regexpSignature) {
emoji.packages.emojiCustom._regexpSignature = emojisMatchGroup;
emoji.packages.emojiCustom._regexp = new RegExp(
`<object[^>]*>.*?<\/object>|<span[^>]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|(${emojisMatchGroup})`,
'gi',
);
emoji.dispatchUpdate();
}
html = html.replace(emoji.packages.emojiCustom._regexp!, (shortname) => {
if (typeof shortname === 'undefined' || shortname === '' || (emoji.packages.emojiCustom.list?.indexOf(shortname) ?? -1) === -1) {
return shortname;
}
let emojiAlias = shortname.replace(/:/g, '');
let dataCheck = emoji.list[shortname];
if (dataCheck.aliasOf) {
emojiAlias = dataCheck.aliasOf;
dataCheck = emoji.list[`:${emojiAlias}:`];
}
return `<span class="emoji emoji--custom" style="background-image:url(${getEmojiUrlFromName(
emojiAlias,
dataCheck.extension!,
dataCheck.etag,
)});" data-emoji="${emojiAlias}" title="${shortname}">${shortname}</span>`;
});
return html;
};