@sveltia/ui 0.65.1 → 0.65.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/emoji/emoji-suggestions.svelte +82 -9
- package/dist/components/emoji/emoji.d.ts +8 -5
- package/dist/components/emoji/emoji.js +99 -58
- package/dist/components/emoji/generated.d.ts +14 -0
- package/dist/components/emoji/generated.js +1921 -0
- package/dist/components/text-editor/shiki/generated.d.ts +1 -1
- package/dist/components/text-editor/shiki/generated.js +1 -1
- package/dist/typedefs.d.ts +3 -7
- package/dist/typedefs.js +3 -8
- package/package.json +2 -2
- package/dist/components/emoji/cache.d.ts +0 -3
- package/dist/components/emoji/cache.js +0 -96
- package/dist/components/emoji/loader.d.ts +0 -17
- package/dist/components/emoji/loader.js +0 -78
|
@@ -40,11 +40,17 @@
|
|
|
40
40
|
} = $props();
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
|
-
*
|
|
44
|
-
* also enforced in the stylesheet below.
|
|
43
|
+
* Width of the dropdown, also enforced in the stylesheet below.
|
|
45
44
|
*/
|
|
46
45
|
const LIST_WIDTH = 280;
|
|
47
|
-
|
|
46
|
+
/**
|
|
47
|
+
* How many suggestions are visible at once. The rest are reached by scrolling.
|
|
48
|
+
*/
|
|
49
|
+
const VISIBLE_ROWS = 5;
|
|
50
|
+
/**
|
|
51
|
+
* Height to assume until a row has been measured, so the first open is positioned sensibly.
|
|
52
|
+
*/
|
|
53
|
+
const FALLBACK_MAX_HEIGHT = 180;
|
|
48
54
|
/**
|
|
49
55
|
* Gap between the dropdown and the caret, and the minimum margin to the viewport edges.
|
|
50
56
|
*/
|
|
@@ -93,6 +99,23 @@
|
|
|
93
99
|
|
|
94
100
|
const open = $derived(!!trigger && !!candidates.length);
|
|
95
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Height of one suggestion, measured rather than assumed so the dropdown still shows exactly
|
|
104
|
+
* {@link VISIBLE_ROWS} of them whatever the theme makes a row.
|
|
105
|
+
* @type {number}
|
|
106
|
+
*/
|
|
107
|
+
let rowHeight = $state(0);
|
|
108
|
+
/**
|
|
109
|
+
* The dropdown’s own vertical padding and border, which sit outside the rows. `box-sizing` is
|
|
110
|
+
* `border-box`, so `max-height` has to cover them for the rows to get their full share.
|
|
111
|
+
* @type {number}
|
|
112
|
+
*/
|
|
113
|
+
let listChrome = $state(0);
|
|
114
|
+
|
|
115
|
+
const listMaxHeight = $derived(
|
|
116
|
+
rowHeight ? rowHeight * VISIBLE_ROWS + listChrome : FALLBACK_MAX_HEIGHT,
|
|
117
|
+
);
|
|
118
|
+
|
|
96
119
|
/**
|
|
97
120
|
* Position of the dropdown, flipped above the caret and clamped to the viewport as needed.
|
|
98
121
|
*
|
|
@@ -108,7 +131,7 @@
|
|
|
108
131
|
const { innerWidth, innerHeight } = window;
|
|
109
132
|
const spaceBelow = innerHeight - anchorRect.bottom;
|
|
110
133
|
const spaceAbove = anchorRect.top;
|
|
111
|
-
const flipped = spaceBelow <
|
|
134
|
+
const flipped = spaceBelow < listMaxHeight + VIEWPORT_MARGIN && spaceAbove > spaceBelow;
|
|
112
135
|
const rtl = document.dir === 'rtl';
|
|
113
136
|
const anchorLeft = rtl ? anchorRect.right - LIST_WIDTH : anchorRect.left;
|
|
114
137
|
|
|
@@ -120,7 +143,7 @@
|
|
|
120
143
|
)}px`,
|
|
121
144
|
maxHeight: `${Math.round(
|
|
122
145
|
Math.min(
|
|
123
|
-
|
|
146
|
+
listMaxHeight,
|
|
124
147
|
(flipped ? spaceAbove : spaceBelow) - LIST_OFFSET - VIEWPORT_MARGIN,
|
|
125
148
|
),
|
|
126
149
|
)}px`,
|
|
@@ -247,11 +270,34 @@
|
|
|
247
270
|
return true;
|
|
248
271
|
};
|
|
249
272
|
|
|
250
|
-
// Move the dropdown to the top layer, so it’s not clipped by anything around the field
|
|
273
|
+
// Move the dropdown to the top layer, so it’s not clipped by anything around the field, then
|
|
274
|
+
// measure a row. The measurement has to happen after the popover is shown, because until then the
|
|
275
|
+
// element isn’t rendered at all and everything measures zero. A row’s height comes from the
|
|
276
|
+
// theme’s control height plus its padding, so it’s read back rather than assumed.
|
|
251
277
|
$effect(() => {
|
|
252
|
-
|
|
278
|
+
void candidates;
|
|
279
|
+
|
|
280
|
+
if (!listElement) {
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (!listElement.matches(':popover-open')) {
|
|
253
285
|
listElement.showPopover?.();
|
|
254
286
|
}
|
|
287
|
+
|
|
288
|
+
const row = listElement.querySelector('.option');
|
|
289
|
+
|
|
290
|
+
if (row) {
|
|
291
|
+
const { paddingTop, paddingBottom, borderTopWidth, borderBottomWidth } =
|
|
292
|
+
getComputedStyle(listElement);
|
|
293
|
+
|
|
294
|
+
rowHeight = row.getBoundingClientRect().height;
|
|
295
|
+
listChrome =
|
|
296
|
+
Number.parseFloat(paddingTop) +
|
|
297
|
+
Number.parseFloat(paddingBottom) +
|
|
298
|
+
Number.parseFloat(borderTopWidth) +
|
|
299
|
+
Number.parseFloat(borderBottomWidth);
|
|
300
|
+
}
|
|
255
301
|
});
|
|
256
302
|
|
|
257
303
|
// Advertise that typing here can bring up predictions, for as long as the autocomplete is
|
|
@@ -301,11 +347,15 @@
|
|
|
301
347
|
};
|
|
302
348
|
});
|
|
303
349
|
|
|
304
|
-
// Keep the highlighted suggestion visible while the user arrows through a long list
|
|
350
|
+
// Keep the highlighted suggestion visible while the user arrows through a long list. The scroll
|
|
351
|
+
// has to be instant: an inherited `scroll-behavior: smooth` otherwise animates it, and the
|
|
352
|
+
// animation never lands while the list is in the top layer, leaving the highlight off screen.
|
|
305
353
|
$effect(() => {
|
|
306
354
|
void selectedIndex;
|
|
307
355
|
|
|
308
|
-
listElement
|
|
356
|
+
listElement
|
|
357
|
+
?.querySelector('[aria-selected="true"]')
|
|
358
|
+
?.scrollIntoView({ block: 'nearest', behavior: 'instant' });
|
|
309
359
|
});
|
|
310
360
|
|
|
311
361
|
onMount(() => {
|
|
@@ -323,12 +373,35 @@
|
|
|
323
373
|
}
|
|
324
374
|
};
|
|
325
375
|
|
|
376
|
+
/**
|
|
377
|
+
* Dismiss the list when the user presses somewhere else on the page.
|
|
378
|
+
*
|
|
379
|
+
* The popover is `manual` rather than `auto`, so the platform’s own light dismiss is off: an
|
|
380
|
+
* `auto` popover also closes itself on Escape, which would fight the Escape handling here, and
|
|
381
|
+
* it would close on a press inside the field the list belongs to, where the caret moving is
|
|
382
|
+
* what should decide. This covers the one behavior worth borrowing.
|
|
383
|
+
* @param {PointerEvent} event `pointerdown` event.
|
|
384
|
+
*/
|
|
385
|
+
const onPointerDown = ({ target }) => {
|
|
386
|
+
const node = /** @type {Node} */ (target);
|
|
387
|
+
|
|
388
|
+
// A press on the list is a choice, not a dismissal, and this runs before the option’s own
|
|
389
|
+
// handler; a press in the field is left to the caret to sort out
|
|
390
|
+
if (!open || listElement?.contains(node) || ariaOwner?.contains(node)) {
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
close();
|
|
395
|
+
};
|
|
396
|
+
|
|
326
397
|
window.addEventListener('scroll', reposition, { capture: true, passive: true });
|
|
327
398
|
window.addEventListener('resize', reposition, { passive: true });
|
|
399
|
+
document.addEventListener('pointerdown', onPointerDown, { capture: true });
|
|
328
400
|
|
|
329
401
|
return () => {
|
|
330
402
|
window.removeEventListener('scroll', reposition, { capture: true });
|
|
331
403
|
window.removeEventListener('resize', reposition);
|
|
404
|
+
document.removeEventListener('pointerdown', onPointerDown, { capture: true });
|
|
332
405
|
};
|
|
333
406
|
});
|
|
334
407
|
</script>
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
2
|
+
* @import { EmojiEntry } from '../../typedefs';
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
5
|
* Regular expression that matches an emoji shortcode being typed at the end of a line, like `:smi`.
|
|
6
6
|
* The colon must be at the beginning of the text or preceded by a whitespace or an opening bracket,
|
|
7
7
|
* so a colon in the middle of a word, as in `https://` or `12:34`, doesn’t trigger the suggestions.
|
|
8
|
+
* The query is bounded to keep a runaway line from being searched for, at a length that still
|
|
9
|
+
* accommodates the longest published shortcode.
|
|
8
10
|
*/
|
|
9
11
|
export const EMOJI_TRIGGER_REGEX: RegExp;
|
|
10
12
|
/**
|
|
11
|
-
* Maximum number of emoji suggestions
|
|
13
|
+
* Maximum number of emoji suggestions offered, matching what Discord shows. The dropdown displays
|
|
14
|
+
* five at a time and scrolls through the rest, so this only bounds how far a query can be explored
|
|
15
|
+
* — a single letter otherwise matches over a thousand emojis, all rendered on every keystroke.
|
|
12
16
|
*/
|
|
13
|
-
export const MAX_EMOJI_SUGGESTIONS:
|
|
14
|
-
export function parseEmojiData(data:
|
|
17
|
+
export const MAX_EMOJI_SUGGESTIONS: 50;
|
|
18
|
+
export function parseEmojiData(data: string): EmojiEntry[];
|
|
15
19
|
export function loadEmojiList(): Promise<EmojiEntry[]>;
|
|
16
20
|
/**
|
|
17
21
|
* Rank given when there is no match at all. Higher than any real rank, so an unmatched emoji sorts
|
|
@@ -27,5 +31,4 @@ export function getEmojiMatchRank({ name, aliases }: EmojiEntry, query: string):
|
|
|
27
31
|
export function searchEmojis(query: string): EmojiEntry[];
|
|
28
32
|
export function getEmojiInsertText(emoji: string, textAfterCaret: string): string;
|
|
29
33
|
export function detectEmojiTrigger(textBeforeCaret: string): string | undefined;
|
|
30
|
-
import type { EmojiData } from '../../typedefs';
|
|
31
34
|
import type { EmojiEntry } from '../../typedefs';
|
|
@@ -1,70 +1,75 @@
|
|
|
1
|
-
import { cacheEmojiData, getCachedEmojiData } from './cache.js';
|
|
2
|
-
import { getEmojiDataLoader } from './loader.js';
|
|
3
|
-
|
|
4
1
|
/**
|
|
5
|
-
* @import {
|
|
2
|
+
* @import { EmojiEntry } from '../../typedefs';
|
|
6
3
|
*/
|
|
7
4
|
|
|
8
5
|
/**
|
|
9
6
|
* Regular expression that matches an emoji shortcode being typed at the end of a line, like `:smi`.
|
|
10
7
|
* The colon must be at the beginning of the text or preceded by a whitespace or an opening bracket,
|
|
11
8
|
* so a colon in the middle of a word, as in `https://` or `12:34`, doesn’t trigger the suggestions.
|
|
9
|
+
* The query is bounded to keep a runaway line from being searched for, at a length that still
|
|
10
|
+
* accommodates the longest published shortcode.
|
|
12
11
|
*/
|
|
13
|
-
export const EMOJI_TRIGGER_REGEX = /(?<=^|[\s([{"'«])(?::)(?<query>[a-zA-Z0-9_+-]{1,
|
|
12
|
+
export const EMOJI_TRIGGER_REGEX = /(?<=^|[\s([{"'«])(?::)(?<query>[a-zA-Z0-9_+-]{1,64})$/;
|
|
14
13
|
|
|
15
14
|
/**
|
|
16
|
-
* Maximum number of emoji suggestions
|
|
15
|
+
* Maximum number of emoji suggestions offered, matching what Discord shows. The dropdown displays
|
|
16
|
+
* five at a time and scrolls through the rest, so this only bounds how far a query can be explored
|
|
17
|
+
* — a single letter otherwise matches over a thousand emojis, all rendered on every keystroke.
|
|
17
18
|
*/
|
|
18
|
-
export const MAX_EMOJI_SUGGESTIONS =
|
|
19
|
+
export const MAX_EMOJI_SUGGESTIONS = 50;
|
|
19
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Separator between the words of a shortcode. Most use an underscore, as in `party_popper`, but the
|
|
23
|
+
* flags and the compound people use a hyphen, as in `flag-ca` and `man-woman-girl`.
|
|
24
|
+
*/
|
|
25
|
+
const WORD_SEPARATOR_REGEX = /[-_]/;
|
|
20
26
|
/**
|
|
21
27
|
* Cached emoji list. This is `undefined` until {@link loadEmojiList} resolves for the first time.
|
|
22
28
|
* @type {EmojiEntry[] | undefined}
|
|
23
29
|
*/
|
|
24
30
|
let emojiList;
|
|
25
31
|
/**
|
|
26
|
-
* In-flight or completed loader for {@link emojiList}, so the data is only
|
|
32
|
+
* In-flight or completed loader for {@link emojiList}, so the data is only parsed once.
|
|
27
33
|
* @type {Promise<EmojiEntry[]> | undefined}
|
|
28
34
|
*/
|
|
29
35
|
let loader;
|
|
30
36
|
|
|
31
37
|
/**
|
|
32
|
-
* Convert the
|
|
38
|
+
* Convert the generated emoji data into a searchable list.
|
|
33
39
|
* @internal
|
|
34
|
-
* @param {
|
|
35
|
-
* followed by any keywords.
|
|
40
|
+
* @param {string} data Emoji data, one line per emoji. See `generated.js` for the format.
|
|
36
41
|
* @returns {EmojiEntry[]} Emoji list.
|
|
37
42
|
*/
|
|
38
43
|
export const parseEmojiData = (data) =>
|
|
39
|
-
|
|
40
|
-
emoji,
|
|
41
|
-
name,
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
data.split('\n').map((line) => {
|
|
45
|
+
const [emoji, shortcodes, keywords = ''] = line.split('\t');
|
|
46
|
+
const [name, ...otherShortcodes] = shortcodes.split(' ');
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
emoji,
|
|
50
|
+
name,
|
|
51
|
+
// The alternative shortcodes come first, because they’re what the user might type, while the
|
|
52
|
+
// keywords merely describe the emoji
|
|
53
|
+
aliases: [...otherShortcodes, ...(keywords ? keywords.split(' ') : [])],
|
|
54
|
+
};
|
|
55
|
+
});
|
|
45
56
|
|
|
46
57
|
/**
|
|
47
|
-
* Load the emoji list
|
|
58
|
+
* Load the emoji list.
|
|
48
59
|
*
|
|
49
|
-
* The data is
|
|
50
|
-
* of the
|
|
51
|
-
* shortcode the user typed stays as plain text.
|
|
60
|
+
* The data is imported on demand rather than up front, so a bundler that can split it out keeps it
|
|
61
|
+
* out of the initial payload — most sessions never type a shortcode. A failure here is not worth
|
|
62
|
+
* surfacing: no suggestions are ever shown, and the shortcode the user typed stays as plain text.
|
|
52
63
|
* @returns {Promise<EmojiEntry[]>} Emoji list, or an empty list if the data can’t be obtained.
|
|
53
64
|
*/
|
|
54
65
|
export const loadEmojiList = async () => {
|
|
55
66
|
loader ??= (async () => {
|
|
56
67
|
try {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (!data) {
|
|
60
|
-
data = await getEmojiDataLoader()();
|
|
61
|
-
// Don’t make the caller wait on the write
|
|
62
|
-
cacheEmojiData(data);
|
|
63
|
-
}
|
|
68
|
+
const { EMOJI_DATA } = await import('./generated.js');
|
|
64
69
|
|
|
65
|
-
emojiList = parseEmojiData(
|
|
70
|
+
emojiList = parseEmojiData(EMOJI_DATA);
|
|
66
71
|
} catch (ex) {
|
|
67
|
-
// Allow a later attempt to retry, so a transient
|
|
72
|
+
// Allow a later attempt to retry, so a transient chunk load failure isn’t permanent
|
|
68
73
|
loader = undefined;
|
|
69
74
|
emojiList = [];
|
|
70
75
|
// eslint-disable-next-line no-console
|
|
@@ -84,71 +89,78 @@ export const loadEmojiList = async () => {
|
|
|
84
89
|
export const NO_EMOJI_MATCH = 9;
|
|
85
90
|
|
|
86
91
|
/**
|
|
87
|
-
* Get how well an emoji’s
|
|
92
|
+
* Get how well an emoji’s canonical shortcode matches the given query. A lower rank means a better
|
|
93
|
+
* match.
|
|
88
94
|
*
|
|
89
|
-
* The
|
|
90
|
-
*
|
|
91
|
-
* spanning a word boundary
|
|
95
|
+
* A match has to start at a word boundary. The shortcode is matched word by word rather than only
|
|
96
|
+
* as a whole, so a partly typed `:polar` reaches `polar_bear` just as `:polar_bear` does, and the
|
|
97
|
+
* whole shortcode is tested as well, so a query spanning a word boundary like `:polar_b` still
|
|
98
|
+
* matches. What this rules out is a match starting mid-word, which is nearly always coincidental:
|
|
99
|
+
* `:age` would otherwise turn up `mage`, `bagel`, `baggage`, `pager` and `package`.
|
|
92
100
|
* @internal
|
|
93
|
-
* @param {string} name Canonical
|
|
101
|
+
* @param {string} name Canonical shortcode.
|
|
94
102
|
* @param {string} query Lower-cased search query without the leading colon.
|
|
95
103
|
* @returns {number} Rank, or {@link NO_EMOJI_MATCH}.
|
|
96
104
|
*/
|
|
97
105
|
export const getEmojiNameMatchRank = (name, query) => {
|
|
98
|
-
const words = name.split(
|
|
106
|
+
const words = name.split(WORD_SEPARATOR_REGEX);
|
|
99
107
|
|
|
100
108
|
if (name === query) {
|
|
101
109
|
return 0;
|
|
102
110
|
}
|
|
103
111
|
|
|
104
|
-
|
|
112
|
+
// What the shortcode leads with is what the emoji mostly is, so `heart_eyes` is a better `:heart`
|
|
113
|
+
// match than `sparkling_heart`, where the word merely turns up along the way. The whole leading
|
|
114
|
+
// word has to match: `japanese_castle` is not what `:japan` is after, nor `crystal_ball` `:cry`.
|
|
115
|
+
if (name.startsWith(query) && WORD_SEPARATOR_REGEX.test(name.charAt(query.length))) {
|
|
105
116
|
return 1;
|
|
106
117
|
}
|
|
107
118
|
|
|
108
|
-
if (
|
|
109
|
-
return
|
|
119
|
+
if (words.includes(query)) {
|
|
120
|
+
return 2;
|
|
110
121
|
}
|
|
111
122
|
|
|
112
|
-
|
|
113
|
-
|
|
123
|
+
// The whole shortcode is tested too, so a query spanning a word boundary like `:polar_b` matches
|
|
124
|
+
if (name.startsWith(query) || words.some((word) => word.startsWith(query))) {
|
|
125
|
+
return 4;
|
|
114
126
|
}
|
|
115
127
|
|
|
116
128
|
return NO_EMOJI_MATCH;
|
|
117
129
|
};
|
|
118
130
|
|
|
119
131
|
/**
|
|
120
|
-
* Get how well an emoji’s keywords match the given query. A lower rank
|
|
121
|
-
* ranks interleave with {@link getEmojiNameMatchRank}’s: an exact keyword
|
|
122
|
-
* of the
|
|
132
|
+
* Get how well an emoji’s alternative shortcodes and keywords match the given query. A lower rank
|
|
133
|
+
* means a better match. The ranks interleave with {@link getEmojiNameMatchRank}’s: an exact keyword
|
|
134
|
+
* sits between a whole word of the shortcode and a partial one.
|
|
123
135
|
* @internal
|
|
124
|
-
* @param {string[]} aliases Lower-cased alternative keywords.
|
|
136
|
+
* @param {string[]} aliases Lower-cased alternative shortcodes and keywords.
|
|
125
137
|
* @param {string} query Lower-cased search query without the leading colon.
|
|
126
138
|
* @returns {number} Rank, or {@link NO_EMOJI_MATCH}.
|
|
127
139
|
*/
|
|
128
140
|
export const getEmojiAliasMatchRank = (aliases, query) => {
|
|
129
141
|
if (aliases.includes(query)) {
|
|
130
|
-
return
|
|
142
|
+
return 3;
|
|
131
143
|
}
|
|
132
144
|
|
|
133
145
|
if (aliases.some((alias) => alias.startsWith(query))) {
|
|
134
|
-
return
|
|
146
|
+
return 5;
|
|
135
147
|
}
|
|
136
148
|
|
|
137
149
|
return NO_EMOJI_MATCH;
|
|
138
150
|
};
|
|
139
151
|
|
|
140
152
|
/**
|
|
141
|
-
* Get how well an emoji matches the given query, as the best of its
|
|
142
|
-
*
|
|
153
|
+
* Get how well an emoji matches the given query, as the best of its shortcode and keyword ranks
|
|
154
|
+
* plus the shortcode rank on its own.
|
|
143
155
|
*
|
|
144
|
-
* The
|
|
145
|
-
* while the keywords are merely associated with it. Many emojis share a keyword — `
|
|
146
|
-
*
|
|
147
|
-
* `
|
|
156
|
+
* The shortcode rank is kept so it can break ties, because the shortcode is what the emoji is
|
|
157
|
+
* called while the keywords are merely associated with it. Many emojis share a keyword — `canada`
|
|
158
|
+
* belongs to 🇨🇦 and 🍁 alike — and the one that also carries the query in its shortcode,
|
|
159
|
+
* `flag-ca`, is the one the user is after.
|
|
148
160
|
* @internal
|
|
149
161
|
* @param {EmojiEntry} entry Emoji entry.
|
|
150
162
|
* @param {string} query Lower-cased search query without the leading colon.
|
|
151
|
-
* @returns {{ rank: number, nameRank: number }} Best rank and
|
|
163
|
+
* @returns {{ rank: number, nameRank: number }} Best rank and shortcode rank, either of which is
|
|
152
164
|
* {@link NO_EMOJI_MATCH} when there is nothing to match.
|
|
153
165
|
*/
|
|
154
166
|
export const getEmojiMatchRank = ({ name, aliases }, query) => {
|
|
@@ -158,6 +170,29 @@ export const getEmojiMatchRank = ({ name, aliases }, query) => {
|
|
|
158
170
|
return { rank: Math.min(nameRank, aliasRank), nameRank };
|
|
159
171
|
};
|
|
160
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Get how central a match is to the emoji, to separate emojis that match equally well. A lower
|
|
175
|
+
* number means the query is more of what the emoji is about.
|
|
176
|
+
*
|
|
177
|
+
* For a shortcode match, that’s how much of the shortcode the query accounts for: `red_heart` is
|
|
178
|
+
* more of a `:heart` than `smiling_face_with_heart_eyes` is. For a keyword match, it’s how early
|
|
179
|
+
* the keyword comes — the alternative shortcodes are listed first, then the words of the Unicode
|
|
180
|
+
* name in the order it spells them out, which is roughly most to least defining.
|
|
181
|
+
* @internal
|
|
182
|
+
* @param {EmojiEntry} entry Emoji entry.
|
|
183
|
+
* @param {string} query Lower-cased search query without the leading colon.
|
|
184
|
+
* @returns {number} Centrality, comparable only between equally ranked emojis.
|
|
185
|
+
*/
|
|
186
|
+
const getMatchCentrality = ({ name, aliases }, query) => {
|
|
187
|
+
if (getEmojiNameMatchRank(name, query) < NO_EMOJI_MATCH) {
|
|
188
|
+
return name.split(WORD_SEPARATOR_REGEX).length;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const index = aliases.findIndex((alias) => alias === query || alias.startsWith(query));
|
|
192
|
+
|
|
193
|
+
return (index > -1 ? index : aliases.length) * 100 + aliases.length;
|
|
194
|
+
};
|
|
195
|
+
|
|
161
196
|
/**
|
|
162
197
|
* Search the loaded emoji list for the given query. This returns an empty list unless
|
|
163
198
|
* {@link loadEmojiList} has been resolved beforehand.
|
|
@@ -174,11 +209,17 @@ export const searchEmojis = (query) => {
|
|
|
174
209
|
|
|
175
210
|
return (
|
|
176
211
|
emojiList
|
|
177
|
-
.map((entry) =>
|
|
212
|
+
.map((entry) => {
|
|
213
|
+
const { rank, nameRank } = getEmojiMatchRank(entry, normalizedQuery);
|
|
214
|
+
|
|
215
|
+
return { entry, rank, nameRank, centrality: getMatchCentrality(entry, normalizedQuery) };
|
|
216
|
+
})
|
|
178
217
|
.filter(({ rank }) => rank < NO_EMOJI_MATCH)
|
|
179
|
-
// Equally ranked emojis are settled by the
|
|
180
|
-
//
|
|
181
|
-
.
|
|
218
|
+
// Equally ranked emojis are settled by the shortcode, then by how central the match is to the
|
|
219
|
+
// emoji, then by the published order, which is the Unicode order — `Array.prototype.sort()`
|
|
220
|
+
// is stable. That last resort roughly groups the like with the like, so a tie between two
|
|
221
|
+
// country flags or two smileys at least comes out in a familiar order.
|
|
222
|
+
.sort((a, b) => a.rank - b.rank || a.nameRank - b.nameRank || a.centrality - b.centrality)
|
|
182
223
|
.slice(0, MAX_EMOJI_SUGGESTIONS)
|
|
183
224
|
.map(({ entry }) => entry)
|
|
184
225
|
);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Emoji list from `emoji-data` v16.0.0, in the Unicode order the dataset publishes.
|
|
3
|
+
*
|
|
4
|
+
* One line per emoji, made up of tab-separated fields: the emoji character, its shortcodes, and any
|
|
5
|
+
* further searchable words taken from its Unicode name. Multiple shortcodes or keywords within a
|
|
6
|
+
* field are separated by a space, and the last field is left out when there are no extra keywords.
|
|
7
|
+
* The first shortcode is the canonical one, the one shown alongside the emoji in the suggestions.
|
|
8
|
+
*
|
|
9
|
+
* It’s a single string rather than an object so that it costs one line per emoji in the bundle
|
|
10
|
+
* instead of a few hundred bytes of punctuation, and so that nothing is parsed until the first
|
|
11
|
+
* shortcode is actually typed.
|
|
12
|
+
* @see https://github.com/iamcal/emoji-data
|
|
13
|
+
*/
|
|
14
|
+
export const EMOJI_DATA: "😀\tgrinning\tface\n😃\tsmiley\tsmiling face open mouth\n😄\tsmile\tsmiling face open mouth eyes\n😁\tgrin\tgrinning face smiling eyes\n😆\tlaughing satisfied\tsmiling face open mouth tightly-closed eyes\n😅\tsweat_smile\tsmiling face open mouth cold\n🤣\trolling_on_the_floor_laughing\n😂\tjoy\tface tears\n🙂\tslightly_smiling_face\n🙃\tupside_down_face\tupside-down\n🫠\tmelting_face\n😉\twink\twinking face\n😊\tblush\tsmiling face eyes\n😇\tinnocent\tsmiling face halo\n🥰\tsmiling_face_with_3_hearts\teyes three\n😍\theart_eyes\tsmiling face heart-shaped\n🤩\tstar-struck grinning_face_with_star_eyes\n😘\tkissing_heart\tface throwing kiss\n😗\tkissing\tface\n☺️\trelaxed\twhite smiling face\n😚\tkissing_closed_eyes\tface\n😙\tkissing_smiling_eyes\tface\n🥲\tsmiling_face_with_tear\n😋\tyum\tface savouring delicious food\n😛\tstuck_out_tongue\tface stuck-out\n😜\tstuck_out_tongue_winking_eye\tface stuck-out\n🤪\tzany_face grinning_face_with_one_large_and_one_small_eye\n😝\tstuck_out_tongue_closed_eyes\tface stuck-out tightly-closed\n🤑\tmoney_mouth_face\tmoney-mouth\n🤗\thugging_face\n🤭\tface_with_hand_over_mouth smiling_face_with_smiling_eyes_and_hand_covering_mouth\n🫢\tface_with_open_eyes_and_hand_over_mouth\n🫣\tface_with_peeking_eye\n🤫\tshushing_face face_with_finger_covering_closed_lips\n🤔\tthinking_face\n🫡\tsaluting_face\n🤐\tzipper_mouth_face\tzipper-mouth\n🤨\tface_with_raised_eyebrow face_with_one_eyebrow_raised\n😐\tneutral_face\n😑\texpressionless\tface\n😶\tno_mouth\tface without\n🫥\tdotted_line_face\n😶🌫️\tface_in_clouds\n😏\tsmirk\tsmirking face\n😒\tunamused\tface\n🙄\tface_with_rolling_eyes\n😬\tgrimacing\tface\n😮💨\tface_exhaling\n🤥\tlying_face\n🫨\tshaking_face\n🙂↔️\thead_shaking_horizontally\n🙂↕️\thead_shaking_vertically\n😌\trelieved\tface\n😔\tpensive\tface\n😪\tsleepy\tface\n🤤\tdrooling_face\n😴\tsleeping\tface\n\tface_with_bags_under_eyes\n😷\tmask\tface medical\n🤒\tface_with_thermometer\n🤕\tface_with_head_bandage\thead-bandage\n🤢\tnauseated_face\n🤮\tface_vomiting face_with_open_mouth_vomiting\n🤧\tsneezing_face\n🥵\thot_face\toverheated\n🥶\tcold_face\tfreezing\n🥴\twoozy_face\tuneven eyes wavy mouth\n😵\tdizzy_face\n😵💫\tface_with_spiral_eyes\n🤯\texploding_head shocked_face_with_exploding_head\n🤠\tface_with_cowboy_hat\n🥳\tpartying_face\tparty horn hat\n🥸\tdisguised_face\n😎\tsunglasses\tsmiling face\n🤓\tnerd_face\n🧐\tface_with_monocle\n😕\tconfused\tface\n🫤\tface_with_diagonal_mouth\n😟\tworried\tface\n🙁\tslightly_frowning_face\n☹️\twhite_frowning_face\n😮\topen_mouth\tface\n😯\thushed\tface\n😲\tastonished\tface\n😳\tflushed\tface\n🥺\tpleading_face\teyes\n🥹\tface_holding_back_tears\n😦\tfrowning\tface open mouth\n😧\tanguished\tface\n😨\tfearful\tface\n😰\tcold_sweat\tface open mouth\n😥\tdisappointed_relieved\tbut face\n😢\tcry\tcrying face\n😭\tsob\tloudly crying face\n😱\tscream\tface screaming fear\n😖\tconfounded\tface\n😣\tpersevere\tpersevering face\n😞\tdisappointed\tface\n😓\tsweat\tface cold\n😩\tweary\tface\n😫\ttired_face\n🥱\tyawning_face\n😤\ttriumph\tface look\n😡\trage\tpouting face\n😠\tangry\tface\n🤬\tface_with_symbols_on_mouth serious_face_with_symbols_covering_mouth\n😈\tsmiling_imp\tface horns\n👿\timp\n💀\tskull\n☠️\tskull_and_crossbones\n💩\thankey poop shit\tpile poo\n🤡\tclown_face\n👹\tjapanese_ogre\n👺\tjapanese_goblin\n👻\tghost\n👽\talien\textraterrestrial\n👾\tspace_invader\talien monster\n🤖\trobot_face\n😺\tsmiley_cat\tsmiling face open mouth\n😸\tsmile_cat\tgrinning face smiling eyes\n😹\tjoy_cat\tface tears\n😻\theart_eyes_cat\tsmiling face heart-shaped\n😼\tsmirk_cat\tface wry smile\n😽\tkissing_cat\tface closed eyes\n🙀\tscream_cat\tweary face\n😿\tcrying_cat_face\n😾\tpouting_cat\tface\n🙈\tsee_no_evil\tsee-no-evil monkey\n🙉\thear_no_evil\thear-no-evil monkey\n🙊\tspeak_no_evil\tspeak-no-evil monkey\n💌\tlove_letter\n💘\tcupid\theart arrow\n💝\tgift_heart\tribbon\n💖\tsparkling_heart\n💗\theartpulse\tgrowing heart\n💓\theartbeat\tbeating heart\n💞\trevolving_hearts\n💕\ttwo_hearts\n💟\theart_decoration\n❣️\theavy_heart_exclamation_mark_ornament\n💔\tbroken_heart\n❤️🔥\theart_on_fire\n❤️🩹\tmending_heart\n❤️\theart\theavy black\n🩷\tpink_heart\n🧡\torange_heart\n💛\tyellow_heart\n💚\tgreen_heart\n💙\tblue_heart\n🩵\tlight_blue_heart\n💜\tpurple_heart\n🤎\tbrown_heart\n🖤\tblack_heart\n🩶\tgrey_heart\n🤍\twhite_heart\n💋\tkiss\tmark\n💯\t100\thundred points symbol\n💢\tanger\tsymbol\n💥\tboom collision\tsymbol\n💫\tdizzy\tsymbol\n💦\tsweat_drops\tsplashing symbol\n💨\tdash\tsymbol\n🕳️\thole\n💬\tspeech_balloon\n👁️🗨️\teye-in-speech-bubble\n🗨️\tleft_speech_bubble\n🗯️\tright_anger_bubble\n💭\tthought_balloon\n💤\tzzz\tsleeping symbol\n👋\twave\twaving hand sign\n🤚\traised_back_of_hand\n🖐️\traised_hand_with_fingers_splayed\n✋\thand raised_hand\n🖖\tspock-hand\traised part between middle ring fingers\n🫱\trightwards_hand\n🫲\tleftwards_hand\n🫳\tpalm_down_hand\n🫴\tpalm_up_hand\n🫷\tleftwards_pushing_hand\n🫸\trightwards_pushing_hand\n👌\tok_hand\tsign\n🤌\tpinched_fingers\n🤏\tpinching_hand\n✌️\tv\tvictory hand\n🤞\tcrossed_fingers hand_with_index_and_middle_fingers_crossed\n🫰\thand_with_index_finger_and_thumb_crossed\n🤟\ti_love_you_hand_sign\n🤘\tthe_horns sign_of_the_horns\n🤙\tcall_me_hand\n👈\tpoint_left\twhite pointing backhand index\n👉\tpoint_right\twhite pointing backhand index\n👆\tpoint_up_2\twhite pointing backhand index\n🖕\tmiddle_finger reversed_hand_with_middle_finger_extended\n👇\tpoint_down\twhite pointing backhand index\n☝️\tpoint_up\twhite pointing index\n🫵\tindex_pointing_at_the_viewer\n👍\t+1 thumbsup\tthumbs up sign\n👎\t-1 thumbsdown\tthumbs down sign\n✊\tfist\traised\n👊\tfacepunch punch\tfisted hand sign\n🤛\tleft-facing_fist\tleft-facing\n🤜\tright-facing_fist\tright-facing\n👏\tclap\tclapping hands sign\n🙌\traised_hands\tperson raising both celebration\n🫶\theart_hands\n👐\topen_hands\tsign\n🤲\tpalms_up_together\n🤝\thandshake\n🙏\tpray\tperson folded hands\n✍️\twriting_hand\n💅\tnail_care\tpolish\n🤳\tselfie\n💪\tmuscle\tflexed biceps\n🦾\tmechanical_arm\n🦿\tmechanical_leg\n🦵\tleg\n🦶\tfoot\n👂\tear\n🦻\tear_with_hearing_aid\n👃\tnose\n🧠\tbrain\n🫀\tanatomical_heart\n🫁\tlungs\n🦷\ttooth\n🦴\tbone\n👀\teyes\n👁️\teye\n👅\ttongue\n👄\tlips\tmouth\n🫦\tbiting_lip\n👶\tbaby\n🧒\tchild\n👦\tboy\n👧\tgirl\n🧑\tadult\n👱\tperson_with_blond_hair\n👨\tman\n🧔\tbearded_person\n🧔♂️\tman_with_beard\n🧔♀️\twoman_with_beard\n👨🦰\tred_haired_man\thair\n👨🦱\tcurly_haired_man\thair\n👨🦳\twhite_haired_man\thair\n👨🦲\tbald_man\n👩\twoman\n👩🦰\tred_haired_woman\thair\n🧑🦰\tred_haired_person\thair\n👩🦱\tcurly_haired_woman\thair\n🧑🦱\tcurly_haired_person\thair\n👩🦳\twhite_haired_woman\thair\n🧑🦳\twhite_haired_person\thair\n👩🦲\tbald_woman\n🧑🦲\tbald_person\n👱♀️\tblond-haired-woman\thair\n👱♂️\tblond-haired-man\thair\n🧓\tolder_adult\n👴\tolder_man\n👵\tolder_woman\n🙍\tperson_frowning\n🙍♂️\tman-frowning\n🙍♀️\twoman-frowning\n🙎\tperson_with_pouting_face\n🙎♂️\tman-pouting\n🙎♀️\twoman-pouting\n🙅\tno_good\tface gesture\n🙅♂️\tman-gesturing-no\n🙅♀️\twoman-gesturing-no\n🙆\tok_woman\tface gesture\n🙆♂️\tman-gesturing-ok\n🙆♀️\twoman-gesturing-ok\n💁\tinformation_desk_person\n💁♂️\tman-tipping-hand\n💁♀️\twoman-tipping-hand\n🙋\traising_hand\thappy person one\n🙋♂️\tman-raising-hand\n🙋♀️\twoman-raising-hand\n🧏\tdeaf_person\n🧏♂️\tdeaf_man\n🧏♀️\tdeaf_woman\n🙇\tbow\tperson bowing deeply\n🙇♂️\tman-bowing\n🙇♀️\twoman-bowing\n🤦\tface_palm\n🤦♂️\tman-facepalming\n🤦♀️\twoman-facepalming\n🤷\tshrug\n🤷♂️\tman-shrugging\n🤷♀️\twoman-shrugging\n🧑⚕️\thealth_worker\n👨⚕️\tmale-doctor\tman health worker\n👩⚕️\tfemale-doctor\twoman health worker\n🧑🎓\tstudent\n👨🎓\tmale-student\tman\n👩🎓\tfemale-student\twoman\n🧑🏫\tteacher\n👨🏫\tmale-teacher\tman\n👩🏫\tfemale-teacher\twoman\n🧑⚖️\tjudge\n👨⚖️\tmale-judge\tman\n👩⚖️\tfemale-judge\twoman\n🧑🌾\tfarmer\n👨🌾\tmale-farmer\tman\n👩🌾\tfemale-farmer\twoman\n🧑🍳\tcook\n👨🍳\tmale-cook\tman\n👩🍳\tfemale-cook\twoman\n🧑🔧\tmechanic\n👨🔧\tmale-mechanic\tman\n👩🔧\tfemale-mechanic\twoman\n🧑🏭\tfactory_worker\n👨🏭\tmale-factory-worker\tman\n👩🏭\tfemale-factory-worker\twoman\n🧑💼\toffice_worker\n👨💼\tmale-office-worker\tman\n👩💼\tfemale-office-worker\twoman\n🧑🔬\tscientist\n👨🔬\tmale-scientist\tman\n👩🔬\tfemale-scientist\twoman\n🧑💻\ttechnologist\n👨💻\tmale-technologist\tman\n👩💻\tfemale-technologist\twoman\n🧑🎤\tsinger\n👨🎤\tmale-singer\tman\n👩🎤\tfemale-singer\twoman\n🧑🎨\tartist\n👨🎨\tmale-artist\tman\n👩🎨\tfemale-artist\twoman\n🧑✈️\tpilot\n👨✈️\tmale-pilot\tman\n👩✈️\tfemale-pilot\twoman\n🧑🚀\tastronaut\n👨🚀\tmale-astronaut\tman\n👩🚀\tfemale-astronaut\twoman\n🧑🚒\tfirefighter\n👨🚒\tmale-firefighter\tman\n👩🚒\tfemale-firefighter\twoman\n👮\tcop\tpolice officer\n👮♂️\tmale-police-officer\tman\n👮♀️\tfemale-police-officer\twoman\n🕵️\tsleuth_or_spy\tdetective\n🕵️♂️\tmale-detective\tman\n🕵️♀️\tfemale-detective\twoman\n💂\tguardsman\n💂♂️\tmale-guard\tman\n💂♀️\tfemale-guard\twoman\n🥷\tninja\n👷\tconstruction_worker\n👷♂️\tmale-construction-worker\tman\n👷♀️\tfemale-construction-worker\twoman\n🫅\tperson_with_crown\n🤴\tprince\n👸\tprincess\n👳\tman_with_turban\n👳♂️\tman-wearing-turban\n👳♀️\twoman-wearing-turban\n👲\tman_with_gua_pi_mao\n🧕\tperson_with_headscarf\n🤵\tperson_in_tuxedo\tman\n🤵♂️\tman_in_tuxedo\n🤵♀️\twoman_in_tuxedo\n👰\tbride_with_veil\n👰♂️\tman_with_veil\n👰♀️\twoman_with_veil\n🤰\tpregnant_woman\n🫃\tpregnant_man\n🫄\tpregnant_person\n🤱\tbreast-feeding\n👩🍼\twoman_feeding_baby\n👨🍼\tman_feeding_baby\n🧑🍼\tperson_feeding_baby\n👼\tangel\tbaby\n🎅\tsanta\tfather christmas\n🤶\tmrs_claus mother_christmas\n🧑🎄\tmx_claus\n🦸\tsuperhero\n🦸♂️\tmale_superhero\tman\n🦸♀️\tfemale_superhero\twoman\n🦹\tsupervillain\n🦹♂️\tmale_supervillain\tman\n🦹♀️\tfemale_supervillain\twoman\n🧙\tmage\n🧙♂️\tmale_mage\tman\n🧙♀️\tfemale_mage\twoman\n🧚\tfairy\n🧚♂️\tmale_fairy\tman\n🧚♀️\tfemale_fairy\twoman\n🧛\tvampire\n🧛♂️\tmale_vampire\tman\n🧛♀️\tfemale_vampire\twoman\n🧜\tmerperson\n🧜♂️\tmerman\n🧜♀️\tmermaid\n🧝\telf\n🧝♂️\tmale_elf\tman\n🧝♀️\tfemale_elf\twoman\n🧞\tgenie\n🧞♂️\tmale_genie\tman\n🧞♀️\tfemale_genie\twoman\n🧟\tzombie\n🧟♂️\tmale_zombie\tman\n🧟♀️\tfemale_zombie\twoman\n🧌\ttroll\n💆\tmassage\tface\n💆♂️\tman-getting-massage\n💆♀️\twoman-getting-massage\n💇\thaircut\n💇♂️\tman-getting-haircut\n💇♀️\twoman-getting-haircut\n🚶\twalking\tpedestrian\n🚶♂️\tman-walking\n🚶♀️\twoman-walking\n🚶➡️\tperson_walking_facing_right\n🚶♀️➡️\twoman_walking_facing_right\n🚶♂️➡️\tman_walking_facing_right\n🧍\tstanding_person\n🧍♂️\tman_standing\n🧍♀️\twoman_standing\n🧎\tkneeling_person\n🧎♂️\tman_kneeling\n🧎♀️\twoman_kneeling\n🧎➡️\tperson_kneeling_facing_right\n🧎♀️➡️\twoman_kneeling_facing_right\n🧎♂️➡️\tman_kneeling_facing_right\n🧑🦯\tperson_with_probing_cane\twhite\n🧑🦯➡️\tperson_with_white_cane_facing_right\n👨🦯\tman_with_probing_cane\twhite\n👨🦯➡️\tman_with_white_cane_facing_right\n👩🦯\twoman_with_probing_cane\twhite\n👩🦯➡️\twoman_with_white_cane_facing_right\n🧑🦼\tperson_in_motorized_wheelchair\n🧑🦼➡️\tperson_in_motorized_wheelchair_facing_right\n👨🦼\tman_in_motorized_wheelchair\n👨🦼➡️\tman_in_motorized_wheelchair_facing_right\n👩🦼\twoman_in_motorized_wheelchair\n👩🦼➡️\twoman_in_motorized_wheelchair_facing_right\n🧑🦽\tperson_in_manual_wheelchair\n🧑🦽➡️\tperson_in_manual_wheelchair_facing_right\n👨🦽\tman_in_manual_wheelchair\n👨🦽➡️\tman_in_manual_wheelchair_facing_right\n👩🦽\twoman_in_manual_wheelchair\n👩🦽➡️\twoman_in_manual_wheelchair_facing_right\n🏃\trunner running\n🏃♂️\tman-running\n🏃♀️\twoman-running\n🏃➡️\tperson_running_facing_right\n🏃♀️➡️\twoman_running_facing_right\n🏃♂️➡️\tman_running_facing_right\n💃\tdancer\n🕺\tman_dancing\n🕴️\tman_in_business_suit_levitating\tperson\n👯\tdancers\twoman bunny ears\n👯♂️\tmen-with-bunny-ears-partying man-with-bunny-ears-partying\n👯♀️\twomen-with-bunny-ears-partying woman-with-bunny-ears-partying\n🧖\tperson_in_steamy_room\n🧖♂️\tman_in_steamy_room\n🧖♀️\twoman_in_steamy_room\n🧗\tperson_climbing\n🧗♂️\tman_climbing\n🧗♀️\twoman_climbing\n🤺\tfencer\n🏇\thorse_racing\n⛷️\tskier\n🏂\tsnowboarder\n🏌️\tgolfer\tperson golfing\n🏌️♂️\tman-golfing\n🏌️♀️\twoman-golfing\n🏄\tsurfer\n🏄♂️\tman-surfing\n🏄♀️\twoman-surfing\n🚣\trowboat\n🚣♂️\tman-rowing-boat\n🚣♀️\twoman-rowing-boat\n🏊\tswimmer\n🏊♂️\tman-swimming\n🏊♀️\twoman-swimming\n⛹️\tperson_with_ball\tbouncing\n⛹️♂️\tman-bouncing-ball\n⛹️♀️\twoman-bouncing-ball\n🏋️\tweight_lifter\tperson lifting weights\n🏋️♂️\tman-lifting-weights\n🏋️♀️\twoman-lifting-weights\n🚴\tbicyclist\n🚴♂️\tman-biking\n🚴♀️\twoman-biking\n🚵\tmountain_bicyclist\n🚵♂️\tman-mountain-biking\n🚵♀️\twoman-mountain-biking\n🤸\tperson_doing_cartwheel\n🤸♂️\tman-cartwheeling\n🤸♀️\twoman-cartwheeling\n🤼\twrestlers\n🤼♂️\tman-wrestling\tmen\n🤼♀️\twoman-wrestling\twomen\n🤽\twater_polo\n🤽♂️\tman-playing-water-polo\n🤽♀️\twoman-playing-water-polo\n🤾\thandball\n🤾♂️\tman-playing-handball\n🤾♀️\twoman-playing-handball\n🤹\tjuggling\n🤹♂️\tman-juggling\n🤹♀️\twoman-juggling\n🧘\tperson_in_lotus_position\n🧘♂️\tman_in_lotus_position\n🧘♀️\twoman_in_lotus_position\n🛀\tbath\n🛌\tsleeping_accommodation\n🧑🤝🧑\tpeople_holding_hands\n👭\ttwo_women_holding_hands women_holding_hands\n👫\tman_and_woman_holding_hands woman_and_man_holding_hands couple\n👬\ttwo_men_holding_hands men_holding_hands\n💏\tcouplekiss\tkiss\n👩❤️💋👨\twoman-kiss-man\n👨❤️💋👨\tman-kiss-man\n👩❤️💋👩\twoman-kiss-woman\n💑\tcouple_with_heart\n👩❤️👨\twoman-heart-man\tcouple\n👨❤️👨\tman-heart-man\tcouple\n👩❤️👩\twoman-heart-woman\tcouple\n👨👩👦\tman-woman-boy\tfamily\n👨👩👧\tman-woman-girl\tfamily\n👨👩👧👦\tman-woman-girl-boy\tfamily\n👨👩👦👦\tman-woman-boy-boy\tfamily\n👨👩👧👧\tman-woman-girl-girl\tfamily\n👨👨👦\tman-man-boy\tfamily\n👨👨👧\tman-man-girl\tfamily\n👨👨👧👦\tman-man-girl-boy\tfamily\n👨👨👦👦\tman-man-boy-boy\tfamily\n👨👨👧👧\tman-man-girl-girl\tfamily\n👩👩👦\twoman-woman-boy\tfamily\n👩👩👧\twoman-woman-girl\tfamily\n👩👩👧👦\twoman-woman-girl-boy\tfamily\n👩👩👦👦\twoman-woman-boy-boy\tfamily\n👩👩👧👧\twoman-woman-girl-girl\tfamily\n👨👦\tman-boy\tfamily\n👨👦👦\tman-boy-boy\tfamily\n👨👧\tman-girl\tfamily\n👨👧👦\tman-girl-boy\tfamily\n👨👧👧\tman-girl-girl\tfamily\n👩👦\twoman-boy\tfamily\n👩👦👦\twoman-boy-boy\tfamily\n👩👧\twoman-girl\tfamily\n👩👧👦\twoman-girl-boy\tfamily\n👩👧👧\twoman-girl-girl\tfamily\n🗣️\tspeaking_head_in_silhouette\n👤\tbust_in_silhouette\n👥\tbusts_in_silhouette\n🫂\tpeople_hugging\n👪\tfamily\n🧑🧑🧒\tfamily_adult_adult_child\n🧑🧑🧒🧒\tfamily_adult_adult_child_child\n🧑🧒\tfamily_adult_child\n🧑🧒🧒\tfamily_adult_child_child\n👣\tfootprints\n\tfingerprint\n🐵\tmonkey_face\n🐒\tmonkey\n🦍\tgorilla\n🦧\torangutan\n🐶\tdog\tface\n🐕\tdog2\tdog\n🦮\tguide_dog\n🐕🦺\tservice_dog\n🐩\tpoodle\n🐺\twolf\tface\n🦊\tfox_face\n🦝\traccoon\n🐱\tcat\tface\n🐈\tcat2\tcat\n🐈⬛\tblack_cat\n🦁\tlion_face\n🐯\ttiger\tface\n🐅\ttiger2\ttiger\n🐆\tleopard\n🐴\thorse\tface\n🫎\tmoose\n🫏\tdonkey\n🐎\tracehorse\thorse\n🦄\tunicorn_face\n🦓\tzebra_face\n🦌\tdeer\n🦬\tbison\n🐮\tcow\tface\n🐂\tox\n🐃\twater_buffalo\n🐄\tcow2\tcow\n🐷\tpig\tface\n🐖\tpig2\tpig\n🐗\tboar\n🐽\tpig_nose\n🐏\tram\n🐑\tsheep\n🐐\tgoat\n🐪\tdromedary_camel\n🐫\tcamel\tbactrian\n🦙\tllama\n🦒\tgiraffe_face\n🐘\telephant\n🦣\tmammoth\n🦏\trhinoceros\n🦛\thippopotamus\n🐭\tmouse\tface\n🐁\tmouse2\tmouse\n🐀\trat\n🐹\thamster\tface\n🐰\trabbit\tface\n🐇\trabbit2\trabbit\n🐿️\tchipmunk\n🦫\tbeaver\n🦔\thedgehog\n🦇\tbat\n🐻\tbear\tface\n🐻❄️\tpolar_bear\n🐨\tkoala\n🐼\tpanda_face\n🦥\tsloth\n🦦\totter\n🦨\tskunk\n🦘\tkangaroo\n🦡\tbadger\n🐾\tfeet paw_prints\n🦃\tturkey\n🐔\tchicken\n🐓\trooster\n🐣\thatching_chick\n🐤\tbaby_chick\n🐥\thatched_chick\tfront-facing baby\n🐦\tbird\n🐧\tpenguin\n🕊️\tdove_of_peace\n🦅\teagle\n🦆\tduck\n🦢\tswan\n🦉\towl\n🦤\tdodo\n🪶\tfeather\n🦩\tflamingo\n🦚\tpeacock\n🦜\tparrot\n🪽\twing\n🐦⬛\tblack_bird\n🪿\tgoose\n🐦🔥\tphoenix\n🐸\tfrog\tface\n🐊\tcrocodile\n🐢\tturtle\n🦎\tlizard\n🐍\tsnake\n🐲\tdragon_face\n🐉\tdragon\n🦕\tsauropod\n🦖\tt-rex\n🐳\twhale\tspouting\n🐋\twhale2\twhale\n🐬\tdolphin flipper\n🦭\tseal\n🐟\tfish\n🐠\ttropical_fish\n🐡\tblowfish\n🦈\tshark\n🐙\toctopus\n🐚\tshell\tspiral\n🪸\tcoral\n🪼\tjellyfish\n🦀\tcrab\n🦞\tlobster\n🦐\tshrimp\n🦑\tsquid\n🦪\toyster\n🐌\tsnail\n🦋\tbutterfly\n🐛\tbug\n🐜\tant\n🐝\tbee honeybee\n🪲\tbeetle\n🐞\tladybug lady_beetle\n🦗\tcricket\n🪳\tcockroach\n🕷️\tspider\n🕸️\tspider_web\n🦂\tscorpion\n🦟\tmosquito\n🪰\tfly\n🪱\tworm\n🦠\tmicrobe\n💐\tbouquet\n🌸\tcherry_blossom\n💮\twhite_flower\n🪷\tlotus\n🏵️\trosette\n🌹\trose\n🥀\twilted_flower\n🌺\thibiscus\n🌻\tsunflower\n🌼\tblossom\n🌷\ttulip\n🪻\thyacinth\n🌱\tseedling\n🪴\tpotted_plant\n🌲\tevergreen_tree\n🌳\tdeciduous_tree\n🌴\tpalm_tree\n🌵\tcactus\n🌾\tear_of_rice\n🌿\therb\n☘️\tshamrock\n🍀\tfour_leaf_clover\n🍁\tmaple_leaf\n🍂\tfallen_leaf\n🍃\tleaves\tleaf fluttering wind\n🪹\tempty_nest\n🪺\tnest_with_eggs\n🍄\tmushroom\n\tleafless_tree\n🍇\tgrapes\n🍈\tmelon\n🍉\twatermelon\n🍊\ttangerine\n🍋\tlemon\n🍋🟩\tlime\n🍌\tbanana\n🍍\tpineapple\n🥭\tmango\n🍎\tapple\tred\n🍏\tgreen_apple\n🍐\tpear\n🍑\tpeach\n🍒\tcherries\n🍓\tstrawberry\n🫐\tblueberries\n🥝\tkiwifruit\n🍅\ttomato\n🫒\tolive\n🥥\tcoconut\n🥑\tavocado\n🍆\teggplant\taubergine\n🥔\tpotato\n🥕\tcarrot\n🌽\tcorn\tear maize\n🌶️\thot_pepper\n🫑\tbell_pepper\n🥒\tcucumber\n🥬\tleafy_green\n🥦\tbroccoli\n🧄\tgarlic\n🧅\tonion\n🥜\tpeanuts\n🫘\tbeans\n🌰\tchestnut\n🫚\tginger_root\n🫛\tpea_pod\n🍄🟫\tbrown_mushroom\n\troot_vegetable\n🍞\tbread\n🥐\tcroissant\n🥖\tbaguette_bread\n🫓\tflatbread\n🥨\tpretzel\n🥯\tbagel\n🥞\tpancakes\n🧇\twaffle\n🧀\tcheese_wedge\n🍖\tmeat_on_bone\n🍗\tpoultry_leg\n🥩\tcut_of_meat\n🥓\tbacon\n🍔\thamburger\n🍟\tfries\tfrench\n🍕\tpizza\tslice\n🌭\thotdog\thot dog\n🥪\tsandwich\n🌮\ttaco\n🌯\tburrito\n🫔\ttamale\n🥙\tstuffed_flatbread\n🧆\tfalafel\n🥚\tegg\n🍳\tfried_egg cooking\n🥘\tshallow_pan_of_food\n🍲\tstew\tpot food\n🫕\tfondue\n🥣\tbowl_with_spoon\n🥗\tgreen_salad\n🍿\tpopcorn\n🧈\tbutter\n🧂\tsalt\tshaker\n🥫\tcanned_food\n🍱\tbento\tbox\n🍘\trice_cracker\n🍙\trice_ball\n🍚\trice\tcooked\n🍛\tcurry\trice\n🍜\tramen\tsteaming bowl\n🍝\tspaghetti\n🍠\tsweet_potato\troasted\n🍢\toden\n🍣\tsushi\n🍤\tfried_shrimp\n🍥\tfish_cake\tswirl design\n🥮\tmoon_cake\n🍡\tdango\n🥟\tdumpling\n🥠\tfortune_cookie\n🥡\ttakeout_box\n🍦\ticecream\tsoft ice cream\n🍧\tshaved_ice\n🍨\tice_cream\n🍩\tdoughnut\n🍪\tcookie\n🎂\tbirthday\tcake\n🍰\tcake\tshortcake\n🧁\tcupcake\n🥧\tpie\n🍫\tchocolate_bar\n🍬\tcandy\n🍭\tlollipop\n🍮\tcustard\n🍯\thoney_pot\n🍼\tbaby_bottle\n🥛\tglass_of_milk\n☕\tcoffee\thot beverage\n🫖\tteapot\n🍵\ttea\tteacup without handle\n🍶\tsake\tbottle cup\n🍾\tchampagne\tbottle popping cork\n🍷\twine_glass\n🍸\tcocktail\tglass\n🍹\ttropical_drink\n🍺\tbeer\tmug\n🍻\tbeers\tclinking beer mugs\n🥂\tclinking_glasses\n🥃\ttumbler_glass\n🫗\tpouring_liquid\n🥤\tcup_with_straw\n🧋\tbubble_tea\n🧃\tbeverage_box\n🧉\tmate_drink\n🧊\tice_cube\n🥢\tchopsticks\n🍽️\tknife_fork_plate\n🍴\tfork_and_knife\n🥄\tspoon\n🔪\thocho knife\n🫙\tjar\n🏺\tamphora\n🌍\tearth_africa\tglobe europe-africa\n🌎\tearth_americas\tglobe\n🌏\tearth_asia\tglobe asia-australia\n🌐\tglobe_with_meridians\n🗺️\tworld_map\n🗾\tjapan\tsilhouette\n🧭\tcompass\n🏔️\tsnow_capped_mountain\tsnow-capped\n⛰️\tmountain\n🌋\tvolcano\n🗻\tmount_fuji\n🏕️\tcamping\n🏖️\tbeach_with_umbrella\n🏜️\tdesert\n🏝️\tdesert_island\n🏞️\tnational_park\n🏟️\tstadium\n🏛️\tclassical_building\n🏗️\tbuilding_construction\n🧱\tbricks\tbrick\n🪨\trock\n🪵\twood\n🛖\thut\n🏘️\thouse_buildings\thouses\n🏚️\tderelict_house_building\n🏠\thouse\tbuilding\n🏡\thouse_with_garden\n🏢\toffice\tbuilding\n🏣\tpost_office\tjapanese\n🏤\teuropean_post_office\n🏥\thospital\n🏦\tbank\n🏨\thotel\n🏩\tlove_hotel\n🏪\tconvenience_store\n🏫\tschool\n🏬\tdepartment_store\n🏭\tfactory\n🏯\tjapanese_castle\n🏰\teuropean_castle\n💒\twedding\n🗼\ttokyo_tower\n🗽\tstatue_of_liberty\n⛪\tchurch\n🕌\tmosque\n🛕\thindu_temple\n🕍\tsynagogue\n⛩️\tshinto_shrine\n🕋\tkaaba\n⛲\tfountain\n⛺\ttent\n🌁\tfoggy\n🌃\tnight_with_stars\n🏙️\tcityscape\n🌄\tsunrise_over_mountains\n🌅\tsunrise\n🌆\tcity_sunset\tcityscape at dusk\n🌇\tcity_sunrise\tsunset over buildings\n🌉\tbridge_at_night\n♨️\thotsprings\thot springs\n🎠\tcarousel_horse\n🛝\tplayground_slide\n🎡\tferris_wheel\n🎢\troller_coaster\n💈\tbarber\tpole\n🎪\tcircus_tent\n🚂\tsteam_locomotive\n🚃\trailway_car\n🚄\tbullettrain_side\thigh-speed train\n🚅\tbullettrain_front\thigh-speed train bullet nose\n🚆\ttrain2\ttrain\n🚇\tmetro\n🚈\tlight_rail\n🚉\tstation\n🚊\ttram\n🚝\tmonorail\n🚞\tmountain_railway\n🚋\ttrain\ttram car\n🚌\tbus\n🚍\toncoming_bus\n🚎\ttrolleybus\n🚐\tminibus\n🚑\tambulance\n🚒\tfire_engine\n🚓\tpolice_car\n🚔\toncoming_police_car\n🚕\ttaxi\n🚖\toncoming_taxi\n🚗\tcar red_car\tautomobile\n🚘\toncoming_automobile\n🚙\tblue_car\trecreational vehicle\n🛻\tpickup_truck\n🚚\ttruck\tdelivery\n🚛\tarticulated_lorry\n🚜\ttractor\n🏎️\tracing_car\n🏍️\tracing_motorcycle\n🛵\tmotor_scooter\n🦽\tmanual_wheelchair\n🦼\tmotorized_wheelchair\n🛺\tauto_rickshaw\n🚲\tbike\tbicycle\n🛴\tscooter\n🛹\tskateboard\n🛼\troller_skate\n🚏\tbusstop\tbus stop\n🛣️\tmotorway\n🛤️\trailway_track\n🛢️\toil_drum\n⛽\tfuelpump\tfuel pump\n🛞\twheel\n🚨\trotating_light\tpolice cars revolving\n🚥\ttraffic_light\thorizontal\n🚦\tvertical_traffic_light\n🛑\toctagonal_sign\n🚧\tconstruction\tsign\n⚓\tanchor\n🛟\tring_buoy\n⛵\tboat sailboat\n🛶\tcanoe\n🚤\tspeedboat\n🛳️\tpassenger_ship\n⛴️\tferry\n🛥️\tmotor_boat\n🚢\tship\n✈️\tairplane\n🛩️\tsmall_airplane\n🛫\tairplane_departure\n🛬\tairplane_arriving\n🪂\tparachute\n💺\tseat\n🚁\thelicopter\n🚟\tsuspension_railway\n🚠\tmountain_cableway\n🚡\taerial_tramway\n🛰️\tsatellite\n🚀\trocket\n🛸\tflying_saucer\n🛎️\tbellhop_bell\n🧳\tluggage\n⌛\thourglass\n⏳\thourglass_flowing_sand\n⌚\twatch\n⏰\talarm_clock\n⏱️\tstopwatch\n⏲️\ttimer_clock\n🕰️\tmantelpiece_clock\n🕛\tclock12\tclock face twelve oclock\n🕧\tclock1230\tclock face twelve-thirty\n🕐\tclock1\tclock face one oclock\n🕜\tclock130\tclock face one-thirty\n🕑\tclock2\tclock face two oclock\n🕝\tclock230\tclock face two-thirty\n🕒\tclock3\tclock face three oclock\n🕞\tclock330\tclock face three-thirty\n🕓\tclock4\tclock face four oclock\n🕟\tclock430\tclock face four-thirty\n🕔\tclock5\tclock face five oclock\n🕠\tclock530\tclock face five-thirty\n🕕\tclock6\tclock face six oclock\n🕡\tclock630\tclock face six-thirty\n🕖\tclock7\tclock face seven oclock\n🕢\tclock730\tclock face seven-thirty\n🕗\tclock8\tclock face eight oclock\n🕣\tclock830\tclock face eight-thirty\n🕘\tclock9\tclock face nine oclock\n🕤\tclock930\tclock face nine-thirty\n🕙\tclock10\tclock face ten oclock\n🕥\tclock1030\tclock face ten-thirty\n🕚\tclock11\tclock face eleven oclock\n🕦\tclock1130\tclock face eleven-thirty\n🌑\tnew_moon\tsymbol\n🌒\twaxing_crescent_moon\tsymbol\n🌓\tfirst_quarter_moon\tsymbol\n🌔\tmoon waxing_gibbous_moon\tsymbol\n🌕\tfull_moon\tsymbol\n🌖\twaning_gibbous_moon\tsymbol\n🌗\tlast_quarter_moon\tsymbol\n🌘\twaning_crescent_moon\tsymbol\n🌙\tcrescent_moon\n🌚\tnew_moon_with_face\n🌛\tfirst_quarter_moon_with_face\n🌜\tlast_quarter_moon_with_face\n🌡️\tthermometer\n☀️\tsunny\tblack sun rays\n🌝\tfull_moon_with_face\n🌞\tsun_with_face\n🪐\tringed_planet\n⭐\tstar\twhite medium\n🌟\tstar2\tglowing star\n🌠\tstars\tshooting star\n🌌\tmilky_way\n☁️\tcloud\n⛅\tpartly_sunny\tsun behind cloud\n⛈️\tthunder_cloud_and_rain\tlightning\n🌤️\tmostly_sunny sun_small_cloud\tbehind\n🌥️\tbarely_sunny sun_behind_cloud\tlarge\n🌦️\tpartly_sunny_rain sun_behind_rain_cloud\n🌧️\train_cloud\n🌨️\tsnow_cloud\n🌩️\tlightning lightning_cloud\n🌪️\ttornado tornado_cloud\n🌫️\tfog\n🌬️\twind_blowing_face\n🌀\tcyclone\n🌈\trainbow\n🌂\tclosed_umbrella\n☂️\tumbrella\n☔\tumbrella_with_rain_drops\n⛱️\tumbrella_on_ground\n⚡\tzap\thigh voltage sign\n❄️\tsnowflake\n☃️\tsnowman\n⛄\tsnowman_without_snow\n☄️\tcomet\n🔥\tfire\n💧\tdroplet\n🌊\tocean\twater wave\n🎃\tjack_o_lantern\tjack-o-lantern\n🎄\tchristmas_tree\n🎆\tfireworks\n🎇\tsparkler\tfirework\n🧨\tfirecracker\n✨\tsparkles\n🎈\tballoon\n🎉\ttada\tparty popper\n🎊\tconfetti_ball\n🎋\ttanabata_tree\n🎍\tbamboo\tpine decoration\n🎎\tdolls\tjapanese\n🎏\tflags\tcarp streamer\n🎐\twind_chime\n🎑\trice_scene\tmoon viewing ceremony\n🧧\tred_envelope\tgift\n🎀\tribbon\n🎁\tgift\twrapped present\n🎗️\treminder_ribbon\n🎟️\tadmission_tickets\n🎫\tticket\n🎖️\tmedal\tmilitary\n🏆\ttrophy\n🏅\tsports_medal\n🥇\tfirst_place_medal\n🥈\tsecond_place_medal\n🥉\tthird_place_medal\n⚽\tsoccer\tball\n⚾\tbaseball\n🥎\tsoftball\n🏀\tbasketball\thoop\n🏐\tvolleyball\n🏈\tfootball\tamerican\n🏉\trugby_football\n🎾\ttennis\tracquet ball\n🥏\tflying_disc\n🎳\tbowling\n🏏\tcricket_bat_and_ball\n🏑\tfield_hockey_stick_and_ball\n🏒\tice_hockey_stick_and_puck\n🥍\tlacrosse\tstick ball\n🏓\ttable_tennis_paddle_and_ball\n🏸\tbadminton_racquet_and_shuttlecock\n🥊\tboxing_glove\n🥋\tmartial_arts_uniform\n🥅\tgoal_net\n⛳\tgolf\tflag hole\n⛸️\tice_skate\n🎣\tfishing_pole_and_fish\n🤿\tdiving_mask\n🎽\trunning_shirt_with_sash\n🎿\tski\tboot\n🛷\tsled\n🥌\tcurling_stone\n🎯\tdart\tdirect hit\n🪀\tyo-yo\n🪁\tkite\n🔫\tgun\tpistol\n🎱\t8ball\tbilliards\n🔮\tcrystal_ball\n🪄\tmagic_wand\n🎮\tvideo_game\n🕹️\tjoystick\n🎰\tslot_machine\n🎲\tgame_die\n🧩\tjigsaw\tpuzzle piece\n🧸\tteddy_bear\n🪅\tpinata\n🪩\tmirror_ball\n🪆\tnesting_dolls\n♠️\tspades\tblack spade suit\n♥️\thearts\tblack heart suit\n♦️\tdiamonds\tblack diamond suit\n♣️\tclubs\tblack club suit\n♟️\tchess_pawn\n🃏\tblack_joker\tplaying card\n🀄\tmahjong\ttile red dragon\n🎴\tflower_playing_cards\n🎭\tperforming_arts\n🖼️\tframe_with_picture\tframed\n🎨\tart\tartist palette\n🧵\tthread\tspool\n🪡\tsewing_needle\n🧶\tyarn\tball\n🪢\tknot\n👓\teyeglasses\n🕶️\tdark_sunglasses\n🥽\tgoggles\n🥼\tlab_coat\n🦺\tsafety_vest\n👔\tnecktie\n👕\tshirt tshirt\tt-shirt\n👖\tjeans\n🧣\tscarf\n🧤\tgloves\n🧥\tcoat\n🧦\tsocks\n👗\tdress\n👘\tkimono\n🥻\tsari\n🩱\tone-piece_swimsuit\tone-piece\n🩲\tbriefs\n🩳\tshorts\n👙\tbikini\n👚\twomans_clothes\n🪭\tfolding_hand_fan\n👛\tpurse\n👜\thandbag\n👝\tpouch\n🛍️\tshopping_bags\n🎒\tschool_satchel\n🩴\tthong_sandal\n👞\tmans_shoe shoe\n👟\tathletic_shoe\n🥾\thiking_boot\n🥿\twomans_flat_shoe\n👠\thigh_heel\thigh-heeled shoe\n👡\tsandal\twomans\n🩰\tballet_shoes\n👢\tboot\twomans boots\n🪮\thair_pick\n👑\tcrown\n👒\twomans_hat\n🎩\ttophat\ttop hat\n🎓\tmortar_board\tgraduation cap\n🧢\tbilled_cap\n🪖\tmilitary_helmet\n⛑️\thelmet_with_white_cross\trescue worker s\n📿\tprayer_beads\n💄\tlipstick\n💍\tring\n💎\tgem\tstone\n🔇\tmute\tspeaker cancellation stroke\n🔈\tspeaker\n🔉\tsound\tspeaker one wave\n🔊\tloud_sound\tspeaker three waves\n📢\tloudspeaker\tpublic address\n📣\tmega\tcheering megaphone\n📯\tpostal_horn\n🔔\tbell\n🔕\tno_bell\tcancellation stroke\n🎼\tmusical_score\n🎵\tmusical_note\n🎶\tnotes\tmultiple musical\n🎙️\tstudio_microphone\n🎚️\tlevel_slider\n🎛️\tcontrol_knobs\n🎤\tmicrophone\n🎧\theadphones\theadphone\n📻\tradio\n🎷\tsaxophone\n🪗\taccordion\n🎸\tguitar\n🎹\tmusical_keyboard\n🎺\ttrumpet\n🎻\tviolin\n🪕\tbanjo\n🥁\tdrum_with_drumsticks\n🪘\tlong_drum\n🪇\tmaracas\n🪈\tflute\n\tharp\n📱\tiphone\tmobile phone\n📲\tcalling\tmobile phone rightwards arrow at left\n☎️\tphone telephone\tblack\n📞\ttelephone_receiver\n📟\tpager\n📠\tfax\tmachine\n🔋\tbattery\n🪫\tlow_battery\n🔌\telectric_plug\n💻\tcomputer\tpersonal\n🖥️\tdesktop_computer\n🖨️\tprinter\n⌨️\tkeyboard\n🖱️\tthree_button_mouse\tcomputer\n🖲️\ttrackball\n💽\tminidisc\n💾\tfloppy_disk\n💿\tcd\toptical disc\n📀\tdvd\n🧮\tabacus\n🎥\tmovie_camera\n🎞️\tfilm_frames\n📽️\tfilm_projector\n🎬\tclapper\tboard\n📺\ttv\ttelevision\n📷\tcamera\n📸\tcamera_with_flash\n📹\tvideo_camera\n📼\tvhs\tvideocassette\n🔍\tmag\tleft-pointing magnifying glass\n🔎\tmag_right\tright-pointing magnifying glass\n🕯️\tcandle\n💡\tbulb\telectric light\n🔦\tflashlight\telectric torch\n🏮\tizakaya_lantern lantern\n🪔\tdiya_lamp\n📔\tnotebook_with_decorative_cover\n📕\tclosed_book\n📖\tbook open_book\n📗\tgreen_book\n📘\tblue_book\n📙\torange_book\n📚\tbooks\n📓\tnotebook\n📒\tledger\n📃\tpage_with_curl\n📜\tscroll\n📄\tpage_facing_up\n📰\tnewspaper\n🗞️\trolled_up_newspaper\trolled-up\n📑\tbookmark_tabs\n🔖\tbookmark\n🏷️\tlabel\n💰\tmoneybag\tmoney bag\n🪙\tcoin\n💴\tyen\tbanknote sign\n💵\tdollar\tbanknote sign\n💶\teuro\tbanknote sign\n💷\tpound\tbanknote sign\n💸\tmoney_with_wings\n💳\tcredit_card\n🧾\treceipt\n💹\tchart\tupwards trend yen sign\n✉️\temail envelope\n📧\te-mail\tsymbol\n📨\tincoming_envelope\n📩\tenvelope_with_arrow\tdownwards above\n📤\toutbox_tray\n📥\tinbox_tray\n📦\tpackage\n📫\tmailbox\tclosed raised flag\n📪\tmailbox_closed\tlowered flag\n📬\tmailbox_with_mail\topen raised flag\n📭\tmailbox_with_no_mail\topen lowered flag\n📮\tpostbox\n🗳️\tballot_box_with_ballot\n✏️\tpencil2\tpencil\n✒️\tblack_nib\n🖋️\tlower_left_fountain_pen\n🖊️\tlower_left_ballpoint_pen\n🖌️\tlower_left_paintbrush\n🖍️\tlower_left_crayon\n📝\tmemo pencil\n💼\tbriefcase\n📁\tfile_folder\n📂\topen_file_folder\n🗂️\tcard_index_dividers\n📅\tdate\tcalendar\n📆\tcalendar\ttear-off\n🗒️\tspiral_note_pad\tnotepad\n🗓️\tspiral_calendar_pad\n📇\tcard_index\n📈\tchart_with_upwards_trend\n📉\tchart_with_downwards_trend\n📊\tbar_chart\n📋\tclipboard\n📌\tpushpin\n📍\tround_pushpin\n📎\tpaperclip\n🖇️\tlinked_paperclips\n📏\tstraight_ruler\n📐\ttriangular_ruler\n✂️\tscissors\tblack\n🗃️\tcard_file_box\n🗄️\tfile_cabinet\n🗑️\twastebasket\n🔒\tlock\n🔓\tunlock\topen lock\n🔏\tlock_with_ink_pen\n🔐\tclosed_lock_with_key\n🔑\tkey\n🗝️\told_key\n🔨\thammer\n🪓\taxe\n⛏️\tpick\n⚒️\thammer_and_pick\n🛠️\thammer_and_wrench\n🗡️\tdagger_knife\n⚔️\tcrossed_swords\n💣\tbomb\n🪃\tboomerang\n🏹\tbow_and_arrow\n🛡️\tshield\n🪚\tcarpentry_saw\n🔧\twrench\n🪛\tscrewdriver\n🔩\tnut_and_bolt\n⚙️\tgear\n🗜️\tcompression\tclamp\n⚖️\tscales\tbalance scale\n🦯\tprobing_cane\n🔗\tlink\tsymbol\n⛓️💥\tbroken_chain\n⛓️\tchains\n🪝\thook\n🧰\ttoolbox\n🧲\tmagnet\n🪜\tladder\n\tshovel\n⚗️\talembic\n🧪\ttest_tube\n🧫\tpetri_dish\n🧬\tdna\tdouble helix\n🔬\tmicroscope\n🔭\ttelescope\n📡\tsatellite_antenna\n💉\tsyringe\n🩸\tdrop_of_blood\n💊\tpill\n🩹\tadhesive_bandage\n🩼\tcrutch\n🩺\tstethoscope\n🩻\tx-ray\n🚪\tdoor\n🛗\televator\n🪞\tmirror\n🪟\twindow\n🛏️\tbed\n🛋️\tcouch_and_lamp\n🪑\tchair\n🚽\ttoilet\n🪠\tplunger\n🚿\tshower\n🛁\tbathtub\n🪤\tmouse_trap\n🪒\trazor\n🧴\tlotion_bottle\n🧷\tsafety_pin\n🧹\tbroom\n🧺\tbasket\n🧻\troll_of_paper\n🪣\tbucket\n🧼\tsoap\tbar\n🫧\tbubbles\n🪥\ttoothbrush\n🧽\tsponge\n🧯\tfire_extinguisher\n🛒\tshopping_trolley\n🚬\tsmoking\tsymbol\n⚰️\tcoffin\n🪦\theadstone\n⚱️\tfuneral_urn\n🧿\tnazar_amulet\n🪬\thamsa\n🗿\tmoyai\n🪧\tplacard\n🪪\tidentification_card\n🏧\tatm\tautomated teller machine\n🚮\tput_litter_in_its_place\tsymbol\n🚰\tpotable_water\tsymbol\n♿\twheelchair\tsymbol\n🚹\tmens\tsymbol\n🚺\twomens\tsymbol\n🚻\trestroom\n🚼\tbaby_symbol\n🚾\twc\twater closet\n🛂\tpassport_control\n🛃\tcustoms\n🛄\tbaggage_claim\n🛅\tleft_luggage\n⚠️\twarning\tsign\n🚸\tchildren_crossing\n⛔\tno_entry\n🚫\tno_entry_sign\n🚳\tno_bicycles\n🚭\tno_smoking\tsymbol\n🚯\tdo_not_litter\tsymbol\n🚱\tnon-potable_water\tnon-potable symbol\n🚷\tno_pedestrians\n📵\tno_mobile_phones\n🔞\tunderage\tno one under eighteen symbol\n☢️\tradioactive_sign\n☣️\tbiohazard_sign\n⬆️\tarrow_up\tupwards black\n↗️\tarrow_upper_right\tnorth east\n➡️\tarrow_right\tblack rightwards\n↘️\tarrow_lower_right\tsouth east\n⬇️\tarrow_down\tdownwards black\n↙️\tarrow_lower_left\tsouth west\n⬅️\tarrow_left\tleftwards black\n↖️\tarrow_upper_left\tnorth west\n↕️\tarrow_up_down\n↔️\tleft_right_arrow\n↩️\tleftwards_arrow_with_hook\n↪️\tarrow_right_hook\trightwards\n⤴️\tarrow_heading_up\tpointing rightwards then curving upwards\n⤵️\tarrow_heading_down\tpointing rightwards then curving downwards\n🔃\tarrows_clockwise\tdownwards upwards open circle\n🔄\tarrows_counterclockwise\tanticlockwise downwards upwards open circle\n🔙\tback\tleftwards arrow above\n🔚\tend\tleftwards arrow above\n🔛\ton\texclamation mark left right arrow above\n🔜\tsoon\trightwards arrow above\n🔝\ttop\tupwards arrow above\n🛐\tplace_of_worship\n⚛️\tatom_symbol\n🕉️\tom_symbol\n✡️\tstar_of_david\n☸️\twheel_of_dharma\n☯️\tyin_yang\n✝️\tlatin_cross\n☦️\torthodox_cross\n☪️\tstar_and_crescent\n☮️\tpeace_symbol\n🕎\tmenorah_with_nine_branches\n🔯\tsix_pointed_star\tmiddle dot\n🪯\tkhanda\n♈\taries\n♉\ttaurus\n♊\tgemini\n♋\tcancer\n♌\tleo\n♍\tvirgo\n♎\tlibra\n♏\tscorpius\n♐\tsagittarius\n♑\tcapricorn\n♒\taquarius\n♓\tpisces\n⛎\tophiuchus\n🔀\ttwisted_rightwards_arrows\n🔁\trepeat\tclockwise rightwards leftwards open circle arrows\n🔂\trepeat_one\tclockwise rightwards leftwards open circle arrows circled overlay\n▶️\tarrow_forward\tblack right-pointing triangle\n⏩\tfast_forward\tblack right-pointing double triangle\n⏭️\tblack_right_pointing_double_triangle_with_vertical_bar\tnext track button\n⏯️\tblack_right_pointing_triangle_with_double_vertical_bar\tplay pause button\n◀️\tarrow_backward\tblack left-pointing triangle\n⏪\trewind\tblack left-pointing double triangle\n⏮️\tblack_left_pointing_double_triangle_with_vertical_bar\tlast track button\n🔼\tarrow_up_small\tup-pointing red triangle\n⏫\tarrow_double_up\tblack up-pointing triangle\n🔽\tarrow_down_small\tdown-pointing red triangle\n⏬\tarrow_double_down\tblack down-pointing triangle\n⏸️\tdouble_vertical_bar\tpause button\n⏹️\tblack_square_for_stop\tbutton\n⏺️\tblack_circle_for_record\tbutton\n⏏️\teject\tbutton\n🎦\tcinema\n🔅\tlow_brightness\tsymbol\n🔆\thigh_brightness\tsymbol\n📶\tsignal_strength\tantenna bars\n🛜\twireless\n📳\tvibration_mode\n📴\tmobile_phone_off\n♀️\tfemale_sign\n♂️\tmale_sign\n⚧️\ttransgender_symbol\n✖️\theavy_multiplication_x\n➕\theavy_plus_sign\n➖\theavy_minus_sign\n➗\theavy_division_sign\n🟰\theavy_equals_sign\n♾️\tinfinity\n‼️\tbangbang\tdouble exclamation mark\n⁉️\tinterrobang\texclamation question mark\n❓\tquestion\tblack mark ornament\n❔\tgrey_question\twhite mark ornament\n❕\tgrey_exclamation\twhite mark ornament\n❗\texclamation heavy_exclamation_mark\tsymbol\n〰️\twavy_dash\n💱\tcurrency_exchange\n💲\theavy_dollar_sign\n⚕️\tmedical_symbol staff_of_aesculapius\n♻️\trecycle\tblack universal recycling symbol\n⚜️\tfleur_de_lis\tfleur-de-lis\n🔱\ttrident\temblem\n📛\tname_badge\n🔰\tbeginner\tjapanese symbol\n⭕\to\theavy large circle\n✅\twhite_check_mark\theavy\n☑️\tballot_box_with_check\n✔️\theavy_check_mark\n❌\tx\tcross mark\n❎\tnegative_squared_cross_mark\n➰\tcurly_loop\n➿\tloop\tdouble curly\n〽️\tpart_alternation_mark\n✳️\teight_spoked_asterisk\n✴️\teight_pointed_black_star\n❇️\tsparkle\n©️\tcopyright\tsign\n®️\tregistered\tsign\n™️\ttm\ttrade mark sign\n\tsplatter\n#️⃣\thash\tkey\n*️⃣\tkeycap_star\n0️⃣\tzero\tkeycap 0\n1️⃣\tone\tkeycap 1\n2️⃣\ttwo\tkeycap 2\n3️⃣\tthree\tkeycap 3\n4️⃣\tfour\tkeycap 4\n5️⃣\tfive\tkeycap 5\n6️⃣\tsix\tkeycap 6\n7️⃣\tseven\tkeycap 7\n8️⃣\teight\tkeycap 8\n9️⃣\tnine\tkeycap 9\n🔟\tkeycap_ten\n🔠\tcapital_abcd\tinput symbol latin letters\n🔡\tabcd\tinput symbol latin small letters\n🔢\t1234\tinput symbol numbers\n🔣\tsymbols\tinput symbol\n🔤\tabc\tinput symbol latin letters\n🅰️\ta\tnegative squared latin capital letter\n🆎\tab\tnegative squared\n🅱️\tb\tnegative squared latin capital letter\n🆑\tcl\tsquared\n🆒\tcool\tsquared\n🆓\tfree\tsquared\nℹ️\tinformation_source\n🆔\tid\tsquared\nⓂ️\tm\tcircled latin capital letter\n🆕\tnew\tsquared\n🆖\tng\tsquared\n🅾️\to2\tnegative squared latin capital letter o\n🆗\tok\tsquared\n🅿️\tparking\tnegative squared latin capital letter p\n🆘\tsos\tsquared\n🆙\tup\tsquared exclamation mark\n🆚\tvs\tsquared\n🈁\tkoko\tsquared katakana\n🈂️\tsa\tsquared katakana\n🈷️\tu6708\tsquared cjk unified ideograph-6708\n🈶\tu6709\tsquared cjk unified ideograph-6709\n🈯\tu6307\tsquared cjk unified ideograph-6307\n🉐\tideograph_advantage\tcircled\n🈹\tu5272\tsquared cjk unified ideograph-5272\n🈚\tu7121\tsquared cjk unified ideograph-7121\n🈲\tu7981\tsquared cjk unified ideograph-7981\n🉑\taccept\tcircled ideograph\n🈸\tu7533\tsquared cjk unified ideograph-7533\n🈴\tu5408\tsquared cjk unified ideograph-5408\n🈳\tu7a7a\tsquared cjk unified ideograph-7a7a\n㊗️\tcongratulations\tcircled ideograph congratulation\n㊙️\tsecret\tcircled ideograph\n🈺\tu55b6\tsquared cjk unified ideograph-55b6\n🈵\tu6e80\tsquared cjk unified ideograph-6e80\n🔴\tred_circle\tlarge\n🟠\tlarge_orange_circle\n🟡\tlarge_yellow_circle\n🟢\tlarge_green_circle\n🔵\tlarge_blue_circle\n🟣\tlarge_purple_circle\n🟤\tlarge_brown_circle\n⚫\tblack_circle\tmedium\n⚪\twhite_circle\tmedium\n🟥\tlarge_red_square\n🟧\tlarge_orange_square\n🟨\tlarge_yellow_square\n🟩\tlarge_green_square\n🟦\tlarge_blue_square\n🟪\tlarge_purple_square\n🟫\tlarge_brown_square\n⬛\tblack_large_square\n⬜\twhite_large_square\n◼️\tblack_medium_square\n◻️\twhite_medium_square\n◾\tblack_medium_small_square\n◽\twhite_medium_small_square\n▪️\tblack_small_square\n▫️\twhite_small_square\n🔶\tlarge_orange_diamond\n🔷\tlarge_blue_diamond\n🔸\tsmall_orange_diamond\n🔹\tsmall_blue_diamond\n🔺\tsmall_red_triangle\tup-pointing\n🔻\tsmall_red_triangle_down\tdown-pointing\n💠\tdiamond_shape_with_a_dot_inside\n🔘\tradio_button\n🔳\twhite_square_button\n🔲\tblack_square_button\n🏁\tcheckered_flag\tchequered\n🚩\ttriangular_flag_on_post\n🎌\tcrossed_flags\n🏴\twaving_black_flag\n🏳️\twaving_white_flag\n🏳️🌈\trainbow-flag\n🏳️⚧️\ttransgender_flag\n🏴☠️\tpirate_flag\n🇦🇨\tflag-ac\tascension island\n🇦🇩\tflag-ad\tandorra\n🇦🇪\tflag-ae\tunited arab emirates\n🇦🇫\tflag-af\tafghanistan\n🇦🇬\tflag-ag\tantigua barbuda\n🇦🇮\tflag-ai\tanguilla\n🇦🇱\tflag-al\talbania\n🇦🇲\tflag-am\tarmenia\n🇦🇴\tflag-ao\tangola\n🇦🇶\tflag-aq\tantarctica\n🇦🇷\tflag-ar\targentina\n🇦🇸\tflag-as\tamerican samoa\n🇦🇹\tflag-at\taustria\n🇦🇺\tflag-au\taustralia\n🇦🇼\tflag-aw\taruba\n🇦🇽\tflag-ax\tland islands\n🇦🇿\tflag-az\tazerbaijan\n🇧🇦\tflag-ba\tbosnia herzegovina\n🇧🇧\tflag-bb\tbarbados\n🇧🇩\tflag-bd\tbangladesh\n🇧🇪\tflag-be\tbelgium\n🇧🇫\tflag-bf\tburkina faso\n🇧🇬\tflag-bg\tbulgaria\n🇧🇭\tflag-bh\tbahrain\n🇧🇮\tflag-bi\tburundi\n🇧🇯\tflag-bj\tbenin\n🇧🇱\tflag-bl\tst barth lemy\n🇧🇲\tflag-bm\tbermuda\n🇧🇳\tflag-bn\tbrunei\n🇧🇴\tflag-bo\tbolivia\n🇧🇶\tflag-bq\tcaribbean netherlands\n🇧🇷\tflag-br\tbrazil\n🇧🇸\tflag-bs\tbahamas\n🇧🇹\tflag-bt\tbhutan\n🇧🇻\tflag-bv\tbouvet island\n🇧🇼\tflag-bw\tbotswana\n🇧🇾\tflag-by\tbelarus\n🇧🇿\tflag-bz\tbelize\n🇨🇦\tflag-ca\tcanada\n🇨🇨\tflag-cc\tcocos keeling islands\n🇨🇩\tflag-cd\tcongo - kinshasa\n🇨🇫\tflag-cf\tcentral african republic\n🇨🇬\tflag-cg\tcongo - brazzaville\n🇨🇭\tflag-ch\tswitzerland\n🇨🇮\tflag-ci\tc te d ivoire\n🇨🇰\tflag-ck\tcook islands\n🇨🇱\tflag-cl\tchile\n🇨🇲\tflag-cm\tcameroon\n🇨🇳\tcn flag-cn\tchina\n🇨🇴\tflag-co\tcolombia\n🇨🇵\tflag-cp\tclipperton island\n🇨🇶\tflag-sark\n🇨🇷\tflag-cr\tcosta rica\n🇨🇺\tflag-cu\tcuba\n🇨🇻\tflag-cv\tcape verde\n🇨🇼\tflag-cw\tcura ao\n🇨🇽\tflag-cx\tchristmas island\n🇨🇾\tflag-cy\tcyprus\n🇨🇿\tflag-cz\tczechia\n🇩🇪\tde flag-de\tgermany\n🇩🇬\tflag-dg\tdiego garcia\n🇩🇯\tflag-dj\tdjibouti\n🇩🇰\tflag-dk\tdenmark\n🇩🇲\tflag-dm\tdominica\n🇩🇴\tflag-do\tdominican republic\n🇩🇿\tflag-dz\talgeria\n🇪🇦\tflag-ea\tceuta melilla\n🇪🇨\tflag-ec\tecuador\n🇪🇪\tflag-ee\testonia\n🇪🇬\tflag-eg\tegypt\n🇪🇭\tflag-eh\twestern sahara\n🇪🇷\tflag-er\teritrea\n🇪🇸\tes flag-es\tspain\n🇪🇹\tflag-et\tethiopia\n🇪🇺\tflag-eu\teuropean union\n🇫🇮\tflag-fi\tfinland\n🇫🇯\tflag-fj\tfiji\n🇫🇰\tflag-fk\tfalkland islands\n🇫🇲\tflag-fm\tmicronesia\n🇫🇴\tflag-fo\tfaroe islands\n🇫🇷\tfr flag-fr\tfrance\n🇬🇦\tflag-ga\tgabon\n🇬🇧\tgb uk flag-gb\tunited kingdom\n🇬🇩\tflag-gd\tgrenada\n🇬🇪\tflag-ge\tgeorgia\n🇬🇫\tflag-gf\tfrench guiana\n🇬🇬\tflag-gg\tguernsey\n🇬🇭\tflag-gh\tghana\n🇬🇮\tflag-gi\tgibraltar\n🇬🇱\tflag-gl\tgreenland\n🇬🇲\tflag-gm\tgambia\n🇬🇳\tflag-gn\tguinea\n🇬🇵\tflag-gp\tguadeloupe\n🇬🇶\tflag-gq\tequatorial guinea\n🇬🇷\tflag-gr\tgreece\n🇬🇸\tflag-gs\tsouth georgia sandwich islands\n🇬🇹\tflag-gt\tguatemala\n🇬🇺\tflag-gu\tguam\n🇬🇼\tflag-gw\tguinea-bissau\n🇬🇾\tflag-gy\tguyana\n🇭🇰\tflag-hk\thong kong sar china\n🇭🇲\tflag-hm\theard mcdonald islands\n🇭🇳\tflag-hn\thonduras\n🇭🇷\tflag-hr\tcroatia\n🇭🇹\tflag-ht\thaiti\n🇭🇺\tflag-hu\thungary\n🇮🇨\tflag-ic\tcanary islands\n🇮🇩\tflag-id\tindonesia\n🇮🇪\tflag-ie\tireland\n🇮🇱\tflag-il\tisrael\n🇮🇲\tflag-im\tisle man\n🇮🇳\tflag-in\tindia\n🇮🇴\tflag-io\tbritish indian ocean territory\n🇮🇶\tflag-iq\tiraq\n🇮🇷\tflag-ir\tiran\n🇮🇸\tflag-is\ticeland\n🇮🇹\tit flag-it\titaly\n🇯🇪\tflag-je\tjersey\n🇯🇲\tflag-jm\tjamaica\n🇯🇴\tflag-jo\tjordan\n🇯🇵\tjp flag-jp\tjapan\n🇰🇪\tflag-ke\tkenya\n🇰🇬\tflag-kg\tkyrgyzstan\n🇰🇭\tflag-kh\tcambodia\n🇰🇮\tflag-ki\tkiribati\n🇰🇲\tflag-km\tcomoros\n🇰🇳\tflag-kn\tst kitts nevis\n🇰🇵\tflag-kp\tnorth korea\n🇰🇷\tkr flag-kr\tsouth korea\n🇰🇼\tflag-kw\tkuwait\n🇰🇾\tflag-ky\tcayman islands\n🇰🇿\tflag-kz\tkazakhstan\n🇱🇦\tflag-la\tlaos\n🇱🇧\tflag-lb\tlebanon\n🇱🇨\tflag-lc\tst lucia\n🇱🇮\tflag-li\tliechtenstein\n🇱🇰\tflag-lk\tsri lanka\n🇱🇷\tflag-lr\tliberia\n🇱🇸\tflag-ls\tlesotho\n🇱🇹\tflag-lt\tlithuania\n🇱🇺\tflag-lu\tluxembourg\n🇱🇻\tflag-lv\tlatvia\n🇱🇾\tflag-ly\tlibya\n🇲🇦\tflag-ma\tmorocco\n🇲🇨\tflag-mc\tmonaco\n🇲🇩\tflag-md\tmoldova\n🇲🇪\tflag-me\tmontenegro\n🇲🇫\tflag-mf\tst martin\n🇲🇬\tflag-mg\tmadagascar\n🇲🇭\tflag-mh\tmarshall islands\n🇲🇰\tflag-mk\tnorth macedonia\n🇲🇱\tflag-ml\tmali\n🇲🇲\tflag-mm\tmyanmar burma\n🇲🇳\tflag-mn\tmongolia\n🇲🇴\tflag-mo\tmacao sar china\n🇲🇵\tflag-mp\tnorthern mariana islands\n🇲🇶\tflag-mq\tmartinique\n🇲🇷\tflag-mr\tmauritania\n🇲🇸\tflag-ms\tmontserrat\n🇲🇹\tflag-mt\tmalta\n🇲🇺\tflag-mu\tmauritius\n🇲🇻\tflag-mv\tmaldives\n🇲🇼\tflag-mw\tmalawi\n🇲🇽\tflag-mx\tmexico\n🇲🇾\tflag-my\tmalaysia\n🇲🇿\tflag-mz\tmozambique\n🇳🇦\tflag-na\tnamibia\n🇳🇨\tflag-nc\tnew caledonia\n🇳🇪\tflag-ne\tniger\n🇳🇫\tflag-nf\tnorfolk island\n🇳🇬\tflag-ng\tnigeria\n🇳🇮\tflag-ni\tnicaragua\n🇳🇱\tflag-nl\tnetherlands\n🇳🇴\tflag-no\tnorway\n🇳🇵\tflag-np\tnepal\n🇳🇷\tflag-nr\tnauru\n🇳🇺\tflag-nu\tniue\n🇳🇿\tflag-nz\tnew zealand\n🇴🇲\tflag-om\toman\n🇵🇦\tflag-pa\tpanama\n🇵🇪\tflag-pe\tperu\n🇵🇫\tflag-pf\tfrench polynesia\n🇵🇬\tflag-pg\tpapua new guinea\n🇵🇭\tflag-ph\tphilippines\n🇵🇰\tflag-pk\tpakistan\n🇵🇱\tflag-pl\tpoland\n🇵🇲\tflag-pm\tst pierre miquelon\n🇵🇳\tflag-pn\tpitcairn islands\n🇵🇷\tflag-pr\tpuerto rico\n🇵🇸\tflag-ps\tpalestinian territories\n🇵🇹\tflag-pt\tportugal\n🇵🇼\tflag-pw\tpalau\n🇵🇾\tflag-py\tparaguay\n🇶🇦\tflag-qa\tqatar\n🇷🇪\tflag-re\tr union\n🇷🇴\tflag-ro\tromania\n🇷🇸\tflag-rs\tserbia\n🇷🇺\tru flag-ru\trussia\n🇷🇼\tflag-rw\trwanda\n🇸🇦\tflag-sa\tsaudi arabia\n🇸🇧\tflag-sb\tsolomon islands\n🇸🇨\tflag-sc\tseychelles\n🇸🇩\tflag-sd\tsudan\n🇸🇪\tflag-se\tsweden\n🇸🇬\tflag-sg\tsingapore\n🇸🇭\tflag-sh\tst helena\n🇸🇮\tflag-si\tslovenia\n🇸🇯\tflag-sj\tsvalbard jan mayen\n🇸🇰\tflag-sk\tslovakia\n🇸🇱\tflag-sl\tsierra leone\n🇸🇲\tflag-sm\tsan marino\n🇸🇳\tflag-sn\tsenegal\n🇸🇴\tflag-so\tsomalia\n🇸🇷\tflag-sr\tsuriname\n🇸🇸\tflag-ss\tsouth sudan\n🇸🇹\tflag-st\ts o tom pr ncipe\n🇸🇻\tflag-sv\tel salvador\n🇸🇽\tflag-sx\tsint maarten\n🇸🇾\tflag-sy\tsyria\n🇸🇿\tflag-sz\teswatini\n🇹🇦\tflag-ta\ttristan da cunha\n🇹🇨\tflag-tc\tturks caicos islands\n🇹🇩\tflag-td\tchad\n🇹🇫\tflag-tf\tfrench southern territories\n🇹🇬\tflag-tg\ttogo\n🇹🇭\tflag-th\tthailand\n🇹🇯\tflag-tj\ttajikistan\n🇹🇰\tflag-tk\ttokelau\n🇹🇱\tflag-tl\ttimor-leste\n🇹🇲\tflag-tm\tturkmenistan\n🇹🇳\tflag-tn\ttunisia\n🇹🇴\tflag-to\ttonga\n🇹🇷\tflag-tr\tt rkiye\n🇹🇹\tflag-tt\ttrinidad tobago\n🇹🇻\tflag-tv\ttuvalu\n🇹🇼\tflag-tw\ttaiwan\n🇹🇿\tflag-tz\ttanzania\n🇺🇦\tflag-ua\tukraine\n🇺🇬\tflag-ug\tuganda\n🇺🇲\tflag-um\tu s outlying islands\n🇺🇳\tflag-un\tunited nations\n🇺🇸\tus flag-us\tunited states\n🇺🇾\tflag-uy\turuguay\n🇺🇿\tflag-uz\tuzbekistan\n🇻🇦\tflag-va\tvatican city\n🇻🇨\tflag-vc\tst vincent grenadines\n🇻🇪\tflag-ve\tvenezuela\n🇻🇬\tflag-vg\tbritish virgin islands\n🇻🇮\tflag-vi\tu s virgin islands\n🇻🇳\tflag-vn\tvietnam\n🇻🇺\tflag-vu\tvanuatu\n🇼🇫\tflag-wf\twallis futuna\n🇼🇸\tflag-ws\tsamoa\n🇽🇰\tflag-xk\tkosovo\n🇾🇪\tflag-ye\tyemen\n🇾🇹\tflag-yt\tmayotte\n🇿🇦\tflag-za\tsouth africa\n🇿🇲\tflag-zm\tzambia\n🇿🇼\tflag-zw\tzimbabwe\n🏴\tflag-england\n🏴\tflag-scotland\n🏴\tflag-wales";
|