Add markdown :name: emoji shortcode support in messages (#27)

Typing a complete 😂/😉/etc. shortcode now renders as the emoji,
matching Slack/GitHub/Discord. Render-time only, alongside the existing
preserveLineBreaks preprocessing step -- stored/sent content keeps the
raw :name: text, same as markdown itself is never converted until
display. Fenced code blocks and inline code spans are skipped so
pasted code (a Ruby symbol, a dict key) isn't silently mangled.

frontend/src/lib/emojiShortcodes.ts is generated once from
emojibase-data's GitHub shortcode set (same one-time-generator approach
as #19's emojiNames.ts, never a runtime dependency) -- 928 of the
app's 936 emoji matched, 956 aliases, no collisions.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-16 10:38:09 -06:00
co-authored by Claude Sonnet 5
parent 7dcc7104df
commit 1adb4fcbe0
2 changed files with 1001 additions and 1 deletions
+34 -1
View File
@@ -1,4 +1,5 @@
import Markdown from 'markdown-to-jsx'
import { EMOJI_SHORTCODES } from '../lib/emojiShortcodes'
interface MessageContentProps {
content: string
@@ -23,6 +24,38 @@ function MarkdownImageLink({ src, alt, title }: MarkdownImageLinkProps) {
)
}
const SHORTCODE_PATTERN = /:([a-z0-9_+-]+):/g
// Converts a complete `:name:` shortcode to its emoji, skipping fenced code
// blocks and inline code spans -- someone pasting code containing
// `:something:` (a Ruby symbol, a dict key) shouldn't get it silently
// turned into an emoji. This is render-time only: stored/sent content
// always keeps the literal `:name:` text, matching how markdown itself is
// never converted until display.
function convertShortcodes(text: string): string {
const lines = text.split('\n')
let inFence = false
return lines
.map((line) => {
if (/^\s*```/.test(line)) {
inFence = !inFence
return line
}
if (inFence) return line
// Splitting on backtick-delimited spans keeps inline code (`:foo:`)
// untouched -- odd-indexed segments are the code spans themselves.
return line
.split(/(`+[^`]*`+)/g)
.map((part, i) =>
i % 2 === 0
? part.replace(SHORTCODE_PATTERN, (match, name) => EMOJI_SHORTCODES[name] ?? match)
: part,
)
.join('')
})
.join('\n')
}
// CommonMark treats a single newline as a soft break (rendered as a space),
// not a visible line break -- only a trailing double-space or blank line
// produces one. The Composer's Shift+Enter has always inserted a plain
@@ -60,5 +93,5 @@ export const MARKDOWN_OPTIONS = {
}
export function MessageContent({ content }: MessageContentProps) {
return <Markdown options={MARKDOWN_OPTIONS}>{preserveLineBreaks(content)}</Markdown>
return <Markdown options={MARKDOWN_OPTIONS}>{preserveLineBreaks(convertShortcodes(content))}</Markdown>
}
+967
View File
@@ -0,0 +1,967 @@
// Shortcode -> emoji lookup for :name: conversion in chat messages,
// generated once from emojibase-data (MIT licensed,
// https://github.com/milesj/emojibase -- en/shortcodes/github.json), matched
// against the emoji actually used in emoji.ts. Not a runtime dependency:
// emojibase-data was only ever a dev-time tool to produce this static
// lookup, never added to package.json. Uses GitHub's shortcode set (the
// most broadly recognized convention) rather than Slack/CLDR/JoyPixels
// variants. If emoji.ts ever adds a new entry, this needs regenerating to
// match.
export const EMOJI_SHORTCODES: Record<string, string> = {
'+1': '👍',
'-1': '👎',
'100': '💯',
'1234': '🔢',
'1st_place_medal': '🥇',
'2nd_place_medal': '🥈',
'3rd_place_medal': '🥉',
'8ball': '🎱',
'a': '🅰️',
'ab': '🆎',
'abc': '🔤',
'adhesive_bandage': '🩹',
'adult': '🧑',
'airplane': '✈️',
'alarm_clock': '⏰',
'alembic': '⚗️',
'alien': '👽',
'ambulance': '🚑',
'anatomical_heart': '🫀',
'anchor': '⚓',
'anger': '💢',
'angry': '😠',
'anguished': '😧',
'ant': '🐜',
'apple': '🍎',
'art': '🎨',
'astonished': '😲',
'australia': '🇦🇺',
'avocado': '🥑',
'axe': '🪓',
'b': '🅱️',
'baby': '👶',
'baby_bottle': '🍼',
'baby_chick': '🐤',
'bacon': '🥓',
'badger': '🦡',
'badminton': '🏸',
'bagel': '🥯',
'baguette_bread': '🥖',
'balance_scale': '⚖️',
'balloon': '🎈',
'ballot_box_with_check': '☑️',
'bamboo': '🎍',
'banana': '🍌',
'bangbang': '‼️',
'bank': '🏦',
'baseball': '⚾',
'basket': '🧺',
'basketball': '🏀',
'bat': '🦇',
'bathtub': '🛁',
'battery': '🔋',
'beach_umbrella': '🏖️',
'bear': '🐻',
'bed': '🛏️',
'bee': '🐝',
'beer': '🍺',
'beers': '🍻',
'beginner': '🔰',
'bell': '🔔',
'bell_pepper': '🫑',
'bellhop_bell': '🛎️',
'bento': '🍱',
'beverage_box': '🧃',
'bicyclist': '🚴',
'bike': '🚲',
'biohazard': '☣️',
'bird': '🐦',
'birthday': '🎂',
'black_circle': '⚫',
'black_flag': '🏴',
'black_heart': '🖤',
'black_joker': '🃏',
'black_large_square': '⬛',
'black_medium_square': '◼️',
'blond_haired_person': '👱',
'blossom': '🌼',
'blowfish': '🐡',
'blue_book': '📘',
'blue_car': '🚙',
'blue_heart': '💙',
'blue_square': '🟦',
'blueberries': '🫐',
'blush': '😊',
'boar': '🐗',
'boat': '⛵',
'bomb': '💣',
'bone': '🦴',
'book': '📖',
'bookmark': '🔖',
'books': '📚',
'boom': '💥',
'bouncing_ball_person': '⛹️',
'bouquet': '💐',
'bow': '🙇',
'bow_and_arrow': '🏹',
'bowl_with_spoon': '🥣',
'bowling': '🎳',
'boxing_glove': '🥊',
'boy': '👦',
'brain': '🧠',
'brazil': '🇧🇷',
'bread': '🍞',
'bricks': '🧱',
'bridge_at_night': '🌉',
'broccoli': '🥦',
'broken_heart': '💔',
'broom': '🧹',
'brown_circle': '🟤',
'brown_heart': '🤎',
'brown_square': '🟫',
'bubble_tea': '🧋',
'bucket': '🪣',
'bug': '🐛',
'building_construction': '🏗️',
'bulb': '💡',
'burrito': '🌯',
'bus': '🚌',
'bust_in_silhouette': '👤',
'busts_in_silhouette': '👥',
'butter': '🧈',
'butterfly': '🦋',
'cactus': '🌵',
'cake': '🍰',
'calendar': '📆',
'call_me_hand': '🤙',
'camel': '🐫',
'camera': '📷',
'camera_flash': '📸',
'camping': '🏕️',
'canada': '🇨🇦',
'candle': '🕯️',
'candy': '🍬',
'canned_food': '🥫',
'canoe': '🛶',
'car': '🚗',
'card_file_box': '🗃️',
'card_index': '📇',
'carousel_horse': '🎠',
'carrot': '🥕',
'cartwheeling': '🤸',
'cat': '🐱',
'cat2': '🐈',
'cd': '💿',
'chains': '⛓️',
'chair': '🪑',
'champagne': '🍾',
'checkered_flag': '🏁',
'cheese': '🧀',
'cherries': '🍒',
'cherry_blossom': '🌸',
'chess_pawn': '♟️',
'chestnut': '🌰',
'chicken': '🐔',
'child': '🧒',
'chipmunk': '🐿️',
'chocolate_bar': '🍫',
'chopsticks': '🥢',
'christmas_tree': '🎄',
'church': '⛪',
'circus_tent': '🎪',
'city_sunrise': '🌇',
'city_sunset': '🌆',
'cityscape': '🏙️',
'clap': '👏',
'clapper': '🎬',
'classical_building': '🏛️',
'climbing': '🧗',
'clinking_glasses': '🥂',
'clipboard': '📋',
'closed_book': '📕',
'closed_lock_with_key': '🔐',
'cloud': '☁️',
'cloud_with_lightning_and_rain': '⛈️',
'cloud_with_rain': '🌧️',
'clown_face': '🤡',
'cn': '🇨🇳',
'cocktail': '🍸',
'coconut': '🥥',
'coffee': '☕',
'coffin': '⚰️',
'cold_face': '🥶',
'cold_sweat': '😰',
'collision': '💥',
'comet': '☄️',
'compass': '🧭',
'computer': '💻',
'computer_mouse': '🖱️',
'confetti_ball': '🎊',
'confounded': '😖',
'confused': '😕',
'construction': '🚧',
'cookie': '🍪',
'cool': '🆒',
'corn': '🌽',
'couch_and_lamp': '🛋️',
'cow': '🐮',
'cow2': '🐄',
'cowboy_hat_face': '🤠',
'crab': '🦀',
'crayon': '🖍️',
'credit_card': '💳',
'crescent_moon': '🌙',
'cricket_game': '🏏',
'crocodile': '🐊',
'croissant': '🥐',
'crossed_fingers': '🤞',
'crossed_flags': '🎌',
'crossed_swords': '⚔️',
'cry': '😢',
'crying_cat_face': '😿',
'cucumber': '🥒',
'cup_with_straw': '🥤',
'cupcake': '🧁',
'cupid': '💘',
'currency_exchange': '💱',
'curry': '🍛',
'cursing_face': '🤬',
'custard': '🍮',
'cut_of_meat': '🥩',
'cyclone': '🌀',
'dagger': '🗡️',
'dango': '🍡',
'dart': '🎯',
'dash': '💨',
'date': '📅',
'de': '🇩🇪',
'deaf_person': '🧏',
'deciduous_tree': '🌳',
'deer': '🦌',
'department_store': '🏬',
'desert': '🏜️',
'desert_island': '🏝️',
'desktop_computer': '🖥️',
'diamond_shape_with_a_dot_inside': '💠',
'disappointed': '😞',
'disappointed_relieved': '😥',
'disguised_face': '🥸',
'diya_lamp': '🪔',
'dizzy': '💫',
'dizzy_face': '😵',
'dog': '🐶',
'dog2': '🐕',
'dollar': '💵',
'dolphin': '🐬',
'door': '🚪',
'dotted_line_face': '🫥',
'doughnut': '🍩',
'dove': '🕊️',
'dragon': '🐉',
'dromedary_camel': '🐪',
'drooling_face': '🤤',
'drop_of_blood': '🩸',
'droplet': '💧',
'drum': '🥁',
'duck': '🦆',
'dumpling': '🥟',
'dvd': '📀',
'e-mail': '📧',
'eagle': '🦅',
'ear': '👂',
'ear_of_rice': '🌾',
'ear_with_hearing_aid': '🦻',
'earth_africa': '🌍',
'earth_americas': '🌎',
'earth_asia': '🌏',
'egg': '🥚',
'eggplant': '🍆',
'eight_pointed_black_star': '✴️',
'eight_spoked_asterisk': '✳️',
'electric_plug': '🔌',
'elephant': '🐘',
'email': '📧',
'envelope_with_arrow': '📩',
'es': '🇪🇸',
'euro': '💶',
'european_castle': '🏰',
'evergreen_tree': '🌲',
'exclamation': '❗',
'exploding_head': '🤯',
'expressionless': '😑',
'eye': '👁️',
'eye_speech_bubble': '👁️‍🗨️',
'eyes': '👀',
'face_holding_back_tears': '🥹',
'face_with_diagonal_mouth': '🫤',
'face_with_head_bandage': '🤕',
'face_with_open_eyes_and_hand_over_mouth': '🫢',
'face_with_peeking_eye': '🫣',
'face_with_thermometer': '🤒',
'facepalm': '🤦',
'facepunch': '👊',
'factory': '🏭',
'falafel': '🧆',
'fallen_leaf': '🍂',
'fearful': '😨',
'feet': '🐾',
'ferris_wheel': '🎡',
'field_hockey': '🏑',
'file_cabinet': '🗄️',
'file_folder': '📁',
'fire': '🔥',
'fire_engine': '🚒',
'fire_extinguisher': '🧯',
'firecracker': '🧨',
'fireworks': '🎆',
'first_quarter_moon': '🌓',
'first_quarter_moon_with_face': '🌛',
'fish': '🐟',
'fish_cake': '🍥',
'fishing_pole_and_fish': '🎣',
'fist': '✊',
'fist_left': '🤛',
'fist_oncoming': '👊',
'fist_raised': '✊',
'fist_right': '🤜',
'flamingo': '🦩',
'flashlight': '🔦',
'fleur_de_lis': '⚜️',
'flight_arrival': '🛬',
'flight_departure': '🛫',
'flipper': '🐬',
'floppy_disk': '💾',
'flower_playing_cards': '🎴',
'flushed': '😳',
'flying_disc': '🥏',
'flying_saucer': '🛸',
'foggy': '🌁',
'foot': '🦶',
'football': '🏈',
'fork_and_knife': '🍴',
'fortune_cookie': '🥠',
'fountain': '⛲',
'fountain_pen': '🖋️',
'four_leaf_clover': '🍀',
'fox_face': '🦊',
'fr': '🇫🇷',
'free': '🆓',
'fried_egg': '🍳',
'fried_shrimp': '🍤',
'fries': '🍟',
'frog': '🐸',
'frowning': '😦',
'frowning_face': '☹️',
'fu': '🖕',
'full_moon': '🌕',
'full_moon_with_face': '🌝',
'game_die': '🎲',
'garlic': '🧄',
'gb': '🇬🇧',
'gear': '⚙️',
'gem': '💎',
'ghost': '👻',
'gift': '🎁',
'gift_heart': '💝',
'giraffe': '🦒',
'girl': '👧',
'goal_net': '🥅',
'goat': '🐐',
'golf': '⛳',
'gorilla': '🦍',
'grapes': '🍇',
'green_apple': '🍏',
'green_book': '📗',
'green_circle': '🟢',
'green_heart': '💚',
'green_salad': '🥗',
'green_square': '🟩',
'grey_exclamation': '❕',
'grey_question': '❔',
'grimacing': '😬',
'grin': '😁',
'grinning': '😀',
'guitar': '🎸',
'gun': '🔫',
'hamburger': '🍔',
'hammer': '🔨',
'hammer_and_pick': '⚒️',
'hammer_and_wrench': '🛠️',
'hamster': '🐹',
'hand': '✋',
'hand_over_mouth': '🤭',
'hand_with_index_finger_and_thumb_crossed': '🫰',
'handball_person': '🤾',
'handshake': '🤝',
'hankey': '💩',
'hatched_chick': '🐥',
'headphones': '🎧',
'headstone': '🪦',
'hear_no_evil': '🙉',
'heart': '❤️',
'heart_decoration': '💟',
'heart_eyes': '😍',
'heart_eyes_cat': '😻',
'heart_hands': '🫶',
'heart_on_fire': '❤️‍🔥',
'heartbeat': '💓',
'heartpulse': '💗',
'hearts': '♥️',
'heavy_check_mark': '✔️',
'heavy_division_sign': '➗',
'heavy_dollar_sign': '💲',
'heavy_exclamation_mark': '❗',
'heavy_minus_sign': '',
'heavy_multiplication_x': '✖️',
'heavy_plus_sign': '',
'hedgehog': '🦔',
'helicopter': '🚁',
'herb': '🌿',
'hibiscus': '🌺',
'hindu_temple': '🛕',
'hippopotamus': '🦛',
'hocho': '🔪',
'honey_pot': '🍯',
'honeybee': '🐝',
'horse': '🐴',
'horse_racing': '🏇',
'hospital': '🏥',
'hot_face': '🥵',
'hot_pepper': '🌶️',
'hotdog': '🌭',
'hotel': '🏨',
'hourglass': '⌛',
'hourglass_flowing_sand': '⏳',
'house': '🏠',
'house_with_garden': '🏡',
'hugs': '🤗',
'hushed': '😯',
'ice_cream': '🍨',
'ice_cube': '🧊',
'ice_hockey': '🏒',
'ice_skate': '⛸️',
'icecream': '🍦',
'imp': '👿',
'inbox_tray': '📥',
'incoming_envelope': '📨',
'india': '🇮🇳',
'infinity': '♾️',
'information_desk_person': '💁',
'innocent': '😇',
'interrobang': '⁉️',
'iphone': '📱',
'ireland': '🇮🇪',
'it': '🇮🇹',
'japanese_goblin': '👺',
'japanese_ogre': '👹',
'jigsaw': '🧩',
'joy': '😂',
'joy_cat': '😹',
'jp': '🇯🇵',
'juggling_person': '🤹',
'kangaroo': '🦘',
'key': '🔑',
'keyboard': '⌨️',
'keycap_ten': '🔟',
'kick_scooter': '🛴',
'kiss': '💋',
'kissing': '😗',
'kissing_cat': '😽',
'kissing_closed_eyes': '😚',
'kissing_heart': '😘',
'kissing_smiling_eyes': '😙',
'kite': '🪁',
'kiwi_fruit': '🥝',
'knife': '🔪',
'koala': '🐨',
'kr': '🇰🇷',
'lacrosse': '🥍',
'lady_beetle': '🐞',
'large_blue_circle': '🔵',
'large_blue_diamond': '🔷',
'large_orange_diamond': '🔶',
'last_quarter_moon': '🌗',
'last_quarter_moon_with_face': '🌜',
'laughing': '😆',
'leafy_green': '🥬',
'leaves': '🍃',
'ledger': '📒',
'leg': '🦵',
'lemon': '🍋',
'leopard': '🐆',
'lion': '🦁',
'lips': '👄',
'lizard': '🦎',
'llama': '🦙',
'lobster': '🦞',
'lock': '🔒',
'lock_with_ink_pen': '🔏',
'lollipop': '🍭',
'lotion_bottle': '🧴',
'lotus_position': '🧘',
'loud_sound': '🔊',
'loudspeaker': '📢',
'love_letter': '💌',
'love_you_gesture': '🤟',
'luggage': '🧳',
'lungs': '🫁',
'lying_face': '🤥',
'magic_wand': '🪄',
'magnet': '🧲',
'mahjong': '🀄',
'mailbox': '📫',
'mailbox_closed': '📪',
'mailbox_with_mail': '📬',
'mailbox_with_no_mail': '📭',
'man': '👨',
'mandarin': '🍊',
'mango': '🥭',
'mantelpiece_clock': '🕰️',
'maple_leaf': '🍁',
'martial_arts_uniform': '🥋',
'mask': '😷',
'mate': '🧉',
'meat_on_bone': '🍖',
'mechanical_arm': '🦾',
'mechanical_leg': '🦿',
'medal_military': '🎖️',
'medal_sports': '🏅',
'medical_symbol': '⚕️',
'mega': '📣',
'melon': '🍈',
'melting_face': '🫠',
'memo': '📝',
'metal': '🤘',
'metro': '🚇',
'mexico': '🇲🇽',
'microphone': '🎤',
'microscope': '🔬',
'middle_finger': '🖕',
'milk_glass': '🥛',
'minidisc': '💽',
'mirror': '🪞',
'money_mouth_face': '🤑',
'money_with_wings': '💸',
'moneybag': '💰',
'monkey_face': '🐵',
'monocle_face': '🧐',
'moon': '🌔',
'moon_cake': '🥮',
'mosque': '🕌',
'motor_scooter': '🛵',
'motorcycle': '🏍️',
'mountain': '⛰️',
'mountain_bicyclist': '🚵',
'mountain_snow': '🏔️',
'mouse': '🐭',
'mouse2': '🐁',
'movie_camera': '🎥',
'moyai': '🗿',
'muscle': '💪',
'mushroom': '🍄',
'musical_keyboard': '🎹',
'musical_score': '🎼',
'mute': '🔇',
'nail_care': '💅',
'name_badge': '📛',
'nauseated_face': '🤢',
'negative_squared_cross_mark': '❎',
'nerd_face': '🤓',
'netherlands': '🇳🇱',
'neutral_face': '😐',
'new': '🆕',
'new_moon': '🌑',
'new_moon_with_face': '🌚',
'newspaper': '📰',
'night_with_stars': '🌃',
'no_bell': '🔕',
'no_entry': '⛔',
'no_entry_sign': '🚫',
'no_good': '🙅',
'no_mobile_phones': '📵',
'no_mouth': '😶',
'norway': '🇳🇴',
'nose': '👃',
'notebook': '📓',
'notebook_with_decorative_cover': '📔',
'nut_and_bolt': '🔩',
'o': '⭕',
'o2': '🅾️',
'octopus': '🐙',
'oden': '🍢',
'office': '🏢',
'oil_drum': '🛢️',
'ok': '🆗',
'ok_hand': '👌',
'ok_person': '🙆',
'old_key': '🗝️',
'older_adult': '🧓',
'older_man': '👴',
'older_woman': '👵',
'olive': '🫒',
'onion': '🧅',
'open_book': '📖',
'open_file_folder': '📂',
'open_hands': '👐',
'open_mouth': '😮',
'orange': '🍊',
'orange_book': '📙',
'orange_circle': '🟠',
'orange_heart': '🧡',
'orange_square': '🟧',
'otter': '🦦',
'outbox_tray': '📤',
'owl': '🦉',
'ox': '🐂',
'oyster': '🦪',
'package': '📦',
'page_facing_up': '📄',
'page_with_curl': '📃',
'pager': '📟',
'paintbrush': '🖌️',
'palm_tree': '🌴',
'palms_up_together': '🤲',
'pancakes': '🥞',
'panda_face': '🐼',
'paperclip': '📎',
'parrot': '🦜',
'partly_sunny': '⛅',
'partying_face': '🥳',
'paw_prints': '🐾',
'peach': '🍑',
'peacock': '🦚',
'peanuts': '🥜',
'pear': '🍐',
'pen': '🖊️',
'pencil': '📝',
'pencil2': '✏️',
'penguin': '🐧',
'pensive': '😔',
'people_hugging': '🫂',
'performing_arts': '🎭',
'persevere': '😣',
'person_fencing': '🤺',
'phone': '☎️',
'pick': '⛏️',
'pie': '🥧',
'pig': '🐷',
'pig2': '🐖',
'pig_nose': '🐽',
'pill': '💊',
'pinata': '🪅',
'pinched_fingers': '🤌',
'pinching_hand': '🤏',
'pineapple': '🍍',
'ping_pong': '🏓',
'pirate_flag': '🏴‍☠️',
'pizza': '🍕',
'plate_with_cutlery': '🍽️',
'pleading_face': '🥺',
'point_down': '👇',
'point_left': '👈',
'point_right': '👉',
'point_up': '☝️',
'point_up_2': '👆',
'police_car': '🚓',
'poodle': '🐩',
'poop': '💩',
'popcorn': '🍿',
'portugal': '🇵🇹',
'postal_horn': '📯',
'postbox': '📮',
'potato': '🥔',
'potted_plant': '🪴',
'poultry_leg': '🍗',
'pound': '💷',
'pout': '😡',
'pouting_cat': '😾',
'pray': '🙏',
'pretzel': '🥨',
'printer': '🖨️',
'punch': '👊',
'purple_circle': '🟣',
'purple_heart': '💜',
'purple_square': '🟪',
'pushpin': '📌',
'question': '❓',
'rabbit': '🐰',
'rabbit2': '🐇',
'raccoon': '🦝',
'racehorse': '🐎',
'racing_car': '🏎️',
'radio': '📻',
'radioactive': '☢️',
'rage': '😡',
'rainbow': '🌈',
'rainbow_flag': '🏳️‍🌈',
'raised_back_of_hand': '🤚',
'raised_eyebrow': '🤨',
'raised_hand': '✋',
'raised_hand_with_fingers_splayed': '🖐️',
'raised_hands': '🙌',
'raising_hand': '🙋',
'ramen': '🍜',
'rat': '🐀',
'razor': '🪒',
'receipt': '🧾',
'recycle': '♻️',
'red_car': '🚗',
'red_circle': '🔴',
'red_square': '🟥',
'relieved': '😌',
'reminder_ribbon': '🎗️',
'revolving_hearts': '💞',
'rhinoceros': '🦏',
'ribbon': '🎀',
'rice': '🍚',
'rice_ball': '🍙',
'rice_cracker': '🍘',
'right_anger_bubble': '🗯️',
'ringed_planet': '🪐',
'robot': '🤖',
'rocket': '🚀',
'rofl': '🤣',
'roll_eyes': '🙄',
'roll_of_paper': '🧻',
'roller_coaster': '🎢',
'roller_skate': '🛼',
'rooster': '🐓',
'rose': '🌹',
'rowboat': '🚣',
'ru': '🇷🇺',
'rugby_football': '🏉',
'running_shirt_with_sash': '🎽',
'safety_pin': '🧷',
'sailboat': '⛵',
'sake': '🍶',
'salt': '🧂',
'saluting_face': '🫡',
'sandwich': '🥪',
'satellite': '📡',
'satisfied': '😆',
'sauropod': '🦕',
'saxophone': '🎷',
'school': '🏫',
'scissors': '✂️',
'scorpion': '🦂',
'scream': '😱',
'scream_cat': '🙀',
'scroll': '📜',
'see_no_evil': '🙈',
'seedling': '🌱',
'selfie': '🤳',
'shallow_pan_of_food': '🥘',
'shamrock': '☘️',
'shark': '🦈',
'shaved_ice': '🍧',
'sheep': '🐑',
'shell': '🐚',
'shield': '🛡️',
'shinto_shrine': '⛩️',
'ship': '🚢',
'shit': '💩',
'shopping_cart': '🛒',
'shower': '🚿',
'shrimp': '🦐',
'shrug': '🤷',
'shushing_face': '🤫',
'skateboard': '🛹',
'ski': '🎿',
'skier': '⛷️',
'skull': '💀',
'skull_and_crossbones': '☠️',
'skunk': '🦨',
'sled': '🛷',
'sleeping': '😴',
'sleepy': '😪',
'slightly_frowning_face': '🙁',
'slightly_smiling_face': '🙂',
'slot_machine': '🎰',
'sloth': '🦥',
'small_blue_diamond': '🔹',
'small_orange_diamond': '🔸',
'small_red_triangle': '🔺',
'small_red_triangle_down': '🔻',
'smile': '😄',
'smile_cat': '😸',
'smiley': '😃',
'smiley_cat': '😺',
'smiling_face_with_tear': '🥲',
'smiling_face_with_three_hearts': '🥰',
'smiling_imp': '😈',
'smirk': '😏',
'smirk_cat': '😼',
'smoking': '🚬',
'snail': '🐌',
'snake': '🐍',
'sneezing_face': '🤧',
'snowboarder': '🏂',
'snowflake': '❄️',
'snowman': '⛄',
'snowman_with_snow': '☃️',
'soap': '🧼',
'sob': '😭',
'soccer': '⚽',
'softball': '🥎',
'sound': '🔉',
'space_invader': '👾',
'spaghetti': '🍝',
'sparkle': '❇️',
'sparkler': '🎇',
'sparkles': '✨',
'sparkling_heart': '💖',
'speak_no_evil': '🙊',
'speaker': '🔈',
'speaking_head': '🗣️',
'speech_balloon': '💬',
'spider': '🕷️',
'sponge': '🧽',
'spoon': '🥄',
'squid': '🦑',
'stadium': '🏟️',
'star': '⭐',
'star2': '🌟',
'star_struck': '🤩',
'statue_of_liberty': '🗽',
'steam_locomotive': '🚂',
'stethoscope': '🩺',
'stew': '🍲',
'stopwatch': '⏱️',
'straight_ruler': '📏',
'strawberry': '🍓',
'stuck_out_tongue': '😛',
'stuck_out_tongue_closed_eyes': '😝',
'stuck_out_tongue_winking_eye': '😜',
'stuffed_flatbread': '🥙',
'sun_behind_large_cloud': '🌥️',
'sun_behind_rain_cloud': '🌦️',
'sun_behind_small_cloud': '🌤️',
'sun_with_face': '🌞',
'sunflower': '🌻',
'sunglasses': '😎',
'sunny': '☀️',
'sunrise': '🌅',
'sunrise_over_mountains': '🌄',
'surfer': '🏄',
'sushi': '🍣',
'swan': '🦢',
'sweat': '😓',
'sweat_drops': '💦',
'sweat_smile': '😅',
'sweden': '🇸🇪',
'sweet_potato': '🍠',
'swimmer': '🏊',
'symbols': '🔣',
'syringe': '💉',
't-rex': '🦖',
'taco': '🌮',
'tada': '🎉',
'takeout_box': '🥡',
'tangerine': '🍊',
'taxi': '🚕',
'tea': '🍵',
'teapot': '🫖',
'telephone': '☎️',
'telephone_receiver': '📞',
'telescope': '🔭',
'tennis': '🎾',
'tent': '⛺',
'thinking': '🤔',
'thought_balloon': '💭',
'thumbsdown': '👎',
'thumbsup': '👍',
'ticket': '🎫',
'tiger': '🐯',
'tiger2': '🐅',
'timer_clock': '⏲️',
'tipping_hand_person': '💁',
'tired_face': '😫',
'toilet': '🚽',
'tokyo_tower': '🗼',
'tomato': '🍅',
'tongue': '👅',
'toolbox': '🧰',
'tooth': '🦷',
'toothbrush': '🪥',
'tornado': '🌪️',
'train2': '🚆',
'triangular_flag_on_post': '🚩',
'triangular_ruler': '📐',
'trident': '🔱',
'triumph': '😤',
'trophy': '🏆',
'tropical_drink': '🍹',
'tropical_fish': '🐠',
'truck': '🚚',
'trumpet': '🎺',
'tulip': '🌷',
'tumbler_glass': '🥃',
'turkey': '🦃',
'turtle': '🐢',
'tv': '📺',
'two_hearts': '💕',
'uk': '🇬🇧',
'umbrella': '☔',
'unamused': '😒',
'underage': '🔞',
'unicorn': '🦄',
'unlock': '🔓',
'up': '🆙',
'upside_down_face': '🙃',
'us': '🇺🇸',
'v': '✌️',
'vertical_traffic_light': '🚦',
'video_camera': '📹',
'video_game': '🎮',
'violin': '🎻',
'volcano': '🌋',
'volleyball': '🏐',
'vomiting_face': '🤮',
'vulcan_salute': '🖖',
'waffle': '🧇',
'waning_crescent_moon': '🌘',
'waning_gibbous_moon': '🌖',
'wastebasket': '🗑️',
'watch': '⌚',
'water_buffalo': '🐃',
'watermelon': '🍉',
'wave': '👋',
'wavy_dash': '〰️',
'waxing_crescent_moon': '🌒',
'waxing_gibbous_moon': '🌔',
'weary': '😩',
'wedding': '💒',
'weight_lifting': '🏋️',
'whale': '🐳',
'whale2': '🐋',
'white_check_mark': '✅',
'white_circle': '⚪',
'white_flag': '🏳️',
'white_heart': '🤍',
'white_large_square': '⬜',
'white_medium_square': '◻️',
'wilted_flower': '🥀',
'window': '🪟',
'wine_glass': '🍷',
'wink': '😉',
'wolf': '🐺',
'woman': '👩',
'woozy_face': '🥴',
'world_map': '🗺️',
'worried': '😟',
'wrench': '🔧',
'wrestling': '🤼',
'writing_hand': '✍️',
'x': '❌',
'yawning_face': '🥱',
'yellow_circle': '🟡',
'yellow_heart': '💛',
'yellow_square': '🟨',
'yen': '💴',
'yo_yo': '🪀',
'yum': '😋',
'zany_face': '🤪',
'zap': '⚡',
'zebra': '🦓',
'zipper_mouth_face': '🤐',
}