diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 8ddcc22..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2025 aspizu
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/README.md b/README.md
deleted file mode 100644
index cfba980..0000000
--- a/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# `std` is the goboscript standard library
-
-[](https://deepwiki.com/goboscript/std)
-
-## Installation
-
-Add the following to your `goboscript.toml` file:
-
-```toml
-std = "2.1.0"
-```
diff --git a/base64.gs b/base64.gs
new file mode 100644
index 0000000..93fcff8
--- /dev/null
+++ b/base64.gs
@@ -0,0 +1,108 @@
+list base64_buffer;
+list base64_strbuf;
+list base64_lut; # lookup table: ASCII costume_number -> base64 value (0-63), 255=invalid/pad
+
+%define BASE64_CHARSET "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
+%define BASE64_URLSAFE "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_="
+
+# Build LUT from a charset string into base64_lut.
+# base64_lut[costume_number_of_char] = base64 value (0-63), or 255 for '='
+proc base64_build_lut charset {
+ delete base64_lut;
+ # Fill 256 slots with 255 (invalid)
+ local j = 0;
+ repeat 256 {
+ add 255 to base64_lut;
+ j++;
+ }
+ # Map each charset char to its index (0-63), slot 65 (index 64) is '=' -> 255 already
+ local idx = 0;
+ repeat 64 {
+ switch_costume $charset[1 + idx];
+ base64_lut[costume_number()] = idx;
+ idx++;
+ }
+}
+
+func base64_encode(charset) {
+ delete base64_strbuf;
+ local i = 1;
+ until i > length(base64_buffer) {
+ local a6 = base64_buffer[i] // 0b100;
+ local a2 = base64_buffer[i] % 0b100;
+ add $charset[1 + a6] to base64_strbuf;
+ i++;
+ if i <= length(base64_buffer) {
+ local b4hi = base64_buffer[i] // 0x10;
+ local b4lo = base64_buffer[i] % 0x10;
+ add $charset[1 + a2 * 0x10 + b4hi] to base64_strbuf;
+ i++;
+ if i <= length(base64_buffer) {
+ local c2 = base64_buffer[i] // 0b1000000;
+ local c6 = base64_buffer[i] % 0b1000000;
+ add $charset[1 + b4lo * 4 + c2] to base64_strbuf;
+ add $charset[1 + c6] to base64_strbuf;
+ i++;
+ } else {
+ add $charset[1 + b4lo * 4] to base64_strbuf;
+ add $charset[65] to base64_strbuf;
+ }
+ } else {
+ add $charset[1 + a2 * 0x10] to base64_strbuf;
+ add $charset[65] & $charset[65] to base64_strbuf;
+ }
+ }
+ return base64_strbuf;
+}
+
+# Decode base64 string $data into base64_buffer.
+# Call base64_build_lut with the appropriate charset before calling this.
+# Appends decoded bytes to base64_buffer (clear it first if needed).
+proc base64_decode data {
+ local len = length($data);
+ local i = 1;
+ until i > len {
+ # Read up to 4 base64 chars, get their 6-bit values via LUT
+ switch_costume $data[i];
+ local v0 = base64_lut[costume_number()];
+ i++;
+
+ switch_costume $data[i];
+ local v1 = base64_lut[costume_number()];
+ i++;
+
+ # Byte 1: high 6 bits from v0, low 2 bits from v1 high
+ add v0 * 4 + v1 // 16 to base64_buffer;
+
+ # Check for padding or end: if 3rd char is '=' or beyond end, stop
+ if i > len {
+ stop_this_script;
+ }
+ switch_costume $data[i];
+ local v2 = base64_lut[costume_number()];
+ i++;
+
+ if v2 == 255 {
+ # Padding '=' — only 2 encoded chars, 1 decoded byte (already added)
+ stop_this_script;
+ }
+
+ # Byte 2: low 4 bits of v1, high 4 bits of v2
+ add (v1 % 16) * 16 + v2 // 4 to base64_buffer;
+
+ if i > len {
+ stop_this_script;
+ }
+ switch_costume $data[i];
+ local v3 = base64_lut[costume_number()];
+ i++;
+
+ if v3 == 255 {
+ # Padding '=' — only 3 encoded chars, 2 decoded bytes
+ stop_this_script;
+ }
+
+ # Byte 3: low 2 bits of v2, all 6 bits of v3
+ add (v2 % 4) * 64 + v3 to base64_buffer;
+ }
+}
diff --git a/bitwise.gs b/bitwise.gs
new file mode 100644
index 0000000..aa4e67f
--- /dev/null
+++ b/bitwise.gs
@@ -0,0 +1,72 @@
+list xor4 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14, 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13, 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15, 8, 9, 10, 11, 5, 4, 7, 6, 1, 0, 3, 2, 13, 12, 15, 14, 9, 8, 11, 10, 6, 7, 4, 5, 2, 3, 0, 1, 14, 15, 12, 13, 10, 11, 8, 9, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 9, 8, 11, 10, 13, 12, 15, 14, 1, 0, 3, 2, 5, 4, 7, 6, 10, 11, 8, 9, 14, 15, 12, 13, 2, 3, 0, 1, 6, 7, 4, 5, 11, 10, 9, 8, 15, 14, 13, 12, 3, 2, 1, 0, 7, 6, 5, 4, 12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3, 13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2, 14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0];
+list and4 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 4, 4, 4, 4, 0, 1, 0, 1, 4, 5, 4, 5, 0, 1, 0, 1, 4, 5, 4, 5, 0, 0, 2, 2, 4, 4, 6, 6, 0, 0, 2, 2, 4, 4, 6, 6, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 0, 1, 0, 1, 0, 1, 0, 1, 8, 9, 8, 9, 8, 9, 8, 9, 0, 0, 2, 2, 0, 0, 2, 2, 8, 8, 10, 10, 8, 8, 10, 10, 0, 1, 2, 3, 0, 1, 2, 3, 8, 9, 10, 11, 8, 9, 10, 11, 0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, 12, 12, 0, 1, 0, 1, 4, 5, 4, 5, 8, 9, 8, 9, 12, 13, 12, 13, 0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
+list or4 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1, 1, 3, 3, 5, 5, 7, 7, 9, 9, 11, 11, 13, 13, 15, 15, 2, 3, 2, 3, 6, 7, 6, 7, 10, 11, 10, 11, 14, 15, 14, 15, 3, 3, 3, 3, 7, 7, 7, 7, 11, 11, 11, 11, 15, 15, 15, 15, 4, 5, 6, 7, 4, 5, 6, 7, 12, 13, 14, 15, 12, 13, 14, 15, 5, 5, 7, 7, 5, 5, 7, 7, 13, 13, 15, 15, 13, 13, 15, 15, 6, 7, 6, 7, 6, 7, 6, 7, 14, 15, 14, 15, 14, 15, 14, 15, 7, 7, 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15, 15, 15, 8, 9, 10, 11, 12, 13, 14, 15, 8, 9, 10, 11, 12, 13, 14, 15, 9, 9, 11, 11, 13, 13, 15, 15, 9, 9, 11, 11, 13, 13, 15, 15, 10, 11, 10, 11, 14, 15, 14, 15, 10, 11, 10, 11, 14, 15, 14, 15, 11, 11, 11, 11, 15, 15, 15, 15, 11, 11, 11, 11, 15, 15, 15, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 13, 13, 15, 15, 13, 13, 15, 15, 13, 13, 15, 15, 13, 13, 15, 15, 14, 15, 14, 15, 14, 15, 14, 15, 14, 15, 14, 15, 14, 15, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15];
+
+%define XOR4(A, B) xor4[1+(A)*0x10+(B)]
+
+func xor8(a, b) {
+ return XOR4($a//0x10, $b//0x10)*0x10 + XOR4($a%0x10, $b%0x10);
+}
+
+func xor16(a, b) {
+ return xor8($a//0x100, $b//0x100)*0x100 + xor8($a%0x100, $b%0x100);
+}
+
+func xor32(a, b) {
+ return xor16($a//0x10000, $b//0x10000)*0x10000 + xor16($a%0x10000, $b%0x10000);
+}
+
+%define AND4(A, B) and4[1+(A)*0x10+(B)]
+%define OR4(A, B) or4[1+(A)*0x10+(B)]
+
+func and8(a, b) {
+ return AND4($a//0x10, $b//0x10)*0x10 + AND4($a%0x10, $b%0x10);
+}
+
+func and16(a, b) {
+ return and8($a//0x100, $b//0x100)*0x100 + and8($a%0x100, $b%0x100);
+}
+
+func and32(a, b) {
+ return and16($a//0x10000, $b//0x10000)*0x10000 + and16($a%0x10000, $b%0x10000);
+}
+
+func or8(a, b) {
+ return OR4($a//0x10, $b//0x10)*0x10 + OR4($a%0x10, $b%0x10);
+}
+
+func or16(a, b) {
+ return or8($a//0x100, $b//0x100)*0x100 + or8($a%0x100, $b%0x100);
+}
+
+func or32(a, b) {
+ return or16($a//0x10000, $b//0x10000)*0x10000 + or16($a%0x10000, $b%0x10000);
+}
+
+%define NOT4(A) XOR4((A), 0xF)
+
+func not8(a) {
+ return xor8($a, 0xFF);
+}
+
+func not16(a) {
+ return xor16($a, 0xFFFF);
+}
+
+func not32(a) {
+ return xor32($a, 0xFFFFFFFF);
+}
+
+%define ADD32(A,B) (((A)+(B))%0x100000000)
+
+func add32(a, b) {
+ return ($a + $b) % 0x100000000;
+}
+
+%define ROL32(A) ((((A)*2)%0x100000000)+((A) > 0x7FFFFFFF))
+
+func rol32(a, b) {
+ local a = $a;
+ repeat $b % 32 { a = ROL32(a); }
+ return a;
+}
diff --git a/bytes.gs b/bytes.gs
new file mode 100644
index 0000000..7574877
--- /dev/null
+++ b/bytes.gs
@@ -0,0 +1,54 @@
+list bytes_strbuf;
+
+list bytes_hex_table = ["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF", "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF", "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF", "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF", "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF", "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF"];
+
+%define BYTES_ENCODE_ASCII(LIST) \
+ local i = 1; \
+ repeat length($text) { \
+ switch_costume $text[i]; \
+ add costume_number()+31 to LIST; \
+ i++; \
+ }
+
+%define BYTES_DECODE_ASCII(LIST) \
+ delete bytes_strbuf; \
+ local start = $start; \
+ local end = $end; \
+ if start < 0 { \
+ start = length(LIST) + start + 1; \
+ } \
+ if end < 0 { \
+ end = length(LIST) + end + 1; \
+ } \
+ local i = start; \
+ repeat end - start + 1 { \
+ switch_costume LIST[i]-31; \
+ add costume_name() to bytes_strbuf; \
+ i++; \
+ } \
+ return bytes_strbuf;
+
+%define BYTES_ENCODE_HEX(LIST) \
+ local i = 1; \
+ repeat length($text)//2 { \
+ add ("0x"&$text[i]&$text[i+1]) to LIST; \
+ i+=2; \
+ }
+
+%define BYTES_DECODE_HEX(LIST) \
+ delete bytes_strbuf; \
+ local start = $start; \
+ local end = $end; \
+ if start < 0 { \
+ start = length(LIST) + start + 1; \
+ } \
+ if end < 0 { \
+ end = length(LIST) + end + 1; \
+ } \
+ local i = start; \
+ repeat end - start + 1 { \
+ add bytes_hex_table[1+LIST[i]][1] to bytes_strbuf; \
+ add bytes_hex_table[1+LIST[i]][2] to bytes_strbuf; \
+ i++; \
+ } \
+ return bytes_strbuf;
diff --git a/cmd.gs b/cmd.gs
deleted file mode 100644
index fc596ad..0000000
--- a/cmd.gs
+++ /dev/null
@@ -1,65 +0,0 @@
-list cmd_args;
-
-func cmd_next(start, cmd) {
- delete cmd_args;
- local key = "";
- local single_quote = false;
- local double_quote = false;
- local i = $start;
- until i > length($cmd) {
- if single_quote {
- if $cmd[i] == "'" and $cmd[i-1] != "\\" {
- single_quote = false;
- add key to cmd_args;
- key = "";
- }
- else {
- key &= $cmd[i];
- }
- }
- elif double_quote {
- if $cmd[i] == "\"" {
- double_quote = false;
- add key to cmd_args;
- key = "";
- }
- elif $cmd[i] == "\\" {
- i++;
- key &= $cmd[i];
- }
- else {
- key &= $cmd[i];
- }
- }
- elif $cmd[i] == "\"" {
- double_quote = true;
- }
- elif $cmd[i] == "'" {
- single_quote = true;
- }
- elif $cmd[i] == " " {
- if key != "" {
- add key to cmd_args;
- key = "";
- }
- }
- elif $cmd[i] == ";" {
- if key != "" {
- add key to cmd_args;
- }
- return i+1;
- }
- elif $cmd[i] == "\\" {
- i++;
- key &= $cmd[i];
- }
- else {
- key &= $cmd[i];
- }
- i++;
- }
- if key != "" {
- add key to cmd_args;
- }
- return 0;
-}
diff --git a/cskv.gs b/cskv.gs
deleted file mode 100644
index ec3f72d..0000000
--- a/cskv.gs
+++ /dev/null
@@ -1,74 +0,0 @@
-list cskv;
-list cskv_keys;
-list cskv_key_map;
-
-%define CSKV_GET_INDEX(key) cskv_key_map[(key) in cskv_keys]
-%define CSKV_GET(key) cskv[cskv_key_map[(key) in cskv_keys]]
-
-proc cskv_unpack text {
- delete cskv;
- local token = "";
- local i = 0;
- until i > length($text) {
- if $text[i] == "\\" {
- if $text[i+1] in ",:\\" {
- token &= $text[i+1];
- i++;
- } else {
- token &= "\\";
- }
- } elif $text[i] == "," {
- add token to cskv;
- token = "";
- } elif $text[i] == ":" {
- add token to cskv_keys;
- add 1+length(cskv) to cskv_key_map;
- token = "";
- } else {
- token &= $text[i];
- }
- i++;
- }
- add token to cskv;
-}
-
-func cskv_pack() {
- local result = "";
- local i = 1;
- until i > length(cskv_keys) {
- result &= cskv_keys[i] & ":";
- if (cskv_key_map[i+1] - cskv_key_map[i]) > 2 {
- result &= cskv[cskv_key_map[i]] & ",";
- local j = 1;
- until j > cskv[cskv_key_map[i]] {
- local element = cskv[cskv_key_map[i] + j];
- local k = 1;
- until k > length(element) {
- if element[k] in "\\,:" {
- result &= "\\";
- }
- result &= element[k];
- k++;
- }
- j++;
- if i < length(cskv_keys) or j < cskv[cskv_key_map[i]] {
- result &= ",";
- }
- }
- } else {
- local j = 1;
- until j > length(cskv[cskv_key_map[i]]) {
- if cskv[cskv_key_map[i]][j] in "\\,:" {
- result &= "\\";
- }
- result &= cskv[cskv_key_map[i]][j];
- j++;
- }
- if i < length(cskv_keys) {
- result &= ",";
- }
- }
- i++;
- }
- return result;
-}
diff --git a/emoji.gs b/emoji.gs
deleted file mode 100644
index 524a82f..0000000
--- a/emoji.gs
+++ /dev/null
@@ -1,11452 +0,0 @@
-# Return the emoji for the shortcode `NAME`.
-%define EMOJI(NAME) emoji_values[(NAME) in emoji_names]
-
-# List of all emoji shortcodes.
-list emoji_names = [
- "100",
- "1234",
- "soccer",
- "soccer_ball",
- "basketball",
- "football",
- "baseball",
- "softball",
- "tennis",
- "volleyball",
- "rugby_football",
- "flying_disc",
- "8ball",
- "yo_yo",
- "ping_pong",
- "table_tennis",
- "badminton",
- "hockey",
- "ice_hockey",
- "field_hockey",
- "lacrosse",
- "cricket_game",
- "cricket_bat_ball",
- "boomerang",
- "goal",
- "goal_net",
- "golf",
- "flag_in_hole",
- "kite",
- "playground_slide",
- "bow_and_arrow",
- "archery",
- "fishing_pole_and_fish",
- "fishing_pole",
- "diving_mask",
- "boxing_glove",
- "boxing_gloves",
- "martial_arts_uniform",
- "karate_uniform",
- "running_shirt_with_sash",
- "running_shirt",
- "skateboard",
- "roller_skate",
- "sled",
- "ice_skate",
- "curling_stone",
- "ski",
- "skis",
- "skier",
- "snowboarder",
- "snowboarder_tone1",
- "snowboarder_light_skin_tone",
- "snowboarder_tone2",
- "snowboarder_medium_light_skin_tone",
- "snowboarder_tone3",
- "snowboarder_medium_skin_tone",
- "snowboarder_tone4",
- "snowboarder_medium_dark_skin_tone",
- "snowboarder_tone5",
- "snowboarder_dark_skin_tone",
- "parachute",
- "person_lifting_weights",
- "lifter",
- "weight_lifter",
- "person_lifting_weights_tone1",
- "lifter_tone1",
- "weight_lifter_tone1",
- "person_lifting_weights_tone2",
- "lifter_tone2",
- "weight_lifter_tone2",
- "person_lifting_weights_tone3",
- "lifter_tone3",
- "weight_lifter_tone3",
- "person_lifting_weights_tone4",
- "lifter_tone4",
- "weight_lifter_tone4",
- "person_lifting_weights_tone5",
- "lifter_tone5",
- "weight_lifter_tone5",
- "woman_lifting_weights",
- "woman_lifting_weights_tone1",
- "woman_lifting_weights_light_skin_tone",
- "woman_lifting_weights_tone2",
- "woman_lifting_weights_medium_light_skin_tone",
- "woman_lifting_weights_tone3",
- "woman_lifting_weights_medium_skin_tone",
- "woman_lifting_weights_tone4",
- "woman_lifting_weights_medium_dark_skin_tone",
- "woman_lifting_weights_tone5",
- "woman_lifting_weights_dark_skin_tone",
- "man_lifting_weights",
- "man_lifting_weights_tone1",
- "man_lifting_weights_light_skin_tone",
- "man_lifting_weights_tone2",
- "man_lifting_weights_medium_light_skin_tone",
- "man_lifting_weights_tone3",
- "man_lifting_weights_medium_skin_tone",
- "man_lifting_weights_tone4",
- "man_lifting_weights_medium_dark_skin_tone",
- "man_lifting_weights_tone5",
- "man_lifting_weights_dark_skin_tone",
- "people_wrestling",
- "wrestlers",
- "wrestling",
- "women_wrestling",
- "men_wrestling",
- "person_doing_cartwheel",
- "cartwheel",
- "person_doing_cartwheel_tone1",
- "cartwheel_tone1",
- "person_doing_cartwheel_tone2",
- "cartwheel_tone2",
- "person_doing_cartwheel_tone3",
- "cartwheel_tone3",
- "person_doing_cartwheel_tone4",
- "cartwheel_tone4",
- "person_doing_cartwheel_tone5",
- "cartwheel_tone5",
- "woman_cartwheeling",
- "woman_cartwheeling_tone1",
- "woman_cartwheeling_light_skin_tone",
- "woman_cartwheeling_tone2",
- "woman_cartwheeling_medium_light_skin_tone",
- "woman_cartwheeling_tone3",
- "woman_cartwheeling_medium_skin_tone",
- "woman_cartwheeling_tone4",
- "woman_cartwheeling_medium_dark_skin_tone",
- "woman_cartwheeling_tone5",
- "woman_cartwheeling_dark_skin_tone",
- "man_cartwheeling",
- "man_cartwheeling_tone1",
- "man_cartwheeling_light_skin_tone",
- "man_cartwheeling_tone2",
- "man_cartwheeling_medium_light_skin_tone",
- "man_cartwheeling_tone3",
- "man_cartwheeling_medium_skin_tone",
- "man_cartwheeling_tone4",
- "man_cartwheeling_medium_dark_skin_tone",
- "man_cartwheeling_tone5",
- "man_cartwheeling_dark_skin_tone",
- "person_bouncing_ball",
- "basketball_player",
- "person_with_ball",
- "person_bouncing_ball_tone1",
- "basketball_player_tone1",
- "person_with_ball_tone1",
- "person_bouncing_ball_tone2",
- "basketball_player_tone2",
- "person_with_ball_tone2",
- "person_bouncing_ball_tone3",
- "basketball_player_tone3",
- "person_with_ball_tone3",
- "person_bouncing_ball_tone4",
- "basketball_player_tone4",
- "person_with_ball_tone4",
- "person_bouncing_ball_tone5",
- "basketball_player_tone5",
- "person_with_ball_tone5",
- "woman_bouncing_ball",
- "woman_bouncing_ball_tone1",
- "woman_bouncing_ball_light_skin_tone",
- "woman_bouncing_ball_tone2",
- "woman_bouncing_ball_medium_light_skin_tone",
- "woman_bouncing_ball_tone3",
- "woman_bouncing_ball_medium_skin_tone",
- "woman_bouncing_ball_tone4",
- "woman_bouncing_ball_medium_dark_skin_tone",
- "woman_bouncing_ball_tone5",
- "woman_bouncing_ball_dark_skin_tone",
- "man_bouncing_ball",
- "man_bouncing_ball_tone1",
- "man_bouncing_ball_light_skin_tone",
- "man_bouncing_ball_tone2",
- "man_bouncing_ball_medium_light_skin_tone",
- "man_bouncing_ball_tone3",
- "man_bouncing_ball_medium_skin_tone",
- "man_bouncing_ball_tone4",
- "man_bouncing_ball_medium_dark_skin_tone",
- "man_bouncing_ball_tone5",
- "man_bouncing_ball_dark_skin_tone",
- "person_fencing",
- "fencer",
- "fencing",
- "person_playing_handball",
- "handball",
- "person_playing_handball_tone1",
- "handball_tone1",
- "person_playing_handball_tone2",
- "handball_tone2",
- "person_playing_handball_tone3",
- "handball_tone3",
- "person_playing_handball_tone4",
- "handball_tone4",
- "person_playing_handball_tone5",
- "handball_tone5",
- "woman_playing_handball",
- "woman_playing_handball_tone1",
- "woman_playing_handball_light_skin_tone",
- "woman_playing_handball_tone2",
- "woman_playing_handball_medium_light_skin_tone",
- "woman_playing_handball_tone3",
- "woman_playing_handball_medium_skin_tone",
- "woman_playing_handball_tone4",
- "woman_playing_handball_medium_dark_skin_tone",
- "woman_playing_handball_tone5",
- "woman_playing_handball_dark_skin_tone",
- "man_playing_handball",
- "man_playing_handball_tone1",
- "man_playing_handball_light_skin_tone",
- "man_playing_handball_tone2",
- "man_playing_handball_medium_light_skin_tone",
- "man_playing_handball_tone3",
- "man_playing_handball_medium_skin_tone",
- "man_playing_handball_tone4",
- "man_playing_handball_medium_dark_skin_tone",
- "man_playing_handball_tone5",
- "man_playing_handball_dark_skin_tone",
- "person_golfing",
- "golfer",
- "person_golfing_tone1",
- "person_golfing_light_skin_tone",
- "person_golfing_tone2",
- "person_golfing_medium_light_skin_tone",
- "person_golfing_tone3",
- "person_golfing_medium_skin_tone",
- "person_golfing_tone4",
- "person_golfing_medium_dark_skin_tone",
- "person_golfing_tone5",
- "person_golfing_dark_skin_tone",
- "woman_golfing",
- "woman_golfing_tone1",
- "woman_golfing_light_skin_tone",
- "woman_golfing_tone2",
- "woman_golfing_medium_light_skin_tone",
- "woman_golfing_tone3",
- "woman_golfing_medium_skin_tone",
- "woman_golfing_tone4",
- "woman_golfing_medium_dark_skin_tone",
- "woman_golfing_tone5",
- "woman_golfing_dark_skin_tone",
- "man_golfing",
- "man_golfing_tone1",
- "man_golfing_light_skin_tone",
- "man_golfing_tone2",
- "man_golfing_medium_light_skin_tone",
- "man_golfing_tone3",
- "man_golfing_medium_skin_tone",
- "man_golfing_tone4",
- "man_golfing_medium_dark_skin_tone",
- "man_golfing_tone5",
- "man_golfing_dark_skin_tone",
- "horse_racing",
- "horse_racing_tone1",
- "horse_racing_tone2",
- "horse_racing_tone3",
- "horse_racing_tone4",
- "horse_racing_tone5",
- "person_in_lotus_position",
- "person_in_lotus_position_tone1",
- "person_in_lotus_position_light_skin_tone",
- "person_in_lotus_position_tone2",
- "person_in_lotus_position_medium_light_skin_tone",
- "person_in_lotus_position_tone3",
- "person_in_lotus_position_medium_skin_tone",
- "person_in_lotus_position_tone4",
- "person_in_lotus_position_medium_dark_skin_tone",
- "person_in_lotus_position_tone5",
- "person_in_lotus_position_dark_skin_tone",
- "woman_in_lotus_position",
- "woman_in_lotus_position_tone1",
- "woman_in_lotus_position_light_skin_tone",
- "woman_in_lotus_position_tone2",
- "woman_in_lotus_position_medium_light_skin_tone",
- "woman_in_lotus_position_tone3",
- "woman_in_lotus_position_medium_skin_tone",
- "woman_in_lotus_position_tone4",
- "woman_in_lotus_position_medium_dark_skin_tone",
- "woman_in_lotus_position_tone5",
- "woman_in_lotus_position_dark_skin_tone",
- "man_in_lotus_position",
- "man_in_lotus_position_tone1",
- "man_in_lotus_position_light_skin_tone",
- "man_in_lotus_position_tone2",
- "man_in_lotus_position_medium_light_skin_tone",
- "man_in_lotus_position_tone3",
- "man_in_lotus_position_medium_skin_tone",
- "man_in_lotus_position_tone4",
- "man_in_lotus_position_medium_dark_skin_tone",
- "man_in_lotus_position_tone5",
- "man_in_lotus_position_dark_skin_tone",
- "person_surfing",
- "surfer",
- "person_surfing_tone1",
- "surfer_tone1",
- "person_surfing_tone2",
- "surfer_tone2",
- "person_surfing_tone3",
- "surfer_tone3",
- "person_surfing_tone4",
- "surfer_tone4",
- "person_surfing_tone5",
- "surfer_tone5",
- "woman_surfing",
- "woman_surfing_tone1",
- "woman_surfing_light_skin_tone",
- "woman_surfing_tone2",
- "woman_surfing_medium_light_skin_tone",
- "woman_surfing_tone3",
- "woman_surfing_medium_skin_tone",
- "woman_surfing_tone4",
- "woman_surfing_medium_dark_skin_tone",
- "woman_surfing_tone5",
- "woman_surfing_dark_skin_tone",
- "man_surfing",
- "man_surfing_tone1",
- "man_surfing_light_skin_tone",
- "man_surfing_tone2",
- "man_surfing_medium_light_skin_tone",
- "man_surfing_tone3",
- "man_surfing_medium_skin_tone",
- "man_surfing_tone4",
- "man_surfing_medium_dark_skin_tone",
- "man_surfing_tone5",
- "man_surfing_dark_skin_tone",
- "person_swimming",
- "swimmer",
- "person_swimming_tone1",
- "swimmer_tone1",
- "person_swimming_tone2",
- "swimmer_tone2",
- "person_swimming_tone3",
- "swimmer_tone3",
- "person_swimming_tone4",
- "swimmer_tone4",
- "person_swimming_tone5",
- "swimmer_tone5",
- "woman_swimming",
- "woman_swimming_tone1",
- "woman_swimming_light_skin_tone",
- "woman_swimming_tone2",
- "woman_swimming_medium_light_skin_tone",
- "woman_swimming_tone3",
- "woman_swimming_medium_skin_tone",
- "woman_swimming_tone4",
- "woman_swimming_medium_dark_skin_tone",
- "woman_swimming_tone5",
- "woman_swimming_dark_skin_tone",
- "man_swimming",
- "man_swimming_tone1",
- "man_swimming_light_skin_tone",
- "man_swimming_tone2",
- "man_swimming_medium_light_skin_tone",
- "man_swimming_tone3",
- "man_swimming_medium_skin_tone",
- "man_swimming_tone4",
- "man_swimming_medium_dark_skin_tone",
- "man_swimming_tone5",
- "man_swimming_dark_skin_tone",
- "person_playing_water_polo",
- "water_polo",
- "person_playing_water_polo_tone1",
- "water_polo_tone1",
- "person_playing_water_polo_tone2",
- "water_polo_tone2",
- "person_playing_water_polo_tone3",
- "water_polo_tone3",
- "person_playing_water_polo_tone4",
- "water_polo_tone4",
- "person_playing_water_polo_tone5",
- "water_polo_tone5",
- "woman_playing_water_polo",
- "woman_playing_water_polo_tone1",
- "woman_playing_water_polo_light_skin_tone",
- "woman_playing_water_polo_tone2",
- "woman_playing_water_polo_medium_light_skin_tone",
- "woman_playing_water_polo_tone3",
- "woman_playing_water_polo_medium_skin_tone",
- "woman_playing_water_polo_tone4",
- "woman_playing_water_polo_medium_dark_skin_tone",
- "woman_playing_water_polo_tone5",
- "woman_playing_water_polo_dark_skin_tone",
- "man_playing_water_polo",
- "man_playing_water_polo_tone1",
- "man_playing_water_polo_light_skin_tone",
- "man_playing_water_polo_tone2",
- "man_playing_water_polo_medium_light_skin_tone",
- "man_playing_water_polo_tone3",
- "man_playing_water_polo_medium_skin_tone",
- "man_playing_water_polo_tone4",
- "man_playing_water_polo_medium_dark_skin_tone",
- "man_playing_water_polo_tone5",
- "man_playing_water_polo_dark_skin_tone",
- "person_rowing_boat",
- "rowboat",
- "person_rowing_boat_tone1",
- "rowboat_tone1",
- "person_rowing_boat_tone2",
- "rowboat_tone2",
- "person_rowing_boat_tone3",
- "rowboat_tone3",
- "person_rowing_boat_tone4",
- "rowboat_tone4",
- "person_rowing_boat_tone5",
- "rowboat_tone5",
- "woman_rowing_boat",
- "woman_rowing_boat_tone1",
- "woman_rowing_boat_light_skin_tone",
- "woman_rowing_boat_tone2",
- "woman_rowing_boat_medium_light_skin_tone",
- "woman_rowing_boat_tone3",
- "woman_rowing_boat_medium_skin_tone",
- "woman_rowing_boat_tone4",
- "woman_rowing_boat_medium_dark_skin_tone",
- "woman_rowing_boat_tone5",
- "woman_rowing_boat_dark_skin_tone",
- "man_rowing_boat",
- "man_rowing_boat_tone1",
- "man_rowing_boat_light_skin_tone",
- "man_rowing_boat_tone2",
- "man_rowing_boat_medium_light_skin_tone",
- "man_rowing_boat_tone3",
- "man_rowing_boat_medium_skin_tone",
- "man_rowing_boat_tone4",
- "man_rowing_boat_medium_dark_skin_tone",
- "man_rowing_boat_tone5",
- "man_rowing_boat_dark_skin_tone",
- "person_climbing",
- "person_climbing_tone1",
- "person_climbing_light_skin_tone",
- "person_climbing_tone2",
- "person_climbing_medium_light_skin_tone",
- "person_climbing_tone3",
- "person_climbing_medium_skin_tone",
- "person_climbing_tone4",
- "person_climbing_medium_dark_skin_tone",
- "person_climbing_tone5",
- "person_climbing_dark_skin_tone",
- "woman_climbing",
- "woman_climbing_tone1",
- "woman_climbing_light_skin_tone",
- "woman_climbing_tone2",
- "woman_climbing_medium_light_skin_tone",
- "woman_climbing_tone3",
- "woman_climbing_medium_skin_tone",
- "woman_climbing_tone4",
- "woman_climbing_medium_dark_skin_tone",
- "woman_climbing_tone5",
- "woman_climbing_dark_skin_tone",
- "man_climbing",
- "man_climbing_tone1",
- "man_climbing_light_skin_tone",
- "man_climbing_tone2",
- "man_climbing_medium_light_skin_tone",
- "man_climbing_tone3",
- "man_climbing_medium_skin_tone",
- "man_climbing_tone4",
- "man_climbing_medium_dark_skin_tone",
- "man_climbing_tone5",
- "man_climbing_dark_skin_tone",
- "person_mountain_biking",
- "mountain_bicyclist",
- "person_mountain_biking_tone1",
- "mountain_bicyclist_tone1",
- "person_mountain_biking_tone2",
- "mountain_bicyclist_tone2",
- "person_mountain_biking_tone3",
- "mountain_bicyclist_tone3",
- "person_mountain_biking_tone4",
- "mountain_bicyclist_tone4",
- "person_mountain_biking_tone5",
- "mountain_bicyclist_tone5",
- "woman_mountain_biking",
- "woman_mountain_biking_tone1",
- "woman_mountain_biking_light_skin_tone",
- "woman_mountain_biking_tone2",
- "woman_mountain_biking_medium_light_skin_tone",
- "woman_mountain_biking_tone3",
- "woman_mountain_biking_medium_skin_tone",
- "woman_mountain_biking_tone4",
- "woman_mountain_biking_medium_dark_skin_tone",
- "woman_mountain_biking_tone5",
- "woman_mountain_biking_dark_skin_tone",
- "man_mountain_biking",
- "man_mountain_biking_tone1",
- "man_mountain_biking_light_skin_tone",
- "man_mountain_biking_tone2",
- "man_mountain_biking_medium_light_skin_tone",
- "man_mountain_biking_tone3",
- "man_mountain_biking_medium_skin_tone",
- "man_mountain_biking_tone4",
- "man_mountain_biking_medium_dark_skin_tone",
- "man_mountain_biking_tone5",
- "man_mountain_biking_dark_skin_tone",
- "person_biking",
- "bicyclist",
- "person_biking_tone1",
- "bicyclist_tone1",
- "person_biking_tone2",
- "bicyclist_tone2",
- "person_biking_tone3",
- "bicyclist_tone3",
- "person_biking_tone4",
- "bicyclist_tone4",
- "person_biking_tone5",
- "bicyclist_tone5",
- "woman_biking",
- "woman_biking_tone1",
- "woman_biking_light_skin_tone",
- "woman_biking_tone2",
- "woman_biking_medium_light_skin_tone",
- "woman_biking_tone3",
- "woman_biking_medium_skin_tone",
- "woman_biking_tone4",
- "woman_biking_medium_dark_skin_tone",
- "woman_biking_tone5",
- "woman_biking_dark_skin_tone",
- "man_biking",
- "man_biking_tone1",
- "man_biking_light_skin_tone",
- "man_biking_tone2",
- "man_biking_medium_light_skin_tone",
- "man_biking_tone3",
- "man_biking_medium_skin_tone",
- "man_biking_tone4",
- "man_biking_medium_dark_skin_tone",
- "man_biking_tone5",
- "man_biking_dark_skin_tone",
- "trophy",
- "first_place",
- "first_place_medal",
- "second_place",
- "second_place_medal",
- "third_place",
- "third_place_medal",
- "medal",
- "sports_medal",
- "military_medal",
- "rosette",
- "reminder_ribbon",
- "ticket",
- "tickets",
- "admission_tickets",
- "circus_tent",
- "person_juggling",
- "juggling",
- "juggler",
- "person_juggling_tone1",
- "juggling_tone1",
- "juggler_tone1",
- "person_juggling_tone2",
- "juggling_tone2",
- "juggler_tone2",
- "person_juggling_tone3",
- "juggling_tone3",
- "juggler_tone3",
- "person_juggling_tone4",
- "juggling_tone4",
- "juggler_tone4",
- "person_juggling_tone5",
- "juggling_tone5",
- "juggler_tone5",
- "woman_juggling",
- "woman_juggling_tone1",
- "woman_juggling_light_skin_tone",
- "woman_juggling_tone2",
- "woman_juggling_medium_light_skin_tone",
- "woman_juggling_tone3",
- "woman_juggling_medium_skin_tone",
- "woman_juggling_tone4",
- "woman_juggling_medium_dark_skin_tone",
- "woman_juggling_tone5",
- "woman_juggling_dark_skin_tone",
- "man_juggling",
- "man_juggling_tone1",
- "man_juggling_light_skin_tone",
- "man_juggling_tone2",
- "man_juggling_medium_light_skin_tone",
- "man_juggling_tone3",
- "man_juggling_medium_skin_tone",
- "man_juggling_tone4",
- "man_juggling_medium_dark_skin_tone",
- "man_juggling_tone5",
- "man_juggling_dark_skin_tone",
- "performing_arts",
- "ballet_shoes",
- "art",
- "clapper",
- "clapper_board",
- "microphone",
- "headphones",
- "headphone",
- "musical_score",
- "musical_keyboard",
- "maracas",
- "drum",
- "drum_with_drumsticks",
- "long_drum",
- "saxophone",
- "trumpet",
- "accordion",
- "guitar",
- "banjo",
- "violin",
- "flute",
- "game_die",
- "chess_pawn",
- "dart",
- "direct_hit",
- "bowling",
- "video_game",
- "slot_machine",
- "jigsaw",
- "puzzle_piece",
- "flag_white",
- "flag_black",
- "pirate_flag",
- "checkered_flag",
- "triangular_flag_on_post",
- "rainbow_flag",
- "gay_pride_flag",
- "transgender_flag",
- "united_nations",
- "flag_af",
- "flag_ax",
- "flag_al",
- "flag_dz",
- "flag_as",
- "flag_ad",
- "flag_ao",
- "flag_ai",
- "flag_aq",
- "flag_ag",
- "flag_ar",
- "flag_am",
- "flag_aw",
- "flag_au",
- "flag_at",
- "flag_az",
- "flag_bs",
- "flag_bh",
- "flag_bd",
- "flag_bb",
- "flag_by",
- "flag_be",
- "flag_bz",
- "flag_bj",
- "flag_bm",
- "flag_bt",
- "flag_bo",
- "flag_ba",
- "flag_bw",
- "flag_br",
- "flag_io",
- "flag_vg",
- "flag_bn",
- "flag_bg",
- "flag_bf",
- "flag_bi",
- "flag_kh",
- "flag_cm",
- "flag_ca",
- "flag_ic",
- "flag_cv",
- "flag_bq",
- "flag_ky",
- "flag_cf",
- "flag_td",
- "flag_cl",
- "flag_cn",
- "flag_cx",
- "flag_cc",
- "flag_co",
- "flag_km",
- "flag_cg",
- "flag_cd",
- "flag_ck",
- "flag_cr",
- "flag_ci",
- "flag_hr",
- "flag_cu",
- "flag_cw",
- "flag_cy",
- "flag_cz",
- "flag_dk",
- "flag_dj",
- "flag_dm",
- "flag_do",
- "flag_ec",
- "flag_eg",
- "flag_sv",
- "flag_gq",
- "flag_er",
- "flag_ee",
- "flag_et",
- "flag_eu",
- "flag_fk",
- "flag_fo",
- "flag_fj",
- "flag_fi",
- "flag_fr",
- "flag_gf",
- "flag_pf",
- "flag_tf",
- "flag_ga",
- "flag_gm",
- "flag_ge",
- "flag_de",
- "flag_gh",
- "flag_gi",
- "flag_gr",
- "flag_gl",
- "flag_gd",
- "flag_gp",
- "flag_gu",
- "flag_gt",
- "flag_gg",
- "flag_gn",
- "flag_gw",
- "flag_gy",
- "flag_ht",
- "flag_hn",
- "flag_hk",
- "flag_hu",
- "flag_is",
- "flag_in",
- "flag_id",
- "flag_ir",
- "flag_iq",
- "flag_ie",
- "flag_im",
- "flag_il",
- "flag_it",
- "flag_jm",
- "flag_jp",
- "crossed_flags",
- "flag_je",
- "flag_jo",
- "flag_kz",
- "flag_ke",
- "flag_ki",
- "flag_xk",
- "flag_kw",
- "flag_kg",
- "flag_la",
- "flag_lv",
- "flag_lb",
- "flag_ls",
- "flag_lr",
- "flag_ly",
- "flag_li",
- "flag_lt",
- "flag_lu",
- "flag_mo",
- "flag_mk",
- "flag_mg",
- "flag_mw",
- "flag_my",
- "flag_mv",
- "flag_ml",
- "flag_mt",
- "flag_mh",
- "flag_mq",
- "flag_mr",
- "flag_mu",
- "flag_yt",
- "flag_mx",
- "flag_fm",
- "flag_md",
- "flag_mc",
- "flag_mn",
- "flag_me",
- "flag_ms",
- "flag_ma",
- "flag_mz",
- "flag_mm",
- "flag_na",
- "flag_nr",
- "flag_np",
- "flag_nl",
- "flag_nc",
- "flag_nz",
- "flag_ni",
- "flag_ne",
- "flag_ng",
- "flag_nu",
- "flag_nf",
- "flag_kp",
- "flag_mp",
- "flag_no",
- "flag_om",
- "flag_pk",
- "flag_pw",
- "flag_ps",
- "flag_pa",
- "flag_pg",
- "flag_py",
- "flag_pe",
- "flag_ph",
- "flag_pn",
- "flag_pl",
- "flag_pt",
- "flag_pr",
- "flag_qa",
- "flag_re",
- "flag_ro",
- "flag_ru",
- "flag_rw",
- "flag_ws",
- "flag_sm",
- "flag_st",
- "flag_sa",
- "flag_sn",
- "flag_rs",
- "flag_sc",
- "flag_sl",
- "flag_sg",
- "flag_sx",
- "flag_sk",
- "flag_si",
- "flag_gs",
- "flag_sb",
- "flag_so",
- "flag_za",
- "flag_kr",
- "flag_ss",
- "flag_es",
- "flag_lk",
- "flag_bl",
- "flag_sh",
- "flag_kn",
- "flag_lc",
- "flag_pm",
- "flag_vc",
- "flag_sd",
- "flag_sr",
- "flag_sz",
- "flag_se",
- "flag_ch",
- "flag_sy",
- "flag_tw",
- "flag_tj",
- "flag_tz",
- "flag_th",
- "flag_tl",
- "flag_tg",
- "flag_tk",
- "flag_to",
- "flag_tt",
- "flag_tn",
- "flag_tr",
- "flag_tm",
- "flag_tc",
- "flag_vi",
- "flag_tv",
- "flag_ug",
- "flag_ua",
- "flag_ae",
- "flag_gb",
- "england",
- "scotland",
- "wales",
- "flag_us",
- "flag_uy",
- "flag_uz",
- "flag_vu",
- "flag_va",
- "flag_ve",
- "flag_vn",
- "flag_wf",
- "flag_eh",
- "flag_ye",
- "flag_zm",
- "flag_zw",
- "flag_ac",
- "flag_bv",
- "flag_cp",
- "flag_ea",
- "flag_dg",
- "flag_hm",
- "flag_mf",
- "flag_sj",
- "flag_ta",
- "flag_um",
- "green_apple",
- "apple",
- "red_apple",
- "pear",
- "tangerine",
- "lemon",
- "banana",
- "watermelon",
- "grapes",
- "strawberry",
- "blueberries",
- "melon",
- "cherries",
- "peach",
- "mango",
- "pineapple",
- "coconut",
- "kiwi",
- "kiwifruit",
- "kiwi_fruit",
- "tomato",
- "eggplant",
- "avocado",
- "pea_pod",
- "broccoli",
- "leafy_green",
- "cucumber",
- "hot_pepper",
- "bell_pepper",
- "corn",
- "ear_of_corn",
- "carrot",
- "olive",
- "garlic",
- "onion",
- "potato",
- "sweet_potato",
- "ginger_root",
- "croissant",
- "bagel",
- "bread",
- "french_bread",
- "baguette_bread",
- "pretzel",
- "cheese",
- "cheese_wedge",
- "egg",
- "cooking",
- "butter",
- "pancakes",
- "waffle",
- "bacon",
- "cut_of_meat",
- "poultry_leg",
- "meat_on_bone",
- "bone",
- "hotdog",
- "hot_dog",
- "hamburger",
- "fries",
- "french_fries",
- "pizza",
- "flatbread",
- "sandwich",
- "stuffed_flatbread",
- "stuffed_pita",
- "falafel",
- "taco",
- "burrito",
- "tamale",
- "salad",
- "green_salad",
- "shallow_pan_of_food",
- "paella",
- "fondue",
- "canned_food",
- "jar",
- "spaghetti",
- "ramen",
- "steaming_bowl",
- "stew",
- "pot_of_food",
- "curry",
- "curry_rice",
- "sushi",
- "bento",
- "bento_box",
- "dumpling",
- "oyster",
- "fried_shrimp",
- "rice_ball",
- "rice",
- "cooked_rice",
- "rice_cracker",
- "fish_cake",
- "fortune_cookie",
- "moon_cake",
- "oden",
- "dango",
- "shaved_ice",
- "ice_cream",
- "icecream",
- "pie",
- "cupcake",
- "cake",
- "shortcake",
- "birthday",
- "birthday_cake",
- "custard",
- "pudding",
- "flan",
- "lollipop",
- "candy",
- "chocolate_bar",
- "popcorn",
- "doughnut",
- "cookie",
- "chestnut",
- "peanuts",
- "shelled_peanut",
- "beans",
- "honey_pot",
- "milk",
- "glass_of_milk",
- "pouring_liquid",
- "baby_bottle",
- "teapot",
- "coffee",
- "hot_beverage",
- "tea",
- "mate",
- "beverage_box",
- "cup_with_straw",
- "bubble_tea",
- "sake",
- "beer",
- "beer_mug",
- "beers",
- "champagne_glass",
- "clinking_glass",
- "wine_glass",
- "tumbler_glass",
- "whisky",
- "cocktail",
- "tropical_drink",
- "champagne",
- "bottle_with_popping_cork",
- "ice_cube",
- "spoon",
- "fork_and_knife",
- "fork_knife_plate",
- "fork_and_knife_with_plate",
- "bowl_with_spoon",
- "takeout_box",
- "chopsticks",
- "salt",
- "dog",
- "dog_face",
- "cat",
- "cat_face",
- "mouse",
- "mouse_face",
- "hamster",
- "rabbit",
- "rabbit_face",
- "fox",
- "fox_face",
- "bear",
- "panda_face",
- "panda",
- "polar_bear",
- "koala",
- "tiger",
- "tiger_face",
- "lion_face",
- "lion",
- "cow",
- "cow_face",
- "pig",
- "pig_face",
- "pig_nose",
- "frog",
- "monkey_face",
- "see_no_evil",
- "hear_no_evil",
- "speak_no_evil",
- "monkey",
- "chicken",
- "penguin",
- "bird",
- "baby_chick",
- "hatching_chick",
- "hatched_chick",
- "goose",
- "duck",
- "black_bird",
- "eagle",
- "owl",
- "bat",
- "wolf",
- "boar",
- "horse",
- "horse_face",
- "unicorn",
- "unicorn_face",
- "moose",
- "bee",
- "honeybee",
- "worm",
- "bug",
- "butterfly",
- "snail",
- "lady_beetle",
- "ant",
- "fly",
- "beetle",
- "cockroach",
- "mosquito",
- "cricket",
- "spider",
- "spider_web",
- "scorpion",
- "turtle",
- "snake",
- "lizard",
- "t_rex",
- "sauropod",
- "octopus",
- "squid",
- "jellyfish",
- "shrimp",
- "lobster",
- "crab",
- "blowfish",
- "tropical_fish",
- "fish",
- "dolphin",
- "whale",
- "whale2",
- "shark",
- "seal",
- "crocodile",
- "tiger2",
- "leopard",
- "zebra",
- "gorilla",
- "orangutan",
- "mammoth",
- "elephant",
- "hippopotamus",
- "rhino",
- "rhinoceros",
- "dromedary_camel",
- "camel",
- "giraffe",
- "kangaroo",
- "bison",
- "water_buffalo",
- "ox",
- "cow2",
- "donkey",
- "racehorse",
- "pig2",
- "ram",
- "sheep",
- "ewe",
- "llama",
- "goat",
- "deer",
- "dog2",
- "poodle",
- "guide_dog",
- "service_dog",
- "cat2",
- "black_cat",
- "feather",
- "wing",
- "rooster",
- "turkey",
- "dodo",
- "peacock",
- "parrot",
- "swan",
- "flamingo",
- "dove",
- "dove_of_peace",
- "rabbit2",
- "raccoon",
- "skunk",
- "badger",
- "beaver",
- "otter",
- "sloth",
- "mouse2",
- "rat",
- "chipmunk",
- "hedgehog",
- "feet",
- "paw_prints",
- "dragon",
- "dragon_face",
- "cactus",
- "christmas_tree",
- "evergreen_tree",
- "deciduous_tree",
- "palm_tree",
- "wood",
- "seedling",
- "herb",
- "shamrock",
- "four_leaf_clover",
- "bamboo",
- "potted_plant",
- "tanabata_tree",
- "leaves",
- "fallen_leaf",
- "maple_leaf",
- "nest_with_eggs",
- "empty_nest",
- "mushroom",
- "shell",
- "spiral_shell",
- "coral",
- "rock",
- "ear_of_rice",
- "sheaf_of_rice",
- "bouquet",
- "tulip",
- "rose",
- "wilted_rose",
- "wilted_flower",
- "hyacinth",
- "lotus",
- "hibiscus",
- "cherry_blossom",
- "blossom",
- "sunflower",
- "sun_with_face",
- "full_moon_with_face",
- "first_quarter_moon_with_face",
- "last_quarter_moon_with_face",
- "new_moon_with_face",
- "new_moon_face",
- "full_moon",
- "waning_gibbous_moon",
- "last_quarter_moon",
- "waning_crescent_moon",
- "new_moon",
- "waxing_crescent_moon",
- "first_quarter_moon",
- "waxing_gibbous_moon",
- "crescent_moon",
- "earth_americas",
- "earth_africa",
- "earth_asia",
- "ringed_planet",
- "dizzy",
- "star",
- "star2",
- "glowing_star",
- "sparkles",
- "zap",
- "high_voltage",
- "comet",
- "boom",
- "collision",
- "fire",
- "flame",
- "cloud_tornado",
- "cloud_with_tornado",
- "tornado",
- "rainbow",
- "sunny",
- "sun",
- "white_sun_small_cloud",
- "white_sun_with_small_cloud",
- "partly_sunny",
- "white_sun_cloud",
- "white_sun_behind_cloud",
- "cloud",
- "white_sun_rain_cloud",
- "white_sun_behind_cloud_with_rain",
- "cloud_rain",
- "cloud_with_rain",
- "thunder_cloud_rain",
- "thunder_cloud_and_rain",
- "cloud_lightning",
- "cloud_with_lightning",
- "cloud_snow",
- "cloud_with_snow",
- "snowflake",
- "snowman2",
- "snowman",
- "wind_blowing_face",
- "wind_face",
- "dash",
- "dashing_away",
- "droplet",
- "sweat_drops",
- "bubbles",
- "umbrella",
- "umbrella2",
- "ocean",
- "water_wave",
- "fog",
- "watch",
- "mobile_phone",
- "iphone",
- "calling",
- "computer",
- "keyboard",
- "desktop",
- "desktop_computer",
- "printer",
- "mouse_three_button",
- "three_button_mouse",
- "trackball",
- "joystick",
- "compression",
- "clamp",
- "minidisc",
- "computer_disk",
- "floppy_disk",
- "cd",
- "optical_disk",
- "dvd",
- "vhs",
- "videocassette",
- "camera",
- "camera_with_flash",
- "video_camera",
- "movie_camera",
- "projector",
- "film_projector",
- "film_frames",
- "telephone_receiver",
- "telephone",
- "pager",
- "fax",
- "fax_machine",
- "tv",
- "television",
- "radio",
- "microphone2",
- "studio_microphone",
- "level_slider",
- "control_knobs",
- "compass",
- "stopwatch",
- "timer",
- "timer_clock",
- "alarm_clock",
- "clock",
- "mantlepiece_clock",
- "hourglass",
- "hourglass_flowing_sand",
- "satellite",
- "battery",
- "low_battery",
- "electric_plug",
- "bulb",
- "light_bulb",
- "flashlight",
- "candle",
- "diya_lamp",
- "fire_extinguisher",
- "oil",
- "oil_drum",
- "money_with_wings",
- "dollar",
- "yen",
- "yen_banknote",
- "euro",
- "euro_banknote",
- "pound",
- "coin",
- "moneybag",
- "money_bag",
- "credit_card",
- "identification_card",
- "gem",
- "gem_stone",
- "scales",
- "balance_scale",
- "ladder",
- "toolbox",
- "screwdriver",
- "wrench",
- "hammer",
- "hammer_pick",
- "hammer_and_pick",
- "tools",
- "hammer_and_wrench",
- "pick",
- "carpentry_saw",
- "nut_and_bolt",
- "gear",
- "mouse_trap",
- "bricks",
- "brick",
- "chains",
- "magnet",
- "gun",
- "pistol",
- "bomb",
- "firecracker",
- "axe",
- "knife",
- "kitchen_knife",
- "dagger",
- "dagger_knife",
- "crossed_swords",
- "shield",
- "smoking",
- "cigarette",
- "coffin",
- "headstone",
- "urn",
- "funeral_urn",
- "amphora",
- "crystal_ball",
- "prayer_beads",
- "nazar_amulet",
- "hamsa",
- "barber",
- "barber_pole",
- "alembic",
- "telescope",
- "microscope",
- "hole",
- "x_ray",
- "adhesive_bandage",
- "stethoscope",
- "pill",
- "syringe",
- "drop_of_blood",
- "dna",
- "microbe",
- "petri_dish",
- "test_tube",
- "thermometer",
- "broom",
- "plunger",
- "basket",
- "roll_of_paper",
- "toilet",
- "potable_water",
- "shower",
- "bathtub",
- "bath",
- "bath_tone1",
- "bath_tone2",
- "bath_tone3",
- "bath_tone4",
- "bath_tone5",
- "soap",
- "toothbrush",
- "razor",
- "hair_pick",
- "sponge",
- "bucket",
- "squeeze_bottle",
- "lotion_bottle",
- "bellhop",
- "bellhop_bell",
- "key",
- "key2",
- "old_key",
- "door",
- "chair",
- "couch",
- "couch_and_lamp",
- "bed",
- "sleeping_accommodation",
- "person_in_bed",
- "person_in_bed_tone1",
- "person_in_bed_light_skin_tone",
- "person_in_bed_tone2",
- "person_in_bed_medium_light_skin_tone",
- "person_in_bed_tone3",
- "person_in_bed_medium_skin_tone",
- "person_in_bed_tone4",
- "person_in_bed_medium_dark_skin_tone",
- "person_in_bed_tone5",
- "person_in_bed_dark_skin_tone",
- "teddy_bear",
- "nesting_dolls",
- "frame_photo",
- "frame_with_picture",
- "mirror",
- "window",
- "shopping_bags",
- "shopping_cart",
- "shopping_trolley",
- "gift",
- "wrapped_gift",
- "balloon",
- "flags",
- "carp_streamer",
- "ribbon",
- "magic_wand",
- "piñata",
- "confetti_ball",
- "tada",
- "party_popper",
- "dolls",
- "folding_hand_fan",
- "izakaya_lantern",
- "wind_chime",
- "mirror_ball",
- "red_envelope",
- "envelope",
- "envelope_with_arrow",
- "incoming_envelope",
- "e_mail",
- "email",
- "love_letter",
- "inbox_tray",
- "outbox_tray",
- "package",
- "label",
- "placard",
- "mailbox_closed",
- "mailbox",
- "mailbox_with_mail",
- "mailbox_with_no_mail",
- "postbox",
- "postal_horn",
- "scroll",
- "page_with_curl",
- "page_facing_up",
- "bookmark_tabs",
- "receipt",
- "bar_chart",
- "chart_with_upwards_trend",
- "chart_with_downwards_trend",
- "notepad_spiral",
- "spiral_note_pad",
- "calendar_spiral",
- "spiral_calendar_pad",
- "calendar",
- "date",
- "wastebasket",
- "card_index",
- "card_box",
- "card_file_box",
- "ballot_box",
- "ballot_box_with_ballot",
- "file_cabinet",
- "clipboard",
- "file_folder",
- "open_file_folder",
- "dividers",
- "card_index_dividers",
- "newspaper2",
- "rolled_up_newspaper",
- "newspaper",
- "notebook",
- "notebook_with_decorative_cover",
- "ledger",
- "closed_book",
- "green_book",
- "blue_book",
- "orange_book",
- "books",
- "book",
- "open_book",
- "bookmark",
- "safety_pin",
- "link",
- "paperclip",
- "paperclips",
- "linked_paperclips",
- "triangular_ruler",
- "straight_ruler",
- "abacus",
- "pushpin",
- "round_pushpin",
- "scissors",
- "pen_ballpoint",
- "lower_left_ballpoint_pen",
- "pen",
- "pen_fountain",
- "lower_left_fountain_pen",
- "fountain_pen",
- "black_nib",
- "paintbrush",
- "lower_left_paintbrush",
- "crayon",
- "lower_left_crayon",
- "pencil",
- "memo",
- "pencil2",
- "mag",
- "mag_right",
- "lock_with_ink_pen",
- "closed_lock_with_key",
- "lock",
- "locked",
- "unlock",
- "unlocked",
- "grinning",
- "grinning_face",
- "smiley",
- "smile",
- "grin",
- "laughing",
- "satisfied",
- "face_holding_back_tears",
- "sweat_smile",
- "joy",
- "rofl",
- "rolling_on_the_floor_laughing",
- "smiling_face_with_tear",
- "relaxed",
- "smiling_face",
- "blush",
- "innocent",
- "slight_smile",
- "slightly_smiling_face",
- "upside_down",
- "upside_down_face",
- "wink",
- "winking_face",
- "relieved",
- "relieved_face",
- "heart_eyes",
- "smiling_face_with_3_hearts",
- "kissing_heart",
- "kissing",
- "kissing_face",
- "kissing_smiling_eyes",
- "kissing_closed_eyes",
- "yum",
- "stuck_out_tongue",
- "stuck_out_tongue_closed_eyes",
- "stuck_out_tongue_winking_eye",
- "zany_face",
- "face_with_raised_eyebrow",
- "face_with_monocle",
- "nerd",
- "nerd_face",
- "sunglasses",
- "disguised_face",
- "star_struck",
- "partying_face",
- "smirk",
- "smirking_face",
- "unamused",
- "unamused_face",
- "disappointed",
- "pensive",
- "pensive_face",
- "worried",
- "worried_face",
- "confused",
- "confused_face",
- "slight_frown",
- "slightly_frowning_face",
- "frowning2",
- "white_frowning_face",
- "frowning_face",
- "persevere",
- "confounded",
- "tired_face",
- "weary",
- "weary_face",
- "pleading_face",
- "cry",
- "crying_face",
- "sob",
- "triumph",
- "angry",
- "angry_face",
- "rage",
- "pouting_face",
- "face_with_symbols_over_mouth",
- "exploding_head",
- "flushed",
- "flushed_face",
- "hot_face",
- "cold_face",
- "face_in_clouds",
- "scream",
- "fearful",
- "fearful_face",
- "cold_sweat",
- "disappointed_relieved",
- "sweat",
- "hugging",
- "hugging_face",
- "thinking",
- "thinking_face",
- "face_with_peeking_eye",
- "face_with_hand_over_mouth",
- "face_with_open_eyes_and_hand_over_mouth",
- "saluting_face",
- "shushing_face",
- "melting_face",
- "lying_face",
- "liar",
- "no_mouth",
- "dotted_line_face",
- "neutral_face",
- "face_with_diagonal_mouth",
- "expressionless",
- "shaking_face",
- "grimacing",
- "rolling_eyes",
- "face_with_rolling_eyes",
- "hushed",
- "hushed_face",
- "frowning",
- "anguished",
- "open_mouth",
- "astonished",
- "yawning_face",
- "sleeping",
- "sleeping_face",
- "drooling_face",
- "drool",
- "sleepy",
- "sleepy_face",
- "face_exhaling",
- "dizzy_face",
- "face_with_spiral_eyes",
- "zipper_mouth",
- "zipper_mouth_face",
- "woozy_face",
- "nauseated_face",
- "sick",
- "face_vomiting",
- "sneezing_face",
- "sneeze",
- "mask",
- "thermometer_face",
- "face_with_thermometer",
- "head_bandage",
- "face_with_head_bandage",
- "money_mouth",
- "money_mouth_face",
- "cowboy",
- "face_with_cowboy_hat",
- "smiling_imp",
- "imp",
- "japanese_ogre",
- "ogre",
- "japanese_goblin",
- "goblin",
- "clown",
- "clown_face",
- "poop",
- "shit",
- "hankey",
- "poo",
- "pile_of_poo",
- "ghost",
- "skull",
- "skeleton",
- "skull_crossbones",
- "skull_and_crossbones",
- "alien",
- "space_invader",
- "alien_monster",
- "robot",
- "robot_face",
- "jack_o_lantern",
- "smiley_cat",
- "grinning_cat",
- "smile_cat",
- "joy_cat",
- "heart_eyes_cat",
- "smirk_cat",
- "kissing_cat",
- "scream_cat",
- "weary_cat",
- "crying_cat_face",
- "crying_cat",
- "pouting_cat",
- "heart_hands",
- "heart_hands_tone1",
- "heart_hands_light_skin_tone",
- "heart_hands_tone2",
- "heart_hands_medium_light_skin_tone",
- "heart_hands_tone3",
- "heart_hands_medium_skin_tone",
- "heart_hands_tone4",
- "heart_hands_medium_dark_skin_tone",
- "heart_hands_tone5",
- "heart_hands_dark_skin_tone",
- "palms_up_together",
- "palms_up_together_tone1",
- "palms_up_together_light_skin_tone",
- "palms_up_together_tone2",
- "palms_up_together_medium_light_skin_tone",
- "palms_up_together_tone3",
- "palms_up_together_medium_skin_tone",
- "palms_up_together_tone4",
- "palms_up_together_medium_dark_skin_tone",
- "palms_up_together_tone5",
- "palms_up_together_dark_skin_tone",
- "open_hands",
- "open_hands_tone1",
- "open_hands_tone2",
- "open_hands_tone3",
- "open_hands_tone4",
- "open_hands_tone5",
- "raised_hands",
- "raising_hands",
- "raised_hands_tone1",
- "raised_hands_tone2",
- "raised_hands_tone3",
- "raised_hands_tone4",
- "raised_hands_tone5",
- "clap",
- "clap_tone1",
- "clap_tone2",
- "clap_tone3",
- "clap_tone4",
- "clap_tone5",
- "handshake",
- "shaking_hands",
- "handshake_tone1",
- "handshake_light_skin_tone",
- "handshake_tone1_tone2",
- "handshake_light_skin_tone_medium_light_skin_tone",
- "handshake_tone1_tone3",
- "handshake_light_skin_tone_medium_skin_tone",
- "handshake_tone1_tone4",
- "handshake_light_skin_tone_medium_dark_skin_tone",
- "handshake_tone1_tone5",
- "handshake_light_skin_tone_dark_skin_tone",
- "handshake_tone2_tone1",
- "handshake_medium_light_skin_tone_light_skin_tone",
- "handshake_tone2",
- "handshake_medium_light_skin_tone",
- "handshake_tone2_tone3",
- "handshake_medium_light_skin_tone_medium_skin_tone",
- "handshake_tone2_tone4",
- "handshake_medium_light_skin_tone_medium_dark_skin_tone",
- "handshake_tone2_tone5",
- "handshake_medium_light_skin_tone_dark_skin_tone",
- "handshake_tone3_tone1",
- "handshake_medium_skin_tone_light_skin_tone",
- "handshake_tone3_tone2",
- "handshake_medium_skin_tone_medium_light_skin_tone",
- "handshake_tone3",
- "handshake_medium_skin_tone",
- "handshake_tone3_tone4",
- "handshake_medium_skin_tone_medium_dark_skin_tone",
- "handshake_tone3_tone5",
- "handshake_medium_skin_tone_dark_skin_tone",
- "handshake_tone4_tone1",
- "handshake_medium_dark_skin_tone_light_skin_tone",
- "handshake_tone4_tone2",
- "handshake_medium_dark_skin_tone_medium_light_skin_tone",
- "handshake_tone4_tone3",
- "handshake_medium_dark_skin_tone_medium_skin_tone",
- "handshake_tone4",
- "handshake_medium_dark_skin_tone",
- "handshake_tone4_tone5",
- "handshake_medium_dark_skin_tone_dark_skin_tone",
- "handshake_tone5_tone1",
- "handshake_dark_skin_tone_light_skin_tone",
- "handshake_tone5_tone2",
- "handshake_dark_skin_tone_medium_light_skin_tone",
- "handshake_tone5_tone3",
- "handshake_dark_skin_tone_medium_skin_tone",
- "handshake_tone5_tone4",
- "handshake_dark_skin_tone_medium_dark_skin_tone",
- "handshake_tone5",
- "handshake_dark_skin_tone",
- "thumbsup",
- "+1",
- "thumbup",
- "thumbs_up",
- "thumbsup_tone1",
- "+1_tone1",
- "thumbup_tone1",
- "thumbsup_tone2",
- "+1_tone2",
- "thumbup_tone2",
- "thumbsup_tone3",
- "+1_tone3",
- "thumbup_tone3",
- "thumbsup_tone4",
- "+1_tone4",
- "thumbup_tone4",
- "thumbsup_tone5",
- "+1_tone5",
- "thumbup_tone5",
- "thumbsdown",
- "-1",
- "thumbdown",
- "thumbs_down",
- "thumbsdown_tone1",
- "_1_tone1",
- "thumbdown_tone1",
- "thumbsdown_tone2",
- "_1_tone2",
- "thumbdown_tone2",
- "thumbsdown_tone3",
- "_1_tone3",
- "thumbdown_tone3",
- "thumbsdown_tone4",
- "_1_tone4",
- "thumbdown_tone4",
- "thumbsdown_tone5",
- "_1_tone5",
- "thumbdown_tone5",
- "punch",
- "oncoming_fist",
- "punch_tone1",
- "punch_tone2",
- "punch_tone3",
- "punch_tone4",
- "punch_tone5",
- "fist",
- "raised_fist",
- "fist_tone1",
- "fist_tone2",
- "fist_tone3",
- "fist_tone4",
- "fist_tone5",
- "left_facing_fist",
- "left_fist",
- "left_facing_fist_tone1",
- "left_fist_tone1",
- "left_facing_fist_tone2",
- "left_fist_tone2",
- "left_facing_fist_tone3",
- "left_fist_tone3",
- "left_facing_fist_tone4",
- "left_fist_tone4",
- "left_facing_fist_tone5",
- "left_fist_tone5",
- "right_facing_fist",
- "right_fist",
- "right_facing_fist_tone1",
- "right_fist_tone1",
- "right_facing_fist_tone2",
- "right_fist_tone2",
- "right_facing_fist_tone3",
- "right_fist_tone3",
- "right_facing_fist_tone4",
- "right_fist_tone4",
- "right_facing_fist_tone5",
- "right_fist_tone5",
- "leftwards_pushing_hand",
- "leftwards_pushing_hand_tone1",
- "leftwards_pushing_hand_light_skin_tone",
- "leftwards_pushing_hand_tone2",
- "leftwards_pushing_hand_medium_light_skin_tone",
- "leftwards_pushing_hand_tone3",
- "leftwards_pushing_hand_medium_skin_tone",
- "leftwards_pushing_hand_tone4",
- "leftwards_pushing_hand_medium_dark_skin_tone",
- "leftwards_pushing_hand_tone5",
- "leftwards_pushing_hand_dark_skin_tone",
- "rightwards_pushing_hand",
- "rightwards_pushing_hand_tone1",
- "rightwards_pushing_hand_light_skin_tone",
- "rightwards_pushing_hand_tone2",
- "rightwards_pushing_hand_medium_light_skin_tone",
- "rightwards_pushing_hand_tone3",
- "rightwards_pushing_hand_medium_skin_tone",
- "rightwards_pushing_hand_tone4",
- "rightwards_pushing_hand_medium_dark_skin_tone",
- "rightwards_pushing_hand_tone5",
- "rightwards_pushing_hand_dark_skin_tone",
- "fingers_crossed",
- "hand_with_index_and_middle_finger_crossed",
- "fingers_crossed_tone1",
- "hand_with_index_and_middle_fingers_crossed_tone1",
- "fingers_crossed_tone2",
- "hand_with_index_and_middle_fingers_crossed_tone2",
- "fingers_crossed_tone3",
- "hand_with_index_and_middle_fingers_crossed_tone3",
- "fingers_crossed_tone4",
- "hand_with_index_and_middle_fingers_crossed_tone4",
- "fingers_crossed_tone5",
- "hand_with_index_and_middle_fingers_crossed_tone5",
- "v",
- "victory_hand",
- "v_tone1",
- "v_tone2",
- "v_tone3",
- "v_tone4",
- "v_tone5",
- "hand_with_index_finger_and_thumb_crossed",
- "hand_with_index_finger_and_thumb_crossed_tone1",
- "hand_with_index_finger_and_thumb_crossed_light_skin_tone",
- "hand_with_index_finger_and_thumb_crossed_tone2",
- "hand_with_index_finger_and_thumb_crossed_medium_light_skin_tone",
- "hand_with_index_finger_and_thumb_crossed_tone3",
- "hand_with_index_finger_and_thumb_crossed_medium_skin_tone",
- "hand_with_index_finger_and_thumb_crossed_tone4",
- "hand_with_index_finger_and_thumb_crossed_medium_dark_skin_tone",
- "hand_with_index_finger_and_thumb_crossed_tone5",
- "hand_with_index_finger_and_thumb_crossed_dark_skin_tone",
- "love_you_gesture",
- "love_you_gesture_tone1",
- "love_you_gesture_light_skin_tone",
- "love_you_gesture_tone2",
- "love_you_gesture_medium_light_skin_tone",
- "love_you_gesture_tone3",
- "love_you_gesture_medium_skin_tone",
- "love_you_gesture_tone4",
- "love_you_gesture_medium_dark_skin_tone",
- "love_you_gesture_tone5",
- "love_you_gesture_dark_skin_tone",
- "metal",
- "sign_of_the_horns",
- "metal_tone1",
- "sign_of_the_horns_tone1",
- "metal_tone2",
- "sign_of_the_horns_tone2",
- "metal_tone3",
- "sign_of_the_horns_tone3",
- "metal_tone4",
- "sign_of_the_horns_tone4",
- "metal_tone5",
- "sign_of_the_horns_tone5",
- "ok_hand",
- "ok_hand_tone1",
- "ok_hand_tone2",
- "ok_hand_tone3",
- "ok_hand_tone4",
- "ok_hand_tone5",
- "pinched_fingers",
- "pinched_fingers_tone2",
- "pinched_fingers_medium_light_skin_tone",
- "pinched_fingers_tone1",
- "pinched_fingers_light_skin_tone",
- "pinched_fingers_tone3",
- "pinched_fingers_medium_skin_tone",
- "pinched_fingers_tone4",
- "pinched_fingers_medium_dark_skin_tone",
- "pinched_fingers_tone5",
- "pinched_fingers_dark_skin_tone",
- "pinching_hand",
- "pinching_hand_tone1",
- "pinching_hand_light_skin_tone",
- "pinching_hand_tone2",
- "pinching_hand_medium_light_skin_tone",
- "pinching_hand_tone3",
- "pinching_hand_medium_skin_tone",
- "pinching_hand_tone4",
- "pinching_hand_medium_dark_skin_tone",
- "pinching_hand_tone5",
- "pinching_hand_dark_skin_tone",
- "palm_down_hand",
- "palm_down_hand_tone1",
- "palm_down_hand_light_skin_tone",
- "palm_down_hand_tone2",
- "palm_down_hand_medium_light_skin_tone",
- "palm_down_hand_tone3",
- "palm_down_hand_medium_skin_tone",
- "palm_down_hand_tone4",
- "palm_down_hand_medium_dark_skin_tone",
- "palm_down_hand_tone5",
- "palm_down_hand_dark_skin_tone",
- "palm_up_hand",
- "palm_up_hand_tone1",
- "palm_up_hand_light_skin_tone",
- "palm_up_hand_tone2",
- "palm_up_hand_medium_light_skin_tone",
- "palm_up_hand_tone3",
- "palm_up_hand_medium_skin_tone",
- "palm_up_hand_tone4",
- "palm_up_hand_medium_dark_skin_tone",
- "palm_up_hand_tone5",
- "palm_up_hand_dark_skin_tone",
- "point_left",
- "point_left_tone1",
- "point_left_tone2",
- "point_left_tone3",
- "point_left_tone4",
- "point_left_tone5",
- "point_right",
- "point_right_tone1",
- "point_right_tone2",
- "point_right_tone3",
- "point_right_tone4",
- "point_right_tone5",
- "point_up_2",
- "point_up_2_tone1",
- "point_up_2_tone2",
- "point_up_2_tone3",
- "point_up_2_tone4",
- "point_up_2_tone5",
- "point_down",
- "point_down_tone1",
- "point_down_tone2",
- "point_down_tone3",
- "point_down_tone4",
- "point_down_tone5",
- "point_up",
- "point_up_tone1",
- "point_up_tone2",
- "point_up_tone3",
- "point_up_tone4",
- "point_up_tone5",
- "raised_hand",
- "raised_hand_tone1",
- "raised_hand_tone2",
- "raised_hand_tone3",
- "raised_hand_tone4",
- "raised_hand_tone5",
- "raised_back_of_hand",
- "back_of_hand",
- "raised_back_of_hand_tone1",
- "back_of_hand_tone1",
- "raised_back_of_hand_tone2",
- "back_of_hand_tone2",
- "raised_back_of_hand_tone3",
- "back_of_hand_tone3",
- "raised_back_of_hand_tone4",
- "back_of_hand_tone4",
- "raised_back_of_hand_tone5",
- "back_of_hand_tone5",
- "hand_splayed",
- "raised_hand_with_fingers_splayed",
- "hand_splayed_tone1",
- "raised_hand_with_fingers_splayed_tone1",
- "hand_splayed_tone2",
- "raised_hand_with_fingers_splayed_tone2",
- "hand_splayed_tone3",
- "raised_hand_with_fingers_splayed_tone3",
- "hand_splayed_tone4",
- "raised_hand_with_fingers_splayed_tone4",
- "hand_splayed_tone5",
- "raised_hand_with_fingers_splayed_tone5",
- "vulcan",
- "raised_hand_with_part_between_middle_and_ring_fingers",
- "vulcan_salute",
- "vulcan_tone1",
- "raised_hand_with_part_between_middle_and_ring_fingers_tone1",
- "vulcan_tone2",
- "raised_hand_with_part_between_middle_and_ring_fingers_tone2",
- "vulcan_tone3",
- "raised_hand_with_part_between_middle_and_ring_fingers_tone3",
- "vulcan_tone4",
- "raised_hand_with_part_between_middle_and_ring_fingers_tone4",
- "vulcan_tone5",
- "raised_hand_with_part_between_middle_and_ring_fingers_tone5",
- "wave",
- "waving_hand",
- "wave_tone1",
- "wave_tone2",
- "wave_tone3",
- "wave_tone4",
- "wave_tone5",
- "call_me",
- "call_me_hand",
- "call_me_tone1",
- "call_me_hand_tone1",
- "call_me_tone2",
- "call_me_hand_tone2",
- "call_me_tone3",
- "call_me_hand_tone3",
- "call_me_tone4",
- "call_me_hand_tone4",
- "call_me_tone5",
- "call_me_hand_tone5",
- "leftwards_hand",
- "leftwards_hand_tone1",
- "leftwards_hand_light_skin_tone",
- "leftwards_hand_tone2",
- "leftwards_hand_medium_light_skin_tone",
- "leftwards_hand_tone3",
- "leftwards_hand_medium_skin_tone",
- "leftwards_hand_tone4",
- "leftwards_hand_medium_dark_skin_tone",
- "leftwards_hand_tone5",
- "leftwards_hand_dark_skin_tone",
- "rightwards_hand",
- "rightwards_hand_tone1",
- "rightwards_hand_light_skin_tone",
- "rightwards_hand_tone2",
- "rightwards_hand_medium_light_skin_tone",
- "rightwards_hand_tone3",
- "rightwards_hand_medium_skin_tone",
- "rightwards_hand_tone4",
- "rightwards_hand_medium_dark_skin_tone",
- "rightwards_hand_tone5",
- "rightwards_hand_dark_skin_tone",
- "muscle",
- "flexed_biceps",
- "muscle_tone1",
- "muscle_tone2",
- "muscle_tone3",
- "muscle_tone4",
- "muscle_tone5",
- "mechanical_arm",
- "middle_finger",
- "reversed_hand_with_middle_finger_extended",
- "middle_finger_tone1",
- "reversed_hand_with_middle_finger_extended_tone1",
- "middle_finger_tone2",
- "reversed_hand_with_middle_finger_extended_tone2",
- "middle_finger_tone3",
- "reversed_hand_with_middle_finger_extended_tone3",
- "middle_finger_tone4",
- "reversed_hand_with_middle_finger_extended_tone4",
- "middle_finger_tone5",
- "reversed_hand_with_middle_finger_extended_tone5",
- "writing_hand",
- "writing_hand_tone1",
- "writing_hand_tone2",
- "writing_hand_tone3",
- "writing_hand_tone4",
- "writing_hand_tone5",
- "pray",
- "folded_hands",
- "pray_tone1",
- "pray_tone2",
- "pray_tone3",
- "pray_tone4",
- "pray_tone5",
- "index_pointing_at_the_viewer",
- "index_pointing_at_the_viewer_tone1",
- "index_pointing_at_the_viewer_light_skin_tone",
- "index_pointing_at_the_viewer_tone2",
- "index_pointing_at_the_viewer_medium_light_skin_tone",
- "index_pointing_at_the_viewer_tone3",
- "index_pointing_at_the_viewer_medium_skin_tone",
- "index_pointing_at_the_viewer_tone4",
- "index_pointing_at_the_viewer_medium_dark_skin_tone",
- "index_pointing_at_the_viewer_tone5",
- "index_pointing_at_the_viewer_dark_skin_tone",
- "foot",
- "foot_tone1",
- "foot_light_skin_tone",
- "foot_tone2",
- "foot_medium_light_skin_tone",
- "foot_tone3",
- "foot_medium_skin_tone",
- "foot_tone4",
- "foot_medium_dark_skin_tone",
- "foot_tone5",
- "foot_dark_skin_tone",
- "leg",
- "leg_tone1",
- "leg_light_skin_tone",
- "leg_tone2",
- "leg_medium_light_skin_tone",
- "leg_tone3",
- "leg_medium_skin_tone",
- "leg_tone4",
- "leg_medium_dark_skin_tone",
- "leg_tone5",
- "leg_dark_skin_tone",
- "mechanical_leg",
- "lipstick",
- "kiss",
- "kiss_mark",
- "lips",
- "mouth",
- "biting_lip",
- "tooth",
- "tongue",
- "ear",
- "ear_tone1",
- "ear_tone2",
- "ear_tone3",
- "ear_tone4",
- "ear_tone5",
- "ear_with_hearing_aid",
- "ear_with_hearing_aid_tone1",
- "ear_with_hearing_aid_light_skin_tone",
- "ear_with_hearing_aid_tone2",
- "ear_with_hearing_aid_medium_light_skin_tone",
- "ear_with_hearing_aid_tone3",
- "ear_with_hearing_aid_medium_skin_tone",
- "ear_with_hearing_aid_tone4",
- "ear_with_hearing_aid_medium_dark_skin_tone",
- "ear_with_hearing_aid_tone5",
- "ear_with_hearing_aid_dark_skin_tone",
- "nose",
- "nose_tone1",
- "nose_tone2",
- "nose_tone3",
- "nose_tone4",
- "nose_tone5",
- "footprints",
- "eye",
- "eyes",
- "anatomical_heart",
- "lungs",
- "brain",
- "speaking_head",
- "speaking_head_in_silhouette",
- "bust_in_silhouette",
- "busts_in_silhouette",
- "people_hugging",
- "baby",
- "baby_tone1",
- "baby_tone2",
- "baby_tone3",
- "baby_tone4",
- "baby_tone5",
- "child",
- "child_tone1",
- "child_light_skin_tone",
- "child_tone2",
- "child_medium_light_skin_tone",
- "child_tone3",
- "child_medium_skin_tone",
- "child_tone4",
- "child_medium_dark_skin_tone",
- "child_tone5",
- "child_dark_skin_tone",
- "girl",
- "girl_tone1",
- "girl_tone2",
- "girl_tone3",
- "girl_tone4",
- "girl_tone5",
- "boy",
- "boy_tone1",
- "boy_tone2",
- "boy_tone3",
- "boy_tone4",
- "boy_tone5",
- "adult",
- "person",
- "adult_tone1",
- "adult_light_skin_tone",
- "adult_tone2",
- "adult_medium_light_skin_tone",
- "adult_tone3",
- "adult_medium_skin_tone",
- "adult_tone4",
- "adult_medium_dark_skin_tone",
- "adult_tone5",
- "adult_dark_skin_tone",
- "woman",
- "woman_tone1",
- "woman_tone2",
- "woman_tone3",
- "woman_tone4",
- "woman_tone5",
- "man",
- "man_tone1",
- "man_tone2",
- "man_tone3",
- "man_tone4",
- "man_tone5",
- "person_curly_hair",
- "person_tone1_curly_hair",
- "person_light_skin_tone_curly_hair",
- "person_tone2_curly_hair",
- "person_medium_light_skin_tone_curly_hair",
- "person_tone3_curly_hair",
- "person_medium_skin_tone_curly_hair",
- "person_tone4_curly_hair",
- "person_medium_dark_skin_tone_curly_hair",
- "person_tone5_curly_hair",
- "person_dark_skin_tone_curly_hair",
- "woman_curly_haired",
- "woman_curly_haired_tone1",
- "woman_curly_haired_light_skin_tone",
- "woman_curly_haired_tone2",
- "woman_curly_haired_medium_light_skin_tone",
- "woman_curly_haired_tone3",
- "woman_curly_haired_medium_skin_tone",
- "woman_curly_haired_tone4",
- "woman_curly_haired_medium_dark_skin_tone",
- "woman_curly_haired_tone5",
- "woman_curly_haired_dark_skin_tone",
- "man_curly_haired",
- "man_curly_haired_tone1",
- "man_curly_haired_light_skin_tone",
- "man_curly_haired_tone2",
- "man_curly_haired_medium_light_skin_tone",
- "man_curly_haired_tone3",
- "man_curly_haired_medium_skin_tone",
- "man_curly_haired_tone4",
- "man_curly_haired_medium_dark_skin_tone",
- "man_curly_haired_tone5",
- "man_curly_haired_dark_skin_tone",
- "person_red_hair",
- "person_tone1_red_hair",
- "person_light_skin_tone_red_hair",
- "person_tone2_red_hair",
- "person_medium_light_skin_tone_red_hair",
- "person_tone3_red_hair",
- "person_medium_skin_tone_red_hair",
- "person_tone4_red_hair",
- "person_medium_dark_skin_tone_red_hair",
- "person_tone5_red_hair",
- "person_dark_skin_tone_red_hair",
- "woman_red_haired",
- "woman_red_haired_tone1",
- "woman_red_haired_light_skin_tone",
- "woman_red_haired_tone2",
- "woman_red_haired_medium_light_skin_tone",
- "woman_red_haired_tone3",
- "woman_red_haired_medium_skin_tone",
- "woman_red_haired_tone4",
- "woman_red_haired_medium_dark_skin_tone",
- "woman_red_haired_tone5",
- "woman_red_haired_dark_skin_tone",
- "man_red_haired",
- "man_red_hair",
- "man_red_haired_tone1",
- "man_red_haired_light_skin_tone",
- "man_red_haired_tone2",
- "man_red_haired_medium_light_skin_tone",
- "man_red_haired_tone3",
- "man_red_haired_medium_skin_tone",
- "man_red_haired_tone4",
- "man_red_haired_medium_dark_skin_tone",
- "man_red_haired_tone5",
- "man_red_haired_dark_skin_tone",
- "blond_haired_person",
- "person_with_blond_hair",
- "blond_haired_person_tone1",
- "person_with_blond_hair_tone1",
- "blond_haired_person_tone2",
- "person_with_blond_hair_tone2",
- "blond_haired_person_tone3",
- "person_with_blond_hair_tone3",
- "blond_haired_person_tone4",
- "person_with_blond_hair_tone4",
- "blond_haired_person_tone5",
- "person_with_blond_hair_tone5",
- "blond_haired_woman",
- "blond_haired_woman_tone1",
- "blond_haired_woman_light_skin_tone",
- "blond_haired_woman_tone2",
- "blond_haired_woman_medium_light_skin_tone",
- "blond_haired_woman_tone3",
- "blond_haired_woman_medium_skin_tone",
- "blond_haired_woman_tone4",
- "blond_haired_woman_medium_dark_skin_tone",
- "blond_haired_woman_tone5",
- "blond_haired_woman_dark_skin_tone",
- "blond_haired_man",
- "blond_haired_man_tone1",
- "blond_haired_man_light_skin_tone",
- "blond_haired_man_tone2",
- "blond_haired_man_medium_light_skin_tone",
- "blond_haired_man_tone3",
- "blond_haired_man_medium_skin_tone",
- "blond_haired_man_tone4",
- "blond_haired_man_medium_dark_skin_tone",
- "blond_haired_man_tone5",
- "blond_haired_man_dark_skin_tone",
- "person_white_hair",
- "person_tone1_white_hair",
- "person_light_skin_tone_white_hair",
- "person_tone2_white_hair",
- "person_medium_light_skin_tone_white_hair",
- "person_tone3_white_hair",
- "person_medium_skin_tone_white_hair",
- "person_tone4_white_hair",
- "person_medium_dark_skin_tone_white_hair",
- "person_tone5_white_hair",
- "person_dark_skin_tone_white_hair",
- "woman_white_haired",
- "woman_white_haired_tone1",
- "woman_white_haired_light_skin_tone",
- "woman_white_haired_tone2",
- "woman_white_haired_medium_light_skin_tone",
- "woman_white_haired_tone3",
- "woman_white_haired_medium_skin_tone",
- "woman_white_haired_tone4",
- "woman_white_haired_medium_dark_skin_tone",
- "woman_white_haired_tone5",
- "woman_white_haired_dark_skin_tone",
- "man_white_haired",
- "man_white_haired_tone1",
- "man_white_haired_light_skin_tone",
- "man_white_haired_tone2",
- "man_white_haired_medium_light_skin_tone",
- "man_white_haired_tone3",
- "man_white_haired_medium_skin_tone",
- "man_white_haired_tone4",
- "man_white_haired_medium_dark_skin_tone",
- "man_white_haired_tone5",
- "man_white_haired_dark_skin_tone",
- "person_bald",
- "person_tone1_bald",
- "person_light_skin_tone_bald",
- "person_tone2_bald",
- "person_medium_light_skin_tone_bald",
- "person_tone3_bald",
- "person_medium_skin_tone_bald",
- "person_tone4_bald",
- "person_medium_dark_skin_tone_bald",
- "person_tone5_bald",
- "person_dark_skin_tone_bald",
- "woman_bald",
- "woman_bald_tone1",
- "woman_bald_light_skin_tone",
- "woman_bald_tone2",
- "woman_bald_medium_light_skin_tone",
- "woman_bald_tone3",
- "woman_bald_medium_skin_tone",
- "woman_bald_tone4",
- "woman_bald_medium_dark_skin_tone",
- "woman_bald_tone5",
- "woman_bald_dark_skin_tone",
- "man_bald",
- "man_bald_tone1",
- "man_bald_light_skin_tone",
- "man_bald_tone2",
- "man_bald_medium_light_skin_tone",
- "man_bald_tone3",
- "man_bald_medium_skin_tone",
- "man_bald_tone4",
- "man_bald_medium_dark_skin_tone",
- "man_bald_tone5",
- "man_bald_dark_skin_tone",
- "bearded_person",
- "person_beard",
- "bearded_person_tone1",
- "bearded_person_light_skin_tone",
- "bearded_person_tone2",
- "bearded_person_medium_light_skin_tone",
- "bearded_person_tone3",
- "bearded_person_medium_skin_tone",
- "bearded_person_tone4",
- "bearded_person_medium_dark_skin_tone",
- "bearded_person_tone5",
- "bearded_person_dark_skin_tone",
- "woman_beard",
- "woman_tone1_beard",
- "woman_light_skin_tone_beard",
- "woman_tone2_beard",
- "woman_medium_light_skin_tone_beard",
- "woman_tone3_beard",
- "woman_medium_skin_tone_beard",
- "woman_tone4_beard",
- "woman_medium_dark_skin_tone_beard",
- "woman_tone5_beard",
- "woman_dark_skin_tone_beard",
- "man_beard",
- "man_tone1_beard",
- "man_light_skin_tone_beard",
- "man_tone2_beard",
- "man_medium_light_skin_tone_beard",
- "man_tone3_beard",
- "man_medium_skin_tone_beard",
- "man_tone4_beard",
- "man_medium_dark_skin_tone_beard",
- "man_tone5_beard",
- "man_dark_skin_tone_beard",
- "older_adult",
- "older_person",
- "older_adult_tone1",
- "older_adult_light_skin_tone",
- "older_adult_tone2",
- "older_adult_medium_light_skin_tone",
- "older_adult_tone3",
- "older_adult_medium_skin_tone",
- "older_adult_tone4",
- "older_adult_medium_dark_skin_tone",
- "older_adult_tone5",
- "older_adult_dark_skin_tone",
- "older_woman",
- "grandma",
- "old_woman",
- "older_woman_tone1",
- "grandma_tone1",
- "older_woman_tone2",
- "grandma_tone2",
- "older_woman_tone3",
- "grandma_tone3",
- "older_woman_tone4",
- "grandma_tone4",
- "older_woman_tone5",
- "grandma_tone5",
- "older_man",
- "old_man",
- "older_man_tone1",
- "older_man_tone2",
- "older_man_tone3",
- "older_man_tone4",
- "older_man_tone5",
- "man_with_chinese_cap",
- "man_with_gua_pi_mao",
- "man_with_chinese_cap_tone1",
- "man_with_gua_pi_mao_tone1",
- "man_with_chinese_cap_tone2",
- "man_with_gua_pi_mao_tone2",
- "man_with_chinese_cap_tone3",
- "man_with_gua_pi_mao_tone3",
- "man_with_chinese_cap_tone4",
- "man_with_gua_pi_mao_tone4",
- "man_with_chinese_cap_tone5",
- "man_with_gua_pi_mao_tone5",
- "person_wearing_turban",
- "man_with_turban",
- "person_wearing_turban_tone1",
- "man_with_turban_tone1",
- "person_wearing_turban_tone2",
- "man_with_turban_tone2",
- "person_wearing_turban_tone3",
- "man_with_turban_tone3",
- "person_wearing_turban_tone4",
- "man_with_turban_tone4",
- "person_wearing_turban_tone5",
- "man_with_turban_tone5",
- "woman_wearing_turban",
- "woman_wearing_turban_tone1",
- "woman_wearing_turban_light_skin_tone",
- "woman_wearing_turban_tone2",
- "woman_wearing_turban_medium_light_skin_tone",
- "woman_wearing_turban_tone3",
- "woman_wearing_turban_medium_skin_tone",
- "woman_wearing_turban_tone4",
- "woman_wearing_turban_medium_dark_skin_tone",
- "woman_wearing_turban_tone5",
- "woman_wearing_turban_dark_skin_tone",
- "man_wearing_turban",
- "man_wearing_turban_tone1",
- "man_wearing_turban_light_skin_tone",
- "man_wearing_turban_tone2",
- "man_wearing_turban_medium_light_skin_tone",
- "man_wearing_turban_tone3",
- "man_wearing_turban_medium_skin_tone",
- "man_wearing_turban_tone4",
- "man_wearing_turban_medium_dark_skin_tone",
- "man_wearing_turban_tone5",
- "man_wearing_turban_dark_skin_tone",
- "woman_with_headscarf",
- "woman_with_headscarf_tone1",
- "woman_with_headscarf_light_skin_tone",
- "woman_with_headscarf_tone2",
- "woman_with_headscarf_medium_light_skin_tone",
- "woman_with_headscarf_tone3",
- "woman_with_headscarf_medium_skin_tone",
- "woman_with_headscarf_tone4",
- "woman_with_headscarf_medium_dark_skin_tone",
- "woman_with_headscarf_tone5",
- "woman_with_headscarf_dark_skin_tone",
- "police_officer",
- "cop",
- "police_officer_tone1",
- "cop_tone1",
- "police_officer_tone2",
- "cop_tone2",
- "police_officer_tone3",
- "cop_tone3",
- "police_officer_tone4",
- "cop_tone4",
- "police_officer_tone5",
- "cop_tone5",
- "woman_police_officer",
- "woman_police_officer_tone1",
- "woman_police_officer_light_skin_tone",
- "woman_police_officer_tone2",
- "woman_police_officer_medium_light_skin_tone",
- "woman_police_officer_tone3",
- "woman_police_officer_medium_skin_tone",
- "woman_police_officer_tone4",
- "woman_police_officer_medium_dark_skin_tone",
- "woman_police_officer_tone5",
- "woman_police_officer_dark_skin_tone",
- "man_police_officer",
- "man_police_officer_tone1",
- "man_police_officer_light_skin_tone",
- "man_police_officer_tone2",
- "man_police_officer_medium_light_skin_tone",
- "man_police_officer_tone3",
- "man_police_officer_medium_skin_tone",
- "man_police_officer_tone4",
- "man_police_officer_medium_dark_skin_tone",
- "man_police_officer_tone5",
- "man_police_officer_dark_skin_tone",
- "construction_worker",
- "construction_worker_tone1",
- "construction_worker_tone2",
- "construction_worker_tone3",
- "construction_worker_tone4",
- "construction_worker_tone5",
- "woman_construction_worker",
- "woman_construction_worker_tone1",
- "woman_construction_worker_light_skin_tone",
- "woman_construction_worker_tone2",
- "woman_construction_worker_medium_light_skin_tone",
- "woman_construction_worker_tone3",
- "woman_construction_worker_medium_skin_tone",
- "woman_construction_worker_tone4",
- "woman_construction_worker_medium_dark_skin_tone",
- "woman_construction_worker_tone5",
- "woman_construction_worker_dark_skin_tone",
- "man_construction_worker",
- "man_construction_worker_tone1",
- "man_construction_worker_light_skin_tone",
- "man_construction_worker_tone2",
- "man_construction_worker_medium_light_skin_tone",
- "man_construction_worker_tone3",
- "man_construction_worker_medium_skin_tone",
- "man_construction_worker_tone4",
- "man_construction_worker_medium_dark_skin_tone",
- "man_construction_worker_tone5",
- "man_construction_worker_dark_skin_tone",
- "guard",
- "guardsman",
- "guard_tone1",
- "guardsman_tone1",
- "guard_tone2",
- "guardsman_tone2",
- "guard_tone3",
- "guardsman_tone3",
- "guard_tone4",
- "guardsman_tone4",
- "guard_tone5",
- "guardsman_tone5",
- "woman_guard",
- "woman_guard_tone1",
- "woman_guard_light_skin_tone",
- "woman_guard_tone2",
- "woman_guard_medium_light_skin_tone",
- "woman_guard_tone3",
- "woman_guard_medium_skin_tone",
- "woman_guard_tone4",
- "woman_guard_medium_dark_skin_tone",
- "woman_guard_tone5",
- "woman_guard_dark_skin_tone",
- "man_guard",
- "man_guard_tone1",
- "man_guard_light_skin_tone",
- "man_guard_tone2",
- "man_guard_medium_light_skin_tone",
- "man_guard_tone3",
- "man_guard_medium_skin_tone",
- "man_guard_tone4",
- "man_guard_medium_dark_skin_tone",
- "man_guard_tone5",
- "man_guard_dark_skin_tone",
- "detective",
- "spy",
- "sleuth_or_spy",
- "detective_tone1",
- "spy_tone1",
- "sleuth_or_spy_tone1",
- "detective_tone2",
- "spy_tone2",
- "sleuth_or_spy_tone2",
- "detective_tone3",
- "spy_tone3",
- "sleuth_or_spy_tone3",
- "detective_tone4",
- "spy_tone4",
- "sleuth_or_spy_tone4",
- "detective_tone5",
- "spy_tone5",
- "sleuth_or_spy_tone5",
- "woman_detective",
- "woman_detective_tone1",
- "woman_detective_light_skin_tone",
- "woman_detective_tone2",
- "woman_detective_medium_light_skin_tone",
- "woman_detective_tone3",
- "woman_detective_medium_skin_tone",
- "woman_detective_tone4",
- "woman_detective_medium_dark_skin_tone",
- "woman_detective_tone5",
- "woman_detective_dark_skin_tone",
- "man_detective",
- "man_detective_tone1",
- "man_detective_light_skin_tone",
- "man_detective_tone2",
- "man_detective_medium_light_skin_tone",
- "man_detective_tone3",
- "man_detective_medium_skin_tone",
- "man_detective_tone4",
- "man_detective_medium_dark_skin_tone",
- "man_detective_tone5",
- "man_detective_dark_skin_tone",
- "health_worker",
- "health_worker_tone1",
- "health_worker_light_skin_tone",
- "health_worker_tone2",
- "health_worker_medium_light_skin_tone",
- "health_worker_tone3",
- "health_worker_medium_skin_tone",
- "health_worker_tone4",
- "health_worker_medium_dark_skin_tone",
- "health_worker_tone5",
- "health_worker_dark_skin_tone",
- "woman_health_worker",
- "woman_health_worker_tone1",
- "woman_health_worker_light_skin_tone",
- "woman_health_worker_tone2",
- "woman_health_worker_medium_light_skin_tone",
- "woman_health_worker_tone3",
- "woman_health_worker_medium_skin_tone",
- "woman_health_worker_tone4",
- "woman_health_worker_medium_dark_skin_tone",
- "woman_health_worker_tone5",
- "woman_health_worker_dark_skin_tone",
- "man_health_worker",
- "man_health_worker_tone1",
- "man_health_worker_light_skin_tone",
- "man_health_worker_tone2",
- "man_health_worker_medium_light_skin_tone",
- "man_health_worker_tone3",
- "man_health_worker_medium_skin_tone",
- "man_health_worker_tone4",
- "man_health_worker_medium_dark_skin_tone",
- "man_health_worker_tone5",
- "man_health_worker_dark_skin_tone",
- "farmer",
- "farmer_tone1",
- "farmer_light_skin_tone",
- "farmer_tone2",
- "farmer_medium_light_skin_tone",
- "farmer_tone3",
- "farmer_medium_skin_tone",
- "farmer_tone4",
- "farmer_medium_dark_skin_tone",
- "farmer_tone5",
- "farmer_dark_skin_tone",
- "woman_farmer",
- "woman_farmer_tone1",
- "woman_farmer_light_skin_tone",
- "woman_farmer_tone2",
- "woman_farmer_medium_light_skin_tone",
- "woman_farmer_tone3",
- "woman_farmer_medium_skin_tone",
- "woman_farmer_tone4",
- "woman_farmer_medium_dark_skin_tone",
- "woman_farmer_tone5",
- "woman_farmer_dark_skin_tone",
- "man_farmer",
- "man_farmer_tone1",
- "man_farmer_light_skin_tone",
- "man_farmer_tone2",
- "man_farmer_medium_light_skin_tone",
- "man_farmer_tone3",
- "man_farmer_medium_skin_tone",
- "man_farmer_tone4",
- "man_farmer_medium_dark_skin_tone",
- "man_farmer_tone5",
- "man_farmer_dark_skin_tone",
- "cook",
- "cook_tone1",
- "cook_light_skin_tone",
- "cook_tone2",
- "cook_medium_light_skin_tone",
- "cook_tone3",
- "cook_medium_skin_tone",
- "cook_tone4",
- "cook_medium_dark_skin_tone",
- "cook_tone5",
- "cook_dark_skin_tone",
- "woman_cook",
- "woman_cook_tone1",
- "woman_cook_light_skin_tone",
- "woman_cook_tone2",
- "woman_cook_medium_light_skin_tone",
- "woman_cook_tone3",
- "woman_cook_medium_skin_tone",
- "woman_cook_tone4",
- "woman_cook_medium_dark_skin_tone",
- "woman_cook_tone5",
- "woman_cook_dark_skin_tone",
- "man_cook",
- "man_cook_tone1",
- "man_cook_light_skin_tone",
- "man_cook_tone2",
- "man_cook_medium_light_skin_tone",
- "man_cook_tone3",
- "man_cook_medium_skin_tone",
- "man_cook_tone4",
- "man_cook_medium_dark_skin_tone",
- "man_cook_tone5",
- "man_cook_dark_skin_tone",
- "student",
- "student_tone1",
- "student_light_skin_tone",
- "student_tone2",
- "student_medium_light_skin_tone",
- "student_tone3",
- "student_medium_skin_tone",
- "student_tone4",
- "student_medium_dark_skin_tone",
- "student_tone5",
- "student_dark_skin_tone",
- "woman_student",
- "woman_student_tone1",
- "woman_student_light_skin_tone",
- "woman_student_tone2",
- "woman_student_medium_light_skin_tone",
- "woman_student_tone3",
- "woman_student_medium_skin_tone",
- "woman_student_tone4",
- "woman_student_medium_dark_skin_tone",
- "woman_student_tone5",
- "woman_student_dark_skin_tone",
- "man_student",
- "man_student_tone1",
- "man_student_light_skin_tone",
- "man_student_tone2",
- "man_student_medium_light_skin_tone",
- "man_student_tone3",
- "man_student_medium_skin_tone",
- "man_student_tone4",
- "man_student_medium_dark_skin_tone",
- "man_student_tone5",
- "man_student_dark_skin_tone",
- "singer",
- "singer_tone1",
- "singer_light_skin_tone",
- "singer_tone2",
- "singer_medium_light_skin_tone",
- "singer_tone3",
- "singer_medium_skin_tone",
- "singer_tone4",
- "singer_medium_dark_skin_tone",
- "singer_tone5",
- "singer_dark_skin_tone",
- "woman_singer",
- "woman_singer_tone1",
- "woman_singer_light_skin_tone",
- "woman_singer_tone2",
- "woman_singer_medium_light_skin_tone",
- "woman_singer_tone3",
- "woman_singer_medium_skin_tone",
- "woman_singer_tone4",
- "woman_singer_medium_dark_skin_tone",
- "woman_singer_tone5",
- "woman_singer_dark_skin_tone",
- "man_singer",
- "man_singer_tone1",
- "man_singer_light_skin_tone",
- "man_singer_tone2",
- "man_singer_medium_light_skin_tone",
- "man_singer_tone3",
- "man_singer_medium_skin_tone",
- "man_singer_tone4",
- "man_singer_medium_dark_skin_tone",
- "man_singer_tone5",
- "man_singer_dark_skin_tone",
- "teacher",
- "teacher_tone1",
- "teacher_light_skin_tone",
- "teacher_tone2",
- "teacher_medium_light_skin_tone",
- "teacher_tone3",
- "teacher_medium_skin_tone",
- "teacher_tone4",
- "teacher_medium_dark_skin_tone",
- "teacher_tone5",
- "teacher_dark_skin_tone",
- "woman_teacher",
- "woman_teacher_tone1",
- "woman_teacher_light_skin_tone",
- "woman_teacher_tone2",
- "woman_teacher_medium_light_skin_tone",
- "woman_teacher_tone3",
- "woman_teacher_medium_skin_tone",
- "woman_teacher_tone4",
- "woman_teacher_medium_dark_skin_tone",
- "woman_teacher_tone5",
- "woman_teacher_dark_skin_tone",
- "man_teacher",
- "man_teacher_tone1",
- "man_teacher_light_skin_tone",
- "man_teacher_tone2",
- "man_teacher_medium_light_skin_tone",
- "man_teacher_tone3",
- "man_teacher_medium_skin_tone",
- "man_teacher_tone4",
- "man_teacher_medium_dark_skin_tone",
- "man_teacher_tone5",
- "man_teacher_dark_skin_tone",
- "factory_worker",
- "factory_worker_tone1",
- "factory_worker_light_skin_tone",
- "factory_worker_tone2",
- "factory_worker_medium_light_skin_tone",
- "factory_worker_tone3",
- "factory_worker_medium_skin_tone",
- "factory_worker_tone4",
- "factory_worker_medium_dark_skin_tone",
- "factory_worker_tone5",
- "factory_worker_dark_skin_tone",
- "woman_factory_worker",
- "woman_factory_worker_tone1",
- "woman_factory_worker_light_skin_tone",
- "woman_factory_worker_tone2",
- "woman_factory_worker_medium_light_skin_tone",
- "woman_factory_worker_tone3",
- "woman_factory_worker_medium_skin_tone",
- "woman_factory_worker_tone4",
- "woman_factory_worker_medium_dark_skin_tone",
- "woman_factory_worker_tone5",
- "woman_factory_worker_dark_skin_tone",
- "man_factory_worker",
- "man_factory_worker_tone1",
- "man_factory_worker_light_skin_tone",
- "man_factory_worker_tone2",
- "man_factory_worker_medium_light_skin_tone",
- "man_factory_worker_tone3",
- "man_factory_worker_medium_skin_tone",
- "man_factory_worker_tone4",
- "man_factory_worker_medium_dark_skin_tone",
- "man_factory_worker_tone5",
- "man_factory_worker_dark_skin_tone",
- "technologist",
- "technologist_tone1",
- "technologist_light_skin_tone",
- "technologist_tone2",
- "technologist_medium_light_skin_tone",
- "technologist_tone3",
- "technologist_medium_skin_tone",
- "technologist_tone4",
- "technologist_medium_dark_skin_tone",
- "technologist_tone5",
- "technologist_dark_skin_tone",
- "woman_technologist",
- "woman_technologist_tone1",
- "woman_technologist_light_skin_tone",
- "woman_technologist_tone2",
- "woman_technologist_medium_light_skin_tone",
- "woman_technologist_tone3",
- "woman_technologist_medium_skin_tone",
- "woman_technologist_tone4",
- "woman_technologist_medium_dark_skin_tone",
- "woman_technologist_tone5",
- "woman_technologist_dark_skin_tone",
- "man_technologist",
- "man_technologist_tone1",
- "man_technologist_light_skin_tone",
- "man_technologist_tone2",
- "man_technologist_medium_light_skin_tone",
- "man_technologist_tone3",
- "man_technologist_medium_skin_tone",
- "man_technologist_tone4",
- "man_technologist_medium_dark_skin_tone",
- "man_technologist_tone5",
- "man_technologist_dark_skin_tone",
- "office_worker",
- "office_worker_tone1",
- "office_worker_light_skin_tone",
- "office_worker_tone2",
- "office_worker_medium_light_skin_tone",
- "office_worker_tone3",
- "office_worker_medium_skin_tone",
- "office_worker_tone4",
- "office_worker_medium_dark_skin_tone",
- "office_worker_tone5",
- "office_worker_dark_skin_tone",
- "woman_office_worker",
- "woman_office_worker_tone1",
- "woman_office_worker_light_skin_tone",
- "woman_office_worker_tone2",
- "woman_office_worker_medium_light_skin_tone",
- "woman_office_worker_tone3",
- "woman_office_worker_medium_skin_tone",
- "woman_office_worker_tone4",
- "woman_office_worker_medium_dark_skin_tone",
- "woman_office_worker_tone5",
- "woman_office_worker_dark_skin_tone",
- "man_office_worker",
- "man_office_worker_tone1",
- "man_office_worker_light_skin_tone",
- "man_office_worker_tone2",
- "man_office_worker_medium_light_skin_tone",
- "man_office_worker_tone3",
- "man_office_worker_medium_skin_tone",
- "man_office_worker_tone4",
- "man_office_worker_medium_dark_skin_tone",
- "man_office_worker_tone5",
- "man_office_worker_dark_skin_tone",
- "mechanic",
- "mechanic_tone1",
- "mechanic_light_skin_tone",
- "mechanic_tone2",
- "mechanic_medium_light_skin_tone",
- "mechanic_tone3",
- "mechanic_medium_skin_tone",
- "mechanic_tone4",
- "mechanic_medium_dark_skin_tone",
- "mechanic_tone5",
- "mechanic_dark_skin_tone",
- "woman_mechanic",
- "woman_mechanic_tone1",
- "woman_mechanic_light_skin_tone",
- "woman_mechanic_tone2",
- "woman_mechanic_medium_light_skin_tone",
- "woman_mechanic_tone3",
- "woman_mechanic_medium_skin_tone",
- "woman_mechanic_tone4",
- "woman_mechanic_medium_dark_skin_tone",
- "woman_mechanic_tone5",
- "woman_mechanic_dark_skin_tone",
- "man_mechanic",
- "man_mechanic_tone1",
- "man_mechanic_light_skin_tone",
- "man_mechanic_tone2",
- "man_mechanic_medium_light_skin_tone",
- "man_mechanic_tone3",
- "man_mechanic_medium_skin_tone",
- "man_mechanic_tone4",
- "man_mechanic_medium_dark_skin_tone",
- "man_mechanic_tone5",
- "man_mechanic_dark_skin_tone",
- "scientist",
- "scientist_tone1",
- "scientist_light_skin_tone",
- "scientist_tone2",
- "scientist_medium_light_skin_tone",
- "scientist_tone3",
- "scientist_medium_skin_tone",
- "scientist_tone4",
- "scientist_medium_dark_skin_tone",
- "scientist_tone5",
- "scientist_dark_skin_tone",
- "woman_scientist",
- "woman_scientist_tone1",
- "woman_scientist_light_skin_tone",
- "woman_scientist_tone2",
- "woman_scientist_medium_light_skin_tone",
- "woman_scientist_tone3",
- "woman_scientist_medium_skin_tone",
- "woman_scientist_tone4",
- "woman_scientist_medium_dark_skin_tone",
- "woman_scientist_tone5",
- "woman_scientist_dark_skin_tone",
- "man_scientist",
- "man_scientist_tone1",
- "man_scientist_light_skin_tone",
- "man_scientist_tone2",
- "man_scientist_medium_light_skin_tone",
- "man_scientist_tone3",
- "man_scientist_medium_skin_tone",
- "man_scientist_tone4",
- "man_scientist_medium_dark_skin_tone",
- "man_scientist_tone5",
- "man_scientist_dark_skin_tone",
- "artist",
- "artist_tone1",
- "artist_light_skin_tone",
- "artist_tone2",
- "artist_medium_light_skin_tone",
- "artist_tone3",
- "artist_medium_skin_tone",
- "artist_tone4",
- "artist_medium_dark_skin_tone",
- "artist_tone5",
- "artist_dark_skin_tone",
- "woman_artist",
- "woman_artist_tone1",
- "woman_artist_light_skin_tone",
- "woman_artist_tone2",
- "woman_artist_medium_light_skin_tone",
- "woman_artist_tone3",
- "woman_artist_medium_skin_tone",
- "woman_artist_tone4",
- "woman_artist_medium_dark_skin_tone",
- "woman_artist_tone5",
- "woman_artist_dark_skin_tone",
- "man_artist",
- "man_artist_tone1",
- "man_artist_light_skin_tone",
- "man_artist_tone2",
- "man_artist_medium_light_skin_tone",
- "man_artist_tone3",
- "man_artist_medium_skin_tone",
- "man_artist_tone4",
- "man_artist_medium_dark_skin_tone",
- "man_artist_tone5",
- "man_artist_dark_skin_tone",
- "firefighter",
- "firefighter_tone1",
- "firefighter_light_skin_tone",
- "firefighter_tone2",
- "firefighter_medium_light_skin_tone",
- "firefighter_tone3",
- "firefighter_medium_skin_tone",
- "firefighter_tone4",
- "firefighter_medium_dark_skin_tone",
- "firefighter_tone5",
- "firefighter_dark_skin_tone",
- "woman_firefighter",
- "woman_firefighter_tone1",
- "woman_firefighter_light_skin_tone",
- "woman_firefighter_tone2",
- "woman_firefighter_medium_light_skin_tone",
- "woman_firefighter_tone3",
- "woman_firefighter_medium_skin_tone",
- "woman_firefighter_tone4",
- "woman_firefighter_medium_dark_skin_tone",
- "woman_firefighter_tone5",
- "woman_firefighter_dark_skin_tone",
- "man_firefighter",
- "man_firefighter_tone1",
- "man_firefighter_light_skin_tone",
- "man_firefighter_tone2",
- "man_firefighter_medium_light_skin_tone",
- "man_firefighter_tone3",
- "man_firefighter_medium_skin_tone",
- "man_firefighter_tone4",
- "man_firefighter_medium_dark_skin_tone",
- "man_firefighter_tone5",
- "man_firefighter_dark_skin_tone",
- "pilot",
- "pilot_tone1",
- "pilot_light_skin_tone",
- "pilot_tone2",
- "pilot_medium_light_skin_tone",
- "pilot_tone3",
- "pilot_medium_skin_tone",
- "pilot_tone4",
- "pilot_medium_dark_skin_tone",
- "pilot_tone5",
- "pilot_dark_skin_tone",
- "woman_pilot",
- "woman_pilot_tone1",
- "woman_pilot_light_skin_tone",
- "woman_pilot_tone2",
- "woman_pilot_medium_light_skin_tone",
- "woman_pilot_tone3",
- "woman_pilot_medium_skin_tone",
- "woman_pilot_tone4",
- "woman_pilot_medium_dark_skin_tone",
- "woman_pilot_tone5",
- "woman_pilot_dark_skin_tone",
- "man_pilot",
- "man_pilot_tone1",
- "man_pilot_light_skin_tone",
- "man_pilot_tone2",
- "man_pilot_medium_light_skin_tone",
- "man_pilot_tone3",
- "man_pilot_medium_skin_tone",
- "man_pilot_tone4",
- "man_pilot_medium_dark_skin_tone",
- "man_pilot_tone5",
- "man_pilot_dark_skin_tone",
- "astronaut",
- "astronaut_tone1",
- "astronaut_light_skin_tone",
- "astronaut_tone2",
- "astronaut_medium_light_skin_tone",
- "astronaut_tone3",
- "astronaut_medium_skin_tone",
- "astronaut_tone4",
- "astronaut_medium_dark_skin_tone",
- "astronaut_tone5",
- "astronaut_dark_skin_tone",
- "woman_astronaut",
- "woman_astronaut_tone1",
- "woman_astronaut_light_skin_tone",
- "woman_astronaut_tone2",
- "woman_astronaut_medium_light_skin_tone",
- "woman_astronaut_tone3",
- "woman_astronaut_medium_skin_tone",
- "woman_astronaut_tone4",
- "woman_astronaut_medium_dark_skin_tone",
- "woman_astronaut_tone5",
- "woman_astronaut_dark_skin_tone",
- "man_astronaut",
- "man_astronaut_tone1",
- "man_astronaut_light_skin_tone",
- "man_astronaut_tone2",
- "man_astronaut_medium_light_skin_tone",
- "man_astronaut_tone3",
- "man_astronaut_medium_skin_tone",
- "man_astronaut_tone4",
- "man_astronaut_medium_dark_skin_tone",
- "man_astronaut_tone5",
- "man_astronaut_dark_skin_tone",
- "judge",
- "judge_tone1",
- "judge_light_skin_tone",
- "judge_tone2",
- "judge_medium_light_skin_tone",
- "judge_tone3",
- "judge_medium_skin_tone",
- "judge_tone4",
- "judge_medium_dark_skin_tone",
- "judge_tone5",
- "judge_dark_skin_tone",
- "woman_judge",
- "woman_judge_tone1",
- "woman_judge_light_skin_tone",
- "woman_judge_tone2",
- "woman_judge_medium_light_skin_tone",
- "woman_judge_tone3",
- "woman_judge_medium_skin_tone",
- "woman_judge_tone4",
- "woman_judge_medium_dark_skin_tone",
- "woman_judge_tone5",
- "woman_judge_dark_skin_tone",
- "man_judge",
- "man_judge_tone1",
- "man_judge_light_skin_tone",
- "man_judge_tone2",
- "man_judge_medium_light_skin_tone",
- "man_judge_tone3",
- "man_judge_medium_skin_tone",
- "man_judge_tone4",
- "man_judge_medium_dark_skin_tone",
- "man_judge_tone5",
- "man_judge_dark_skin_tone",
- "person_with_veil",
- "person_with_veil_tone1",
- "person_with_veil_tone2",
- "person_with_veil_tone3",
- "person_with_veil_tone4",
- "person_with_veil_tone5",
- "woman_with_veil",
- "bride_with_veil",
- "woman_with_veil_tone1",
- "woman_with_veil_light_skin_tone",
- "woman_with_veil_tone2",
- "woman_with_veil_medium_light_skin_tone",
- "woman_with_veil_tone3",
- "woman_with_veil_medium_skin_tone",
- "woman_with_veil_tone4",
- "woman_with_veil_medium_dark_skin_tone",
- "woman_with_veil_tone5",
- "woman_with_veil_dark_skin_tone",
- "man_with_veil",
- "man_with_veil_tone1",
- "man_with_veil_light_skin_tone",
- "man_with_veil_tone2",
- "man_with_veil_medium_light_skin_tone",
- "man_with_veil_tone3",
- "man_with_veil_medium_skin_tone",
- "man_with_veil_tone4",
- "man_with_veil_medium_dark_skin_tone",
- "man_with_veil_tone5",
- "man_with_veil_dark_skin_tone",
- "person_in_tuxedo",
- "person_in_tuxedo_tone1",
- "tuxedo_tone1",
- "person_in_tuxedo_tone2",
- "tuxedo_tone2",
- "person_in_tuxedo_tone3",
- "tuxedo_tone3",
- "person_in_tuxedo_tone4",
- "tuxedo_tone4",
- "person_in_tuxedo_tone5",
- "tuxedo_tone5",
- "woman_in_tuxedo",
- "woman_in_tuxedo_tone1",
- "woman_in_tuxedo_light_skin_tone",
- "woman_in_tuxedo_tone2",
- "woman_in_tuxedo_medium_light_skin_tone",
- "woman_in_tuxedo_tone3",
- "woman_in_tuxedo_medium_skin_tone",
- "woman_in_tuxedo_tone4",
- "woman_in_tuxedo_medium_dark_skin_tone",
- "woman_in_tuxedo_tone5",
- "woman_in_tuxedo_dark_skin_tone",
- "man_in_tuxedo",
- "man_in_tuxedo_tone1",
- "man_in_tuxedo_light_skin_tone",
- "man_in_tuxedo_tone2",
- "man_in_tuxedo_medium_light_skin_tone",
- "man_in_tuxedo_tone3",
- "man_in_tuxedo_medium_skin_tone",
- "man_in_tuxedo_tone4",
- "man_in_tuxedo_medium_dark_skin_tone",
- "man_in_tuxedo_tone5",
- "man_in_tuxedo_dark_skin_tone",
- "person_with_crown",
- "person_with_crown_tone1",
- "person_with_crown_light_skin_tone",
- "person_with_crown_tone2",
- "person_with_crown_medium_light_skin_tone",
- "person_with_crown_tone3",
- "person_with_crown_medium_skin_tone",
- "person_with_crown_tone4",
- "person_with_crown_medium_dark_skin_tone",
- "person_with_crown_tone5",
- "person_with_crown_dark_skin_tone",
- "princess",
- "princess_tone1",
- "princess_tone2",
- "princess_tone3",
- "princess_tone4",
- "princess_tone5",
- "prince",
- "prince_tone1",
- "prince_tone2",
- "prince_tone3",
- "prince_tone4",
- "prince_tone5",
- "superhero",
- "superhero_tone1",
- "superhero_light_skin_tone",
- "superhero_tone2",
- "superhero_medium_light_skin_tone",
- "superhero_tone3",
- "superhero_medium_skin_tone",
- "superhero_tone4",
- "superhero_medium_dark_skin_tone",
- "superhero_tone5",
- "superhero_dark_skin_tone",
- "woman_superhero",
- "woman_superhero_tone1",
- "woman_superhero_light_skin_tone",
- "woman_superhero_tone2",
- "woman_superhero_medium_light_skin_tone",
- "woman_superhero_tone3",
- "woman_superhero_medium_skin_tone",
- "woman_superhero_tone4",
- "woman_superhero_medium_dark_skin_tone",
- "woman_superhero_tone5",
- "woman_superhero_dark_skin_tone",
- "man_superhero",
- "man_superhero_tone1",
- "man_superhero_light_skin_tone",
- "man_superhero_tone2",
- "man_superhero_medium_light_skin_tone",
- "man_superhero_tone3",
- "man_superhero_medium_skin_tone",
- "man_superhero_tone4",
- "man_superhero_medium_dark_skin_tone",
- "man_superhero_tone5",
- "man_superhero_dark_skin_tone",
- "supervillain",
- "supervillain_tone1",
- "supervillain_light_skin_tone",
- "supervillain_tone2",
- "supervillain_medium_light_skin_tone",
- "supervillain_tone3",
- "supervillain_medium_skin_tone",
- "supervillain_tone4",
- "supervillain_medium_dark_skin_tone",
- "supervillain_tone5",
- "supervillain_dark_skin_tone",
- "woman_supervillain",
- "woman_supervillain_tone1",
- "woman_supervillain_light_skin_tone",
- "woman_supervillain_tone2",
- "woman_supervillain_medium_light_skin_tone",
- "woman_supervillain_tone3",
- "woman_supervillain_medium_skin_tone",
- "woman_supervillain_tone4",
- "woman_supervillain_medium_dark_skin_tone",
- "woman_supervillain_tone5",
- "woman_supervillain_dark_skin_tone",
- "man_supervillain",
- "man_supervillain_tone1",
- "man_supervillain_light_skin_tone",
- "man_supervillain_tone2",
- "man_supervillain_medium_light_skin_tone",
- "man_supervillain_tone3",
- "man_supervillain_medium_skin_tone",
- "man_supervillain_tone4",
- "man_supervillain_medium_dark_skin_tone",
- "man_supervillain_tone5",
- "man_supervillain_dark_skin_tone",
- "ninja",
- "ninja_tone1",
- "ninja_light_skin_tone",
- "ninja_tone2",
- "ninja_medium_light_skin_tone",
- "ninja_tone3",
- "ninja_medium_skin_tone",
- "ninja_tone4",
- "ninja_medium_dark_skin_tone",
- "ninja_tone5",
- "ninja_dark_skin_tone",
- "mx_claus",
- "mx_claus_tone1",
- "mx_claus_light_skin_tone",
- "mx_claus_tone2",
- "mx_claus_medium_light_skin_tone",
- "mx_claus_tone3",
- "mx_claus_medium_skin_tone",
- "mx_claus_tone4",
- "mx_claus_medium_dark_skin_tone",
- "mx_claus_tone5",
- "mx_claus_dark_skin_tone",
- "mrs_claus",
- "mother_christmas",
- "mrs_claus_tone1",
- "mother_christmas_tone1",
- "mrs_claus_tone2",
- "mother_christmas_tone2",
- "mrs_claus_tone3",
- "mother_christmas_tone3",
- "mrs_claus_tone4",
- "mother_christmas_tone4",
- "mrs_claus_tone5",
- "mother_christmas_tone5",
- "santa",
- "santa_claus",
- "santa_tone1",
- "santa_tone2",
- "santa_tone3",
- "santa_tone4",
- "santa_tone5",
- "mage",
- "mage_tone1",
- "mage_light_skin_tone",
- "mage_tone2",
- "mage_medium_light_skin_tone",
- "mage_tone3",
- "mage_medium_skin_tone",
- "mage_tone4",
- "mage_medium_dark_skin_tone",
- "mage_tone5",
- "mage_dark_skin_tone",
- "woman_mage",
- "woman_mage_tone1",
- "woman_mage_light_skin_tone",
- "woman_mage_tone2",
- "woman_mage_medium_light_skin_tone",
- "woman_mage_tone3",
- "woman_mage_medium_skin_tone",
- "woman_mage_tone4",
- "woman_mage_medium_dark_skin_tone",
- "woman_mage_tone5",
- "woman_mage_dark_skin_tone",
- "man_mage",
- "man_mage_tone1",
- "man_mage_light_skin_tone",
- "man_mage_tone2",
- "man_mage_medium_light_skin_tone",
- "man_mage_tone3",
- "man_mage_medium_skin_tone",
- "man_mage_tone4",
- "man_mage_medium_dark_skin_tone",
- "man_mage_tone5",
- "man_mage_dark_skin_tone",
- "elf",
- "elf_tone1",
- "elf_light_skin_tone",
- "elf_tone2",
- "elf_medium_light_skin_tone",
- "elf_tone3",
- "elf_medium_skin_tone",
- "elf_tone4",
- "elf_medium_dark_skin_tone",
- "elf_tone5",
- "elf_dark_skin_tone",
- "woman_elf",
- "woman_elf_tone1",
- "woman_elf_light_skin_tone",
- "woman_elf_tone2",
- "woman_elf_medium_light_skin_tone",
- "woman_elf_tone3",
- "woman_elf_medium_skin_tone",
- "woman_elf_tone4",
- "woman_elf_medium_dark_skin_tone",
- "woman_elf_tone5",
- "woman_elf_dark_skin_tone",
- "man_elf",
- "man_elf_tone1",
- "man_elf_light_skin_tone",
- "man_elf_tone2",
- "man_elf_medium_light_skin_tone",
- "man_elf_tone3",
- "man_elf_medium_skin_tone",
- "man_elf_tone4",
- "man_elf_medium_dark_skin_tone",
- "man_elf_tone5",
- "man_elf_dark_skin_tone",
- "troll",
- "vampire",
- "vampire_tone1",
- "vampire_light_skin_tone",
- "vampire_tone2",
- "vampire_medium_light_skin_tone",
- "vampire_tone3",
- "vampire_medium_skin_tone",
- "vampire_tone4",
- "vampire_medium_dark_skin_tone",
- "vampire_tone5",
- "vampire_dark_skin_tone",
- "woman_vampire",
- "woman_vampire_tone1",
- "woman_vampire_light_skin_tone",
- "woman_vampire_tone2",
- "woman_vampire_medium_light_skin_tone",
- "woman_vampire_tone3",
- "woman_vampire_medium_skin_tone",
- "woman_vampire_tone4",
- "woman_vampire_medium_dark_skin_tone",
- "woman_vampire_tone5",
- "woman_vampire_dark_skin_tone",
- "man_vampire",
- "man_vampire_tone1",
- "man_vampire_light_skin_tone",
- "man_vampire_tone2",
- "man_vampire_medium_light_skin_tone",
- "man_vampire_tone3",
- "man_vampire_medium_skin_tone",
- "man_vampire_tone4",
- "man_vampire_medium_dark_skin_tone",
- "man_vampire_tone5",
- "man_vampire_dark_skin_tone",
- "zombie",
- "woman_zombie",
- "man_zombie",
- "genie",
- "woman_genie",
- "man_genie",
- "merperson",
- "merperson_tone1",
- "merperson_light_skin_tone",
- "merperson_tone2",
- "merperson_medium_light_skin_tone",
- "merperson_tone3",
- "merperson_medium_skin_tone",
- "merperson_tone4",
- "merperson_medium_dark_skin_tone",
- "merperson_tone5",
- "merperson_dark_skin_tone",
- "mermaid",
- "mermaid_tone1",
- "mermaid_light_skin_tone",
- "mermaid_tone2",
- "mermaid_medium_light_skin_tone",
- "mermaid_tone3",
- "mermaid_medium_skin_tone",
- "mermaid_tone4",
- "mermaid_medium_dark_skin_tone",
- "mermaid_tone5",
- "mermaid_dark_skin_tone",
- "merman",
- "merman_tone1",
- "merman_light_skin_tone",
- "merman_tone2",
- "merman_medium_light_skin_tone",
- "merman_tone3",
- "merman_medium_skin_tone",
- "merman_tone4",
- "merman_medium_dark_skin_tone",
- "merman_tone5",
- "merman_dark_skin_tone",
- "fairy",
- "fairy_tone1",
- "fairy_light_skin_tone",
- "fairy_tone2",
- "fairy_medium_light_skin_tone",
- "fairy_tone3",
- "fairy_medium_skin_tone",
- "fairy_tone4",
- "fairy_medium_dark_skin_tone",
- "fairy_tone5",
- "fairy_dark_skin_tone",
- "woman_fairy",
- "woman_fairy_tone1",
- "woman_fairy_light_skin_tone",
- "woman_fairy_tone2",
- "woman_fairy_medium_light_skin_tone",
- "woman_fairy_tone3",
- "woman_fairy_medium_skin_tone",
- "woman_fairy_tone4",
- "woman_fairy_medium_dark_skin_tone",
- "woman_fairy_tone5",
- "woman_fairy_dark_skin_tone",
- "man_fairy",
- "man_fairy_tone1",
- "man_fairy_light_skin_tone",
- "man_fairy_tone2",
- "man_fairy_medium_light_skin_tone",
- "man_fairy_tone3",
- "man_fairy_medium_skin_tone",
- "man_fairy_tone4",
- "man_fairy_medium_dark_skin_tone",
- "man_fairy_tone5",
- "man_fairy_dark_skin_tone",
- "angel",
- "baby_angel",
- "angel_tone1",
- "angel_tone2",
- "angel_tone3",
- "angel_tone4",
- "angel_tone5",
- "pregnant_person",
- "pregnant_person_tone1",
- "pregnant_person_light_skin_tone",
- "pregnant_person_tone2",
- "pregnant_person_medium_light_skin_tone",
- "pregnant_person_tone3",
- "pregnant_person_medium_skin_tone",
- "pregnant_person_tone4",
- "pregnant_person_medium_dark_skin_tone",
- "pregnant_person_tone5",
- "pregnant_person_dark_skin_tone",
- "pregnant_woman",
- "expecting_woman",
- "pregnant_woman_tone1",
- "expecting_woman_tone1",
- "pregnant_woman_tone2",
- "expecting_woman_tone2",
- "pregnant_woman_tone3",
- "expecting_woman_tone3",
- "pregnant_woman_tone4",
- "expecting_woman_tone4",
- "pregnant_woman_tone5",
- "expecting_woman_tone5",
- "pregnant_man",
- "pregnant_man_tone1",
- "pregnant_man_light_skin_tone",
- "pregnant_man_tone2",
- "pregnant_man_medium_light_skin_tone",
- "pregnant_man_tone3",
- "pregnant_man_medium_skin_tone",
- "pregnant_man_tone4",
- "pregnant_man_medium_dark_skin_tone",
- "pregnant_man_tone5",
- "pregnant_man_dark_skin_tone",
- "breast_feeding",
- "breast_feeding_tone1",
- "breast_feeding_light_skin_tone",
- "breast_feeding_tone2",
- "breast_feeding_medium_light_skin_tone",
- "breast_feeding_tone3",
- "breast_feeding_medium_skin_tone",
- "breast_feeding_tone4",
- "breast_feeding_medium_dark_skin_tone",
- "breast_feeding_tone5",
- "breast_feeding_dark_skin_tone",
- "person_feeding_baby",
- "person_feeding_baby_tone1",
- "person_feeding_baby_light_skin_tone",
- "person_feeding_baby_tone2",
- "person_feeding_baby_medium_light_skin_tone",
- "person_feeding_baby_tone3",
- "person_feeding_baby_medium_skin_tone",
- "person_feeding_baby_tone4",
- "person_feeding_baby_medium_dark_skin_tone",
- "person_feeding_baby_tone5",
- "person_feeding_baby_dark_skin_tone",
- "woman_feeding_baby",
- "woman_feeding_baby_tone1",
- "woman_feeding_baby_light_skin_tone",
- "woman_feeding_baby_tone2",
- "woman_feeding_baby_medium_light_skin_tone",
- "woman_feeding_baby_tone3",
- "woman_feeding_baby_medium_skin_tone",
- "woman_feeding_baby_tone4",
- "woman_feeding_baby_medium_dark_skin_tone",
- "woman_feeding_baby_tone5",
- "woman_feeding_baby_dark_skin_tone",
- "man_feeding_baby",
- "man_feeding_baby_tone1",
- "man_feeding_baby_light_skin_tone",
- "man_feeding_baby_tone2",
- "man_feeding_baby_medium_light_skin_tone",
- "man_feeding_baby_tone3",
- "man_feeding_baby_medium_skin_tone",
- "man_feeding_baby_tone4",
- "man_feeding_baby_medium_dark_skin_tone",
- "man_feeding_baby_tone5",
- "man_feeding_baby_dark_skin_tone",
- "person_bowing",
- "bow",
- "person_bowing_tone1",
- "bow_tone1",
- "person_bowing_tone2",
- "bow_tone2",
- "person_bowing_tone3",
- "bow_tone3",
- "person_bowing_tone4",
- "bow_tone4",
- "person_bowing_tone5",
- "bow_tone5",
- "woman_bowing",
- "woman_bowing_tone1",
- "woman_bowing_light_skin_tone",
- "woman_bowing_tone2",
- "woman_bowing_medium_light_skin_tone",
- "woman_bowing_tone3",
- "woman_bowing_medium_skin_tone",
- "woman_bowing_tone4",
- "woman_bowing_medium_dark_skin_tone",
- "woman_bowing_tone5",
- "woman_bowing_dark_skin_tone",
- "man_bowing",
- "man_bowing_tone1",
- "man_bowing_light_skin_tone",
- "man_bowing_tone2",
- "man_bowing_medium_light_skin_tone",
- "man_bowing_tone3",
- "man_bowing_medium_skin_tone",
- "man_bowing_tone4",
- "man_bowing_medium_dark_skin_tone",
- "man_bowing_tone5",
- "man_bowing_dark_skin_tone",
- "person_tipping_hand",
- "information_desk_person",
- "person_tipping_hand_tone1",
- "information_desk_person_tone1",
- "person_tipping_hand_tone2",
- "information_desk_person_tone2",
- "person_tipping_hand_tone3",
- "information_desk_person_tone3",
- "person_tipping_hand_tone4",
- "information_desk_person_tone4",
- "person_tipping_hand_tone5",
- "information_desk_person_tone5",
- "woman_tipping_hand",
- "woman_tipping_hand_tone1",
- "woman_tipping_hand_light_skin_tone",
- "woman_tipping_hand_tone2",
- "woman_tipping_hand_medium_light_skin_tone",
- "woman_tipping_hand_tone3",
- "woman_tipping_hand_medium_skin_tone",
- "woman_tipping_hand_tone4",
- "woman_tipping_hand_medium_dark_skin_tone",
- "woman_tipping_hand_tone5",
- "woman_tipping_hand_dark_skin_tone",
- "man_tipping_hand",
- "man_tipping_hand_tone1",
- "man_tipping_hand_light_skin_tone",
- "man_tipping_hand_tone2",
- "man_tipping_hand_medium_light_skin_tone",
- "man_tipping_hand_tone3",
- "man_tipping_hand_medium_skin_tone",
- "man_tipping_hand_tone4",
- "man_tipping_hand_medium_dark_skin_tone",
- "man_tipping_hand_tone5",
- "man_tipping_hand_dark_skin_tone",
- "person_gesturing_no",
- "no_good",
- "person_gesturing_no_tone1",
- "no_good_tone1",
- "person_gesturing_no_tone2",
- "no_good_tone2",
- "person_gesturing_no_tone3",
- "no_good_tone3",
- "person_gesturing_no_tone4",
- "no_good_tone4",
- "person_gesturing_no_tone5",
- "no_good_tone5",
- "woman_gesturing_no",
- "woman_gesturing_no_tone1",
- "woman_gesturing_no_light_skin_tone",
- "woman_gesturing_no_tone2",
- "woman_gesturing_no_medium_light_skin_tone",
- "woman_gesturing_no_tone3",
- "woman_gesturing_no_medium_skin_tone",
- "woman_gesturing_no_tone4",
- "woman_gesturing_no_medium_dark_skin_tone",
- "woman_gesturing_no_tone5",
- "woman_gesturing_no_dark_skin_tone",
- "man_gesturing_no",
- "man_gesturing_no_tone1",
- "man_gesturing_no_light_skin_tone",
- "man_gesturing_no_tone2",
- "man_gesturing_no_medium_light_skin_tone",
- "man_gesturing_no_tone3",
- "man_gesturing_no_medium_skin_tone",
- "man_gesturing_no_tone4",
- "man_gesturing_no_medium_dark_skin_tone",
- "man_gesturing_no_tone5",
- "man_gesturing_no_dark_skin_tone",
- "person_gesturing_ok",
- "person_gesturing_ok_tone1",
- "person_gesturing_ok_tone2",
- "person_gesturing_ok_tone3",
- "person_gesturing_ok_tone4",
- "person_gesturing_ok_tone5",
- "woman_gesturing_ok",
- "woman_gesturing_ok_tone1",
- "woman_gesturing_ok_light_skin_tone",
- "woman_gesturing_ok_tone2",
- "woman_gesturing_ok_medium_light_skin_tone",
- "woman_gesturing_ok_tone3",
- "woman_gesturing_ok_medium_skin_tone",
- "woman_gesturing_ok_tone4",
- "woman_gesturing_ok_medium_dark_skin_tone",
- "woman_gesturing_ok_tone5",
- "woman_gesturing_ok_dark_skin_tone",
- "man_gesturing_ok",
- "man_gesturing_ok_tone1",
- "man_gesturing_ok_light_skin_tone",
- "man_gesturing_ok_tone2",
- "man_gesturing_ok_medium_light_skin_tone",
- "man_gesturing_ok_tone3",
- "man_gesturing_ok_medium_skin_tone",
- "man_gesturing_ok_tone4",
- "man_gesturing_ok_medium_dark_skin_tone",
- "man_gesturing_ok_tone5",
- "man_gesturing_ok_dark_skin_tone",
- "person_raising_hand",
- "raising_hand",
- "person_raising_hand_tone1",
- "raising_hand_tone1",
- "person_raising_hand_tone2",
- "raising_hand_tone2",
- "person_raising_hand_tone3",
- "raising_hand_tone3",
- "person_raising_hand_tone4",
- "raising_hand_tone4",
- "person_raising_hand_tone5",
- "raising_hand_tone5",
- "woman_raising_hand",
- "woman_raising_hand_tone1",
- "woman_raising_hand_light_skin_tone",
- "woman_raising_hand_tone2",
- "woman_raising_hand_medium_light_skin_tone",
- "woman_raising_hand_tone3",
- "woman_raising_hand_medium_skin_tone",
- "woman_raising_hand_tone4",
- "woman_raising_hand_medium_dark_skin_tone",
- "woman_raising_hand_tone5",
- "woman_raising_hand_dark_skin_tone",
- "man_raising_hand",
- "man_raising_hand_tone1",
- "man_raising_hand_light_skin_tone",
- "man_raising_hand_tone2",
- "man_raising_hand_medium_light_skin_tone",
- "man_raising_hand_tone3",
- "man_raising_hand_medium_skin_tone",
- "man_raising_hand_tone4",
- "man_raising_hand_medium_dark_skin_tone",
- "man_raising_hand_tone5",
- "man_raising_hand_dark_skin_tone",
- "deaf_person",
- "deaf_person_tone1",
- "deaf_person_light_skin_tone",
- "deaf_person_tone2",
- "deaf_person_medium_light_skin_tone",
- "deaf_person_tone3",
- "deaf_person_medium_skin_tone",
- "deaf_person_tone4",
- "deaf_person_medium_dark_skin_tone",
- "deaf_person_tone5",
- "deaf_person_dark_skin_tone",
- "deaf_woman",
- "deaf_woman_tone1",
- "deaf_woman_light_skin_tone",
- "deaf_woman_tone2",
- "deaf_woman_medium_light_skin_tone",
- "deaf_woman_tone3",
- "deaf_woman_medium_skin_tone",
- "deaf_woman_tone4",
- "deaf_woman_medium_dark_skin_tone",
- "deaf_woman_tone5",
- "deaf_woman_dark_skin_tone",
- "deaf_man",
- "deaf_man_tone1",
- "deaf_man_light_skin_tone",
- "deaf_man_tone2",
- "deaf_man_medium_light_skin_tone",
- "deaf_man_tone3",
- "deaf_man_medium_skin_tone",
- "deaf_man_tone4",
- "deaf_man_medium_dark_skin_tone",
- "deaf_man_tone5",
- "deaf_man_dark_skin_tone",
- "person_facepalming",
- "face_palm",
- "facepalm",
- "person_facepalming_tone1",
- "face_palm_tone1",
- "facepalm_tone1",
- "person_facepalming_tone2",
- "face_palm_tone2",
- "facepalm_tone2",
- "person_facepalming_tone3",
- "face_palm_tone3",
- "facepalm_tone3",
- "person_facepalming_tone4",
- "face_palm_tone4",
- "facepalm_tone4",
- "person_facepalming_tone5",
- "face_palm_tone5",
- "facepalm_tone5",
- "woman_facepalming",
- "woman_facepalming_tone1",
- "woman_facepalming_light_skin_tone",
- "woman_facepalming_tone2",
- "woman_facepalming_medium_light_skin_tone",
- "woman_facepalming_tone3",
- "woman_facepalming_medium_skin_tone",
- "woman_facepalming_tone4",
- "woman_facepalming_medium_dark_skin_tone",
- "woman_facepalming_tone5",
- "woman_facepalming_dark_skin_tone",
- "man_facepalming",
- "man_facepalming_tone1",
- "man_facepalming_light_skin_tone",
- "man_facepalming_tone2",
- "man_facepalming_medium_light_skin_tone",
- "man_facepalming_tone3",
- "man_facepalming_medium_skin_tone",
- "man_facepalming_tone4",
- "man_facepalming_medium_dark_skin_tone",
- "man_facepalming_tone5",
- "man_facepalming_dark_skin_tone",
- "person_shrugging",
- "shrug",
- "person_shrugging_tone1",
- "shrug_tone1",
- "person_shrugging_tone2",
- "shrug_tone2",
- "person_shrugging_tone3",
- "shrug_tone3",
- "person_shrugging_tone4",
- "shrug_tone4",
- "person_shrugging_tone5",
- "shrug_tone5",
- "woman_shrugging",
- "woman_shrugging_tone1",
- "woman_shrugging_light_skin_tone",
- "woman_shrugging_tone2",
- "woman_shrugging_medium_light_skin_tone",
- "woman_shrugging_tone3",
- "woman_shrugging_medium_skin_tone",
- "woman_shrugging_tone4",
- "woman_shrugging_medium_dark_skin_tone",
- "woman_shrugging_tone5",
- "woman_shrugging_dark_skin_tone",
- "man_shrugging",
- "man_shrugging_tone1",
- "man_shrugging_light_skin_tone",
- "man_shrugging_tone2",
- "man_shrugging_medium_light_skin_tone",
- "man_shrugging_tone3",
- "man_shrugging_medium_skin_tone",
- "man_shrugging_tone4",
- "man_shrugging_medium_dark_skin_tone",
- "man_shrugging_tone5",
- "man_shrugging_dark_skin_tone",
- "person_pouting",
- "person_with_pouting_face",
- "person_pouting_tone1",
- "person_with_pouting_face_tone1",
- "person_pouting_tone2",
- "person_with_pouting_face_tone2",
- "person_pouting_tone3",
- "person_with_pouting_face_tone3",
- "person_pouting_tone4",
- "person_with_pouting_face_tone4",
- "person_pouting_tone5",
- "person_with_pouting_face_tone5",
- "woman_pouting",
- "woman_pouting_tone1",
- "woman_pouting_light_skin_tone",
- "woman_pouting_tone2",
- "woman_pouting_medium_light_skin_tone",
- "woman_pouting_tone3",
- "woman_pouting_medium_skin_tone",
- "woman_pouting_tone4",
- "woman_pouting_medium_dark_skin_tone",
- "woman_pouting_tone5",
- "woman_pouting_dark_skin_tone",
- "man_pouting",
- "man_pouting_tone1",
- "man_pouting_light_skin_tone",
- "man_pouting_tone2",
- "man_pouting_medium_light_skin_tone",
- "man_pouting_tone3",
- "man_pouting_medium_skin_tone",
- "man_pouting_tone4",
- "man_pouting_medium_dark_skin_tone",
- "man_pouting_tone5",
- "man_pouting_dark_skin_tone",
- "person_frowning",
- "person_frowning_tone1",
- "person_frowning_tone2",
- "person_frowning_tone3",
- "person_frowning_tone4",
- "person_frowning_tone5",
- "woman_frowning",
- "woman_frowning_tone1",
- "woman_frowning_light_skin_tone",
- "woman_frowning_tone2",
- "woman_frowning_medium_light_skin_tone",
- "woman_frowning_tone3",
- "woman_frowning_medium_skin_tone",
- "woman_frowning_tone4",
- "woman_frowning_medium_dark_skin_tone",
- "woman_frowning_tone5",
- "woman_frowning_dark_skin_tone",
- "man_frowning",
- "man_frowning_tone1",
- "man_frowning_light_skin_tone",
- "man_frowning_tone2",
- "man_frowning_medium_light_skin_tone",
- "man_frowning_tone3",
- "man_frowning_medium_skin_tone",
- "man_frowning_tone4",
- "man_frowning_medium_dark_skin_tone",
- "man_frowning_tone5",
- "man_frowning_dark_skin_tone",
- "person_getting_haircut",
- "haircut",
- "person_getting_haircut_tone1",
- "haircut_tone1",
- "person_getting_haircut_tone2",
- "haircut_tone2",
- "person_getting_haircut_tone3",
- "haircut_tone3",
- "person_getting_haircut_tone4",
- "haircut_tone4",
- "person_getting_haircut_tone5",
- "haircut_tone5",
- "woman_getting_haircut",
- "woman_getting_haircut_tone1",
- "woman_getting_haircut_light_skin_tone",
- "woman_getting_haircut_tone2",
- "woman_getting_haircut_medium_light_skin_tone",
- "woman_getting_haircut_tone3",
- "woman_getting_haircut_medium_skin_tone",
- "woman_getting_haircut_tone4",
- "woman_getting_haircut_medium_dark_skin_tone",
- "woman_getting_haircut_tone5",
- "woman_getting_haircut_dark_skin_tone",
- "man_getting_haircut",
- "man_getting_haircut_tone1",
- "man_getting_haircut_light_skin_tone",
- "man_getting_haircut_tone2",
- "man_getting_haircut_medium_light_skin_tone",
- "man_getting_haircut_tone3",
- "man_getting_haircut_medium_skin_tone",
- "man_getting_haircut_tone4",
- "man_getting_haircut_medium_dark_skin_tone",
- "man_getting_haircut_tone5",
- "man_getting_haircut_dark_skin_tone",
- "person_getting_massage",
- "massage",
- "person_getting_massage_tone1",
- "massage_tone1",
- "person_getting_massage_tone2",
- "massage_tone2",
- "person_getting_massage_tone3",
- "massage_tone3",
- "person_getting_massage_tone4",
- "massage_tone4",
- "person_getting_massage_tone5",
- "massage_tone5",
- "woman_getting_face_massage",
- "woman_getting_face_massage_tone1",
- "woman_getting_face_massage_light_skin_tone",
- "woman_getting_face_massage_tone2",
- "woman_getting_face_massage_medium_light_skin_tone",
- "woman_getting_face_massage_tone3",
- "woman_getting_face_massage_medium_skin_tone",
- "woman_getting_face_massage_tone4",
- "woman_getting_face_massage_medium_dark_skin_tone",
- "woman_getting_face_massage_tone5",
- "woman_getting_face_massage_dark_skin_tone",
- "man_getting_face_massage",
- "man_getting_face_massage_tone1",
- "man_getting_face_massage_light_skin_tone",
- "man_getting_face_massage_tone2",
- "man_getting_face_massage_medium_light_skin_tone",
- "man_getting_face_massage_tone3",
- "man_getting_face_massage_medium_skin_tone",
- "man_getting_face_massage_tone4",
- "man_getting_face_massage_medium_dark_skin_tone",
- "man_getting_face_massage_tone5",
- "man_getting_face_massage_dark_skin_tone",
- "person_in_steamy_room",
- "person_in_steamy_room_tone1",
- "person_in_steamy_room_light_skin_tone",
- "person_in_steamy_room_tone2",
- "person_in_steamy_room_medium_light_skin_tone",
- "person_in_steamy_room_tone3",
- "person_in_steamy_room_medium_skin_tone",
- "person_in_steamy_room_tone4",
- "person_in_steamy_room_medium_dark_skin_tone",
- "person_in_steamy_room_tone5",
- "person_in_steamy_room_dark_skin_tone",
- "woman_in_steamy_room",
- "woman_in_steamy_room_tone1",
- "woman_in_steamy_room_light_skin_tone",
- "woman_in_steamy_room_tone2",
- "woman_in_steamy_room_medium_light_skin_tone",
- "woman_in_steamy_room_tone3",
- "woman_in_steamy_room_medium_skin_tone",
- "woman_in_steamy_room_tone4",
- "woman_in_steamy_room_medium_dark_skin_tone",
- "woman_in_steamy_room_tone5",
- "woman_in_steamy_room_dark_skin_tone",
- "man_in_steamy_room",
- "man_in_steamy_room_tone1",
- "man_in_steamy_room_light_skin_tone",
- "man_in_steamy_room_tone2",
- "man_in_steamy_room_medium_light_skin_tone",
- "man_in_steamy_room_tone3",
- "man_in_steamy_room_medium_skin_tone",
- "man_in_steamy_room_tone4",
- "man_in_steamy_room_medium_dark_skin_tone",
- "man_in_steamy_room_tone5",
- "man_in_steamy_room_dark_skin_tone",
- "nail_care",
- "nail_polish",
- "nail_care_tone1",
- "nail_care_tone2",
- "nail_care_tone3",
- "nail_care_tone4",
- "nail_care_tone5",
- "selfie",
- "selfie_tone1",
- "selfie_tone2",
- "selfie_tone3",
- "selfie_tone4",
- "selfie_tone5",
- "dancer",
- "woman_dancing",
- "dancer_tone1",
- "dancer_tone2",
- "dancer_tone3",
- "dancer_tone4",
- "dancer_tone5",
- "man_dancing",
- "male_dancer",
- "man_dancing_tone1",
- "male_dancer_tone1",
- "man_dancing_tone2",
- "male_dancer_tone2",
- "man_dancing_tone3",
- "male_dancer_tone3",
- "man_dancing_tone5",
- "male_dancer_tone5",
- "man_dancing_tone4",
- "male_dancer_tone4",
- "people_with_bunny_ears_partying",
- "dancers",
- "women_with_bunny_ears_partying",
- "men_with_bunny_ears_partying",
- "levitate",
- "man_in_business_suit_levitating",
- "levitate_tone1",
- "man_in_business_suit_levitating_tone1",
- "man_in_business_suit_levitating_light_skin_tone",
- "levitate_tone2",
- "man_in_business_suit_levitating_tone2",
- "man_in_business_suit_levitating_medium_light_skin_tone",
- "levitate_tone3",
- "man_in_business_suit_levitating_tone3",
- "man_in_business_suit_levitating_medium_skin_tone",
- "levitate_tone4",
- "man_in_business_suit_levitating_tone4",
- "man_in_business_suit_levitating_medium_dark_skin_tone",
- "levitate_tone5",
- "man_in_business_suit_levitating_tone5",
- "man_in_business_suit_levitating_dark_skin_tone",
- "person_in_manual_wheelchair",
- "person_in_manual_wheelchair_tone1",
- "person_in_manual_wheelchair_light_skin_tone",
- "person_in_manual_wheelchair_tone2",
- "person_in_manual_wheelchair_medium_light_skin_tone",
- "person_in_manual_wheelchair_tone3",
- "person_in_manual_wheelchair_medium_skin_tone",
- "person_in_manual_wheelchair_tone4",
- "person_in_manual_wheelchair_medium_dark_skin_tone",
- "person_in_manual_wheelchair_tone5",
- "person_in_manual_wheelchair_dark_skin_tone",
- "woman_in_manual_wheelchair",
- "woman_in_manual_wheelchair_tone1",
- "woman_in_manual_wheelchair_light_skin_tone",
- "woman_in_manual_wheelchair_tone2",
- "woman_in_manual_wheelchair_medium_light_skin_tone",
- "woman_in_manual_wheelchair_tone3",
- "woman_in_manual_wheelchair_medium_skin_tone",
- "woman_in_manual_wheelchair_tone4",
- "woman_in_manual_wheelchair_medium_dark_skin_tone",
- "woman_in_manual_wheelchair_tone5",
- "woman_in_manual_wheelchair_dark_skin_tone",
- "man_in_manual_wheelchair",
- "man_in_manual_wheelchair_tone1",
- "man_in_manual_wheelchair_light_skin_tone",
- "man_in_manual_wheelchair_tone2",
- "man_in_manual_wheelchair_medium_light_skin_tone",
- "man_in_manual_wheelchair_tone3",
- "man_in_manual_wheelchair_medium_skin_tone",
- "man_in_manual_wheelchair_tone4",
- "man_in_manual_wheelchair_medium_dark_skin_tone",
- "man_in_manual_wheelchair_tone5",
- "man_in_manual_wheelchair_dark_skin_tone",
- "person_in_motorized_wheelchair",
- "person_in_motorized_wheelchair_tone1",
- "person_in_motorized_wheelchair_light_skin_tone",
- "person_in_motorized_wheelchair_tone2",
- "person_in_motorized_wheelchair_medium_light_skin_tone",
- "person_in_motorized_wheelchair_tone3",
- "person_in_motorized_wheelchair_medium_skin_tone",
- "person_in_motorized_wheelchair_tone4",
- "person_in_motorized_wheelchair_medium_dark_skin_tone",
- "person_in_motorized_wheelchair_tone5",
- "person_in_motorized_wheelchair_dark_skin_tone",
- "woman_in_motorized_wheelchair",
- "woman_in_motorized_wheelchair_tone1",
- "woman_in_motorized_wheelchair_light_skin_tone",
- "woman_in_motorized_wheelchair_tone2",
- "woman_in_motorized_wheelchair_medium_light_skin_tone",
- "woman_in_motorized_wheelchair_tone3",
- "woman_in_motorized_wheelchair_medium_skin_tone",
- "woman_in_motorized_wheelchair_tone4",
- "woman_in_motorized_wheelchair_medium_dark_skin_tone",
- "woman_in_motorized_wheelchair_tone5",
- "woman_in_motorized_wheelchair_dark_skin_tone",
- "man_in_motorized_wheelchair",
- "man_in_motorized_wheelchair_tone1",
- "man_in_motorized_wheelchair_light_skin_tone",
- "man_in_motorized_wheelchair_tone2",
- "man_in_motorized_wheelchair_medium_light_skin_tone",
- "man_in_motorized_wheelchair_tone3",
- "man_in_motorized_wheelchair_medium_skin_tone",
- "man_in_motorized_wheelchair_tone4",
- "man_in_motorized_wheelchair_medium_dark_skin_tone",
- "man_in_motorized_wheelchair_tone5",
- "man_in_motorized_wheelchair_dark_skin_tone",
- "person_walking",
- "walking",
- "person_walking_tone1",
- "walking_tone1",
- "person_walking_tone2",
- "walking_tone2",
- "person_walking_tone3",
- "walking_tone3",
- "person_walking_tone4",
- "walking_tone4",
- "person_walking_tone5",
- "walking_tone5",
- "woman_walking",
- "woman_walking_tone1",
- "woman_walking_light_skin_tone",
- "woman_walking_tone2",
- "woman_walking_medium_light_skin_tone",
- "woman_walking_tone3",
- "woman_walking_medium_skin_tone",
- "woman_walking_tone4",
- "woman_walking_medium_dark_skin_tone",
- "woman_walking_tone5",
- "woman_walking_dark_skin_tone",
- "man_walking",
- "man_walking_tone1",
- "man_walking_light_skin_tone",
- "man_walking_tone2",
- "man_walking_medium_light_skin_tone",
- "man_walking_tone3",
- "man_walking_medium_skin_tone",
- "man_walking_tone4",
- "man_walking_medium_dark_skin_tone",
- "man_walking_tone5",
- "man_walking_dark_skin_tone",
- "person_with_probing_cane",
- "person_with_probing_cane_tone1",
- "person_with_probing_cane_light_skin_tone",
- "person_with_probing_cane_tone2",
- "person_with_probing_cane_medium_light_skin_tone",
- "person_with_probing_cane_tone3",
- "person_with_probing_cane_medium_skin_tone",
- "person_with_probing_cane_tone4",
- "person_with_probing_cane_medium_dark_skin_tone",
- "person_with_probing_cane_tone5",
- "person_with_probing_cane_dark_skin_tone",
- "woman_with_probing_cane",
- "woman_with_probing_cane_tone1",
- "woman_with_probing_cane_light_skin_tone",
- "woman_with_probing_cane_tone2",
- "woman_with_probing_cane_medium_light_skin_tone",
- "woman_with_probing_cane_tone3",
- "woman_with_probing_cane_medium_skin_tone",
- "woman_with_probing_cane_tone4",
- "woman_with_probing_cane_medium_dark_skin_tone",
- "woman_with_probing_cane_tone5",
- "woman_with_probing_cane_dark_skin_tone",
- "man_with_probing_cane",
- "man_with_probing_cane_tone1",
- "man_with_probing_cane_light_skin_tone",
- "man_with_probing_cane_tone2",
- "man_with_probing_cane_medium_light_skin_tone",
- "man_with_probing_cane_tone3",
- "man_with_probing_cane_medium_skin_tone",
- "man_with_probing_cane_tone4",
- "man_with_probing_cane_medium_dark_skin_tone",
- "man_with_probing_cane_tone5",
- "man_with_probing_cane_dark_skin_tone",
- "person_kneeling",
- "person_kneeling_tone1",
- "person_kneeling_light_skin_tone",
- "person_kneeling_tone2",
- "person_kneeling_medium_light_skin_tone",
- "person_kneeling_tone3",
- "person_kneeling_medium_skin_tone",
- "person_kneeling_tone4",
- "person_kneeling_medium_dark_skin_tone",
- "person_kneeling_tone5",
- "person_kneeling_dark_skin_tone",
- "woman_kneeling",
- "woman_kneeling_tone1",
- "woman_kneeling_light_skin_tone",
- "woman_kneeling_tone2",
- "woman_kneeling_medium_light_skin_tone",
- "woman_kneeling_tone3",
- "woman_kneeling_medium_skin_tone",
- "woman_kneeling_tone4",
- "woman_kneeling_medium_dark_skin_tone",
- "woman_kneeling_tone5",
- "woman_kneeling_dark_skin_tone",
- "man_kneeling",
- "man_kneeling_tone1",
- "man_kneeling_light_skin_tone",
- "man_kneeling_tone2",
- "man_kneeling_medium_light_skin_tone",
- "man_kneeling_tone3",
- "man_kneeling_medium_skin_tone",
- "man_kneeling_tone4",
- "man_kneeling_medium_dark_skin_tone",
- "man_kneeling_tone5",
- "man_kneeling_dark_skin_tone",
- "person_running",
- "runner",
- "person_running_tone1",
- "runner_tone1",
- "person_running_tone2",
- "runner_tone2",
- "person_running_tone3",
- "runner_tone3",
- "person_running_tone4",
- "runner_tone4",
- "person_running_tone5",
- "runner_tone5",
- "woman_running",
- "woman_running_tone1",
- "woman_running_light_skin_tone",
- "woman_running_tone2",
- "woman_running_medium_light_skin_tone",
- "woman_running_tone3",
- "woman_running_medium_skin_tone",
- "woman_running_tone4",
- "woman_running_medium_dark_skin_tone",
- "woman_running_tone5",
- "woman_running_dark_skin_tone",
- "man_running",
- "man_running_tone1",
- "man_running_light_skin_tone",
- "man_running_tone2",
- "man_running_medium_light_skin_tone",
- "man_running_tone3",
- "man_running_medium_skin_tone",
- "man_running_tone4",
- "man_running_medium_dark_skin_tone",
- "man_running_tone5",
- "man_running_dark_skin_tone",
- "person_standing",
- "person_standing_tone1",
- "person_standing_light_skin_tone",
- "person_standing_tone2",
- "person_standing_medium_light_skin_tone",
- "person_standing_tone3",
- "person_standing_medium_skin_tone",
- "person_standing_tone4",
- "person_standing_medium_dark_skin_tone",
- "person_standing_tone5",
- "person_standing_dark_skin_tone",
- "woman_standing",
- "woman_standing_tone1",
- "woman_standing_light_skin_tone",
- "woman_standing_tone2",
- "woman_standing_medium_light_skin_tone",
- "woman_standing_tone3",
- "woman_standing_medium_skin_tone",
- "woman_standing_tone4",
- "woman_standing_medium_dark_skin_tone",
- "woman_standing_tone5",
- "woman_standing_dark_skin_tone",
- "man_standing",
- "man_standing_tone1",
- "man_standing_light_skin_tone",
- "man_standing_tone2",
- "man_standing_medium_light_skin_tone",
- "man_standing_tone3",
- "man_standing_medium_skin_tone",
- "man_standing_tone4",
- "man_standing_medium_dark_skin_tone",
- "man_standing_tone5",
- "man_standing_dark_skin_tone",
- "people_holding_hands",
- "people_holding_hands_tone1",
- "people_holding_hands_light_skin_tone",
- "people_holding_hands_tone1_tone2",
- "people_holding_hands_light_skin_tone_medium_light_skin_tone",
- "people_holding_hands_tone1_tone3",
- "people_holding_hands_light_skin_tone_medium_skin_tone",
- "people_holding_hands_tone1_tone4",
- "people_holding_hands_light_skin_tone_medium_dark_skin_tone",
- "people_holding_hands_tone1_tone5",
- "people_holding_hands_light_skin_tone_dark_skin_tone",
- "people_holding_hands_tone2_tone1",
- "people_holding_hands_medium_light_skin_tone_light_skin_tone",
- "people_holding_hands_tone2",
- "people_holding_hands_medium_light_skin_tone",
- "people_holding_hands_tone2_tone3",
- "people_holding_hands_medium_light_skin_tone_medium_skin_tone",
- "people_holding_hands_tone2_tone4",
- "people_holding_hands_medium_light_skin_tone_medium_dark_skin_tone",
- "people_holding_hands_tone2_tone5",
- "people_holding_hands_medium_light_skin_tone_dark_skin_tone",
- "people_holding_hands_tone3_tone1",
- "people_holding_hands_medium_skin_tone_light_skin_tone",
- "people_holding_hands_tone3_tone2",
- "people_holding_hands_medium_skin_tone_medium_light_skin_tone",
- "people_holding_hands_tone3",
- "people_holding_hands_medium_skin_tone",
- "people_holding_hands_tone3_tone4",
- "people_holding_hands_medium_skin_tone_medium_dark_skin_tone",
- "people_holding_hands_tone3_tone5",
- "people_holding_hands_medium_skin_tone_dark_skin_tone",
- "people_holding_hands_tone4_tone1",
- "people_holding_hands_medium_dark_skin_tone_light_skin_tone",
- "people_holding_hands_tone4_tone2",
- "people_holding_hands_medium_dark_skin_tone_medium_light_skin_tone",
- "people_holding_hands_tone4_tone3",
- "people_holding_hands_medium_dark_skin_tone_medium_skin_tone",
- "people_holding_hands_tone4",
- "people_holding_hands_medium_dark_skin_tone",
- "people_holding_hands_tone4_tone5",
- "people_holding_hands_medium_dark_skin_tone_dark_skin_tone",
- "people_holding_hands_tone5_tone1",
- "people_holding_hands_dark_skin_tone_light_skin_tone",
- "people_holding_hands_tone5_tone2",
- "people_holding_hands_dark_skin_tone_medium_light_skin_tone",
- "people_holding_hands_tone5_tone3",
- "people_holding_hands_dark_skin_tone_medium_skin_tone",
- "people_holding_hands_tone5_tone4",
- "people_holding_hands_dark_skin_tone_medium_dark_skin_tone",
- "people_holding_hands_tone5",
- "people_holding_hands_dark_skin_tone",
- "couple",
- "woman_and_man_holding_hands_tone1",
- "woman_and_man_holding_hands_light_skin_tone",
- "woman_and_man_holding_hands_tone1_tone2",
- "woman_and_man_holding_hands_light_skin_tone_medium_light_skin_tone",
- "woman_and_man_holding_hands_tone1_tone3",
- "woman_and_man_holding_hands_light_skin_tone_medium_skin_tone",
- "woman_and_man_holding_hands_tone1_tone4",
- "woman_and_man_holding_hands_light_skin_tone_medium_dark_skin_tone",
- "woman_and_man_holding_hands_tone1_tone5",
- "woman_and_man_holding_hands_light_skin_tone_dark_skin_tone",
- "woman_and_man_holding_hands_tone2_tone1",
- "woman_and_man_holding_hands_medium_light_skin_tone_light_skin_tone",
- "woman_and_man_holding_hands_tone2",
- "woman_and_man_holding_hands_medium_light_skin_tone",
- "woman_and_man_holding_hands_tone2_tone3",
- "woman_and_man_holding_hands_medium_light_skin_tone_medium_skin_tone",
- "woman_and_man_holding_hands_tone2_tone4",
- "woman_and_man_holding_hands_medium_light_skin_tone_medium_dark_skin_tone",
- "woman_and_man_holding_hands_tone2_tone5",
- "woman_and_man_holding_hands_medium_light_skin_tone_dark_skin_tone",
- "woman_and_man_holding_hands_tone3_tone1",
- "woman_and_man_holding_hands_medium_skin_tone_light_skin_tone",
- "woman_and_man_holding_hands_tone3_tone2",
- "woman_and_man_holding_hands_medium_skin_tone_medium_light_skin_tone",
- "woman_and_man_holding_hands_tone3",
- "woman_and_man_holding_hands_medium_skin_tone",
- "woman_and_man_holding_hands_tone3_tone4",
- "woman_and_man_holding_hands_medium_skin_tone_medium_dark_skin_tone",
- "woman_and_man_holding_hands_tone3_tone5",
- "woman_and_man_holding_hands_medium_skin_tone_dark_skin_tone",
- "woman_and_man_holding_hands_tone4_tone1",
- "woman_and_man_holding_hands_medium_dark_skin_tone_light_skin_tone",
- "woman_and_man_holding_hands_tone4_tone2",
- "woman_and_man_holding_hands_medium_dark_skin_tone_medium_light_skin_tone",
- "woman_and_man_holding_hands_tone4_tone3",
- "woman_and_man_holding_hands_medium_dark_skin_tone_medium_skin_tone",
- "woman_and_man_holding_hands_tone4",
- "woman_and_man_holding_hands_medium_dark_skin_tone",
- "woman_and_man_holding_hands_tone4_tone5",
- "woman_and_man_holding_hands_medium_dark_skin_tone_dark_skin_tone",
- "woman_and_man_holding_hands_tone5_tone1",
- "woman_and_man_holding_hands_dark_skin_tone_light_skin_tone",
- "woman_and_man_holding_hands_tone5_tone2",
- "woman_and_man_holding_hands_dark_skin_tone_medium_light_skin_tone",
- "woman_and_man_holding_hands_tone5_tone3",
- "woman_and_man_holding_hands_dark_skin_tone_medium_skin_tone",
- "woman_and_man_holding_hands_tone5_tone4",
- "woman_and_man_holding_hands_dark_skin_tone_medium_dark_skin_tone",
- "woman_and_man_holding_hands_tone5",
- "woman_and_man_holding_hands_dark_skin_tone",
- "two_women_holding_hands",
- "women_holding_hands_tone1",
- "women_holding_hands_light_skin_tone",
- "women_holding_hands_tone1_tone2",
- "women_holding_hands_light_skin_tone_medium_light_skin_tone",
- "women_holding_hands_tone1_tone3",
- "women_holding_hands_light_skin_tone_medium_skin_tone",
- "women_holding_hands_tone1_tone4",
- "women_holding_hands_light_skin_tone_medium_dark_skin_tone",
- "women_holding_hands_tone1_tone5",
- "women_holding_hands_light_skin_tone_dark_skin_tone",
- "women_holding_hands_tone2_tone1",
- "women_holding_hands_medium_light_skin_tone_light_skin_tone",
- "women_holding_hands_tone2",
- "women_holding_hands_medium_light_skin_tone",
- "women_holding_hands_tone2_tone3",
- "women_holding_hands_medium_light_skin_tone_medium_skin_tone",
- "women_holding_hands_tone2_tone4",
- "women_holding_hands_medium_light_skin_tone_medium_dark_skin_tone",
- "women_holding_hands_tone2_tone5",
- "women_holding_hands_medium_light_skin_tone_dark_skin_tone",
- "women_holding_hands_tone3_tone1",
- "women_holding_hands_medium_skin_tone_light_skin_tone",
- "women_holding_hands_tone3_tone2",
- "women_holding_hands_medium_skin_tone_medium_light_skin_tone",
- "women_holding_hands_tone3",
- "women_holding_hands_medium_skin_tone",
- "women_holding_hands_tone3_tone4",
- "women_holding_hands_medium_skin_tone_medium_dark_skin_tone",
- "women_holding_hands_tone3_tone5",
- "women_holding_hands_medium_skin_tone_dark_skin_tone",
- "women_holding_hands_tone4_tone1",
- "women_holding_hands_medium_dark_skin_tone_light_skin_tone",
- "women_holding_hands_tone4_tone2",
- "women_holding_hands_medium_dark_skin_tone_medium_light_skin_tone",
- "women_holding_hands_tone4_tone3",
- "women_holding_hands_medium_dark_skin_tone_medium_skin_tone",
- "women_holding_hands_tone4",
- "women_holding_hands_medium_dark_skin_tone",
- "women_holding_hands_tone4_tone5",
- "women_holding_hands_medium_dark_skin_tone_dark_skin_tone",
- "women_holding_hands_tone5_tone1",
- "women_holding_hands_dark_skin_tone_light_skin_tone",
- "women_holding_hands_tone5_tone2",
- "women_holding_hands_dark_skin_tone_medium_light_skin_tone",
- "women_holding_hands_tone5_tone3",
- "women_holding_hands_dark_skin_tone_medium_skin_tone",
- "women_holding_hands_tone5_tone4",
- "women_holding_hands_dark_skin_tone_medium_dark_skin_tone",
- "women_holding_hands_tone5",
- "women_holding_hands_dark_skin_tone",
- "two_men_holding_hands",
- "men_holding_hands_tone1",
- "men_holding_hands_light_skin_tone",
- "men_holding_hands_tone1_tone2",
- "men_holding_hands_light_skin_tone_medium_light_skin_tone",
- "men_holding_hands_tone1_tone3",
- "men_holding_hands_light_skin_tone_medium_skin_tone",
- "men_holding_hands_tone1_tone4",
- "men_holding_hands_light_skin_tone_medium_dark_skin_tone",
- "men_holding_hands_tone1_tone5",
- "men_holding_hands_light_skin_tone_dark_skin_tone",
- "men_holding_hands_tone2_tone1",
- "men_holding_hands_medium_light_skin_tone_light_skin_tone",
- "men_holding_hands_tone2",
- "men_holding_hands_medium_light_skin_tone",
- "men_holding_hands_tone2_tone3",
- "men_holding_hands_medium_light_skin_tone_medium_skin_tone",
- "men_holding_hands_tone2_tone4",
- "men_holding_hands_medium_light_skin_tone_medium_dark_skin_tone",
- "men_holding_hands_tone2_tone5",
- "men_holding_hands_medium_light_skin_tone_dark_skin_tone",
- "men_holding_hands_tone3_tone1",
- "men_holding_hands_medium_skin_tone_light_skin_tone",
- "men_holding_hands_tone3_tone2",
- "men_holding_hands_medium_skin_tone_medium_light_skin_tone",
- "men_holding_hands_tone3",
- "men_holding_hands_medium_skin_tone",
- "men_holding_hands_tone3_tone4",
- "men_holding_hands_medium_skin_tone_medium_dark_skin_tone",
- "men_holding_hands_tone3_tone5",
- "men_holding_hands_medium_skin_tone_dark_skin_tone",
- "men_holding_hands_tone4_tone1",
- "men_holding_hands_medium_dark_skin_tone_light_skin_tone",
- "men_holding_hands_tone4_tone2",
- "men_holding_hands_medium_dark_skin_tone_medium_light_skin_tone",
- "men_holding_hands_tone4_tone3",
- "men_holding_hands_medium_dark_skin_tone_medium_skin_tone",
- "men_holding_hands_tone4",
- "men_holding_hands_medium_dark_skin_tone",
- "men_holding_hands_tone4_tone5",
- "men_holding_hands_medium_dark_skin_tone_dark_skin_tone",
- "men_holding_hands_tone5_tone1",
- "men_holding_hands_dark_skin_tone_light_skin_tone",
- "men_holding_hands_tone5_tone2",
- "men_holding_hands_dark_skin_tone_medium_light_skin_tone",
- "men_holding_hands_tone5_tone3",
- "men_holding_hands_dark_skin_tone_medium_skin_tone",
- "men_holding_hands_tone5_tone4",
- "men_holding_hands_dark_skin_tone_medium_dark_skin_tone",
- "men_holding_hands_tone5",
- "men_holding_hands_dark_skin_tone",
- "couple_with_heart",
- "couple_with_heart_tone1",
- "couple_with_heart_light_skin_tone",
- "couple_with_heart_person_person_tone1_tone2",
- "couple_with_heart_person_person_light_skin_tone_medium_light_skin_tone",
- "couple_with_heart_person_person_tone1_tone3",
- "couple_with_heart_person_person_light_skin_tone_medium_skin_tone",
- "couple_with_heart_person_person_tone1_tone4",
- "couple_with_heart_person_person_light_skin_tone_medium_dark_skin_tone",
- "couple_with_heart_person_person_tone1_tone5",
- "couple_with_heart_person_person_light_skin_tone_dark_skin_tone",
- "couple_with_heart_person_person_tone2_tone1",
- "couple_with_heart_person_person_medium_light_skin_tone_light_skin_tone",
- "couple_with_heart_tone2",
- "couple_with_heart_medium_light_skin_tone",
- "couple_with_heart_person_person_tone2_tone3",
- "couple_with_heart_person_person_medium_light_skin_tone_medium_skin_tone",
- "couple_with_heart_person_person_tone2_tone4",
- "couple_with_heart_person_person_medium_light_skin_tone_medium_dark_skin_tone",
- "couple_with_heart_person_person_tone2_tone5",
- "couple_with_heart_person_person_medium_light_skin_tone_dark_skin_tone",
- "couple_with_heart_person_person_tone3_tone1",
- "couple_with_heart_person_person_medium_skin_tone_light_skin_tone",
- "couple_with_heart_person_person_tone3_tone2",
- "couple_with_heart_person_person_medium_skin_tone_medium_light_skin_tone",
- "couple_with_heart_tone3",
- "couple_with_heart_medium_skin_tone",
- "couple_with_heart_person_person_tone3_tone4",
- "couple_with_heart_person_person_medium_skin_tone_medium_dark_skin_tone",
- "couple_with_heart_person_person_tone3_tone5",
- "couple_with_heart_person_person_medium_skin_tone_dark_skin_tone",
- "couple_with_heart_person_person_tone4_tone1",
- "couple_with_heart_person_person_medium_dark_skin_tone_light_skin_tone",
- "couple_with_heart_person_person_tone4_tone2",
- "couple_with_heart_person_person_medium_dark_skin_tone_medium_light_skin_tone",
- "couple_with_heart_person_person_tone4_tone3",
- "couple_with_heart_person_person_medium_dark_skin_tone_medium_skin_tone",
- "couple_with_heart_tone4",
- "couple_with_heart_medium_dark_skin_tone",
- "couple_with_heart_person_person_tone4_tone5",
- "couple_with_heart_person_person_medium_dark_skin_tone_dark_skin_tone",
- "couple_with_heart_person_person_tone5_tone1",
- "couple_with_heart_person_person_dark_skin_tone_light_skin_tone",
- "couple_with_heart_person_person_tone5_tone2",
- "couple_with_heart_person_person_dark_skin_tone_medium_light_skin_tone",
- "couple_with_heart_person_person_tone5_tone3",
- "couple_with_heart_person_person_dark_skin_tone_medium_skin_tone",
- "couple_with_heart_person_person_tone5_tone4",
- "couple_with_heart_person_person_dark_skin_tone_medium_dark_skin_tone",
- "couple_with_heart_tone5",
- "couple_with_heart_dark_skin_tone",
- "couple_with_heart_woman_man",
- "couple_with_heart_woman_man_tone1",
- "couple_with_heart_woman_man_light_skin_tone",
- "couple_with_heart_woman_man_tone1_tone2",
- "couple_with_heart_woman_man_light_skin_tone_medium_light_skin_tone",
- "couple_with_heart_woman_man_tone1_tone3",
- "couple_with_heart_woman_man_light_skin_tone_medium_skin_tone",
- "couple_with_heart_woman_man_tone1_tone4",
- "couple_with_heart_woman_man_light_skin_tone_medium_dark_skin_tone",
- "couple_with_heart_woman_man_tone1_tone5",
- "couple_with_heart_woman_man_light_skin_tone_dark_skin_tone",
- "couple_with_heart_woman_man_tone2_tone1",
- "couple_with_heart_woman_man_medium_light_skin_tone_light_skin_tone",
- "couple_with_heart_woman_man_tone2",
- "couple_with_heart_woman_man_medium_light_skin_tone",
- "couple_with_heart_woman_man_tone2_tone3",
- "couple_with_heart_woman_man_medium_light_skin_tone_medium_skin_tone",
- "couple_with_heart_woman_man_tone2_tone4",
- "couple_with_heart_woman_man_medium_light_skin_tone_medium_dark_skin_tone",
- "couple_with_heart_woman_man_tone2_tone5",
- "couple_with_heart_woman_man_medium_light_skin_tone_dark_skin_tone",
- "couple_with_heart_woman_man_tone3_tone1",
- "couple_with_heart_woman_man_medium_skin_tone_light_skin_tone",
- "couple_with_heart_woman_man_tone3_tone2",
- "couple_with_heart_woman_man_medium_skin_tone_medium_light_skin_tone",
- "couple_with_heart_woman_man_tone3",
- "couple_with_heart_woman_man_medium_skin_tone",
- "couple_with_heart_woman_man_tone3_tone4",
- "couple_with_heart_woman_man_medium_skin_tone_medium_dark_skin_tone",
- "couple_with_heart_woman_man_tone3_tone5",
- "couple_with_heart_woman_man_medium_skin_tone_dark_skin_tone",
- "couple_with_heart_woman_man_tone4_tone1",
- "couple_with_heart_woman_man_medium_dark_skin_tone_light_skin_tone",
- "couple_with_heart_woman_man_tone4_tone2",
- "couple_with_heart_woman_man_medium_dark_skin_tone_medium_light_skin_tone",
- "couple_with_heart_woman_man_tone4_tone3",
- "couple_with_heart_woman_man_medium_dark_skin_tone_medium_skin_tone",
- "couple_with_heart_woman_man_tone4",
- "couple_with_heart_woman_man_medium_dark_skin_tone",
- "couple_with_heart_woman_man_tone4_tone5",
- "couple_with_heart_woman_man_medium_dark_skin_tone_dark_skin_tone",
- "couple_with_heart_woman_man_tone5_tone1",
- "couple_with_heart_woman_man_dark_skin_tone_light_skin_tone",
- "couple_with_heart_woman_man_tone5_tone2",
- "couple_with_heart_woman_man_dark_skin_tone_medium_light_skin_tone",
- "couple_with_heart_woman_man_tone5_tone3",
- "couple_with_heart_woman_man_dark_skin_tone_medium_skin_tone",
- "couple_with_heart_woman_man_tone5_tone4",
- "couple_with_heart_woman_man_dark_skin_tone_medium_dark_skin_tone",
- "couple_with_heart_woman_man_tone5",
- "couple_with_heart_woman_man_dark_skin_tone",
- "couple_ww",
- "couple_with_heart_ww",
- "couple_with_heart_woman_woman_tone1",
- "couple_with_heart_woman_woman_light_skin_tone",
- "couple_with_heart_woman_woman_tone1_tone2",
- "couple_with_heart_woman_woman_light_skin_tone_medium_light_skin_tone",
- "couple_with_heart_woman_woman_tone1_tone3",
- "couple_with_heart_woman_woman_light_skin_tone_medium_skin_tone",
- "couple_with_heart_woman_woman_tone1_tone4",
- "couple_with_heart_woman_woman_light_skin_tone_medium_dark_skin_tone",
- "couple_with_heart_woman_woman_tone1_tone5",
- "couple_with_heart_woman_woman_light_skin_tone_dark_skin_tone",
- "couple_with_heart_woman_woman_tone2_tone1",
- "couple_with_heart_woman_woman_medium_light_skin_tone_light_skin_tone",
- "couple_with_heart_woman_woman_tone2",
- "couple_with_heart_woman_woman_medium_light_skin_tone",
- "couple_with_heart_woman_woman_tone2_tone3",
- "couple_with_heart_woman_woman_medium_light_skin_tone_medium_skin_tone",
- "couple_with_heart_woman_woman_tone2_tone4",
- "couple_with_heart_woman_woman_medium_light_skin_tone_medium_dark_skin_tone",
- "couple_with_heart_woman_woman_tone2_tone5",
- "couple_with_heart_woman_woman_medium_light_skin_tone_dark_skin_tone",
- "couple_with_heart_woman_woman_tone3_tone1",
- "couple_with_heart_woman_woman_medium_skin_tone_light_skin_tone",
- "couple_with_heart_woman_woman_tone3_tone2",
- "couple_with_heart_woman_woman_medium_skin_tone_medium_light_skin_tone",
- "couple_with_heart_woman_woman_tone3",
- "couple_with_heart_woman_woman_medium_skin_tone",
- "couple_with_heart_woman_woman_tone3_tone4",
- "couple_with_heart_woman_woman_medium_skin_tone_medium_dark_skin_tone",
- "couple_with_heart_woman_woman_tone3_tone5",
- "couple_with_heart_woman_woman_medium_skin_tone_dark_skin_tone",
- "couple_with_heart_woman_woman_tone4_tone1",
- "couple_with_heart_woman_woman_medium_dark_skin_tone_light_skin_tone",
- "couple_with_heart_woman_woman_tone4_tone2",
- "couple_with_heart_woman_woman_medium_dark_skin_tone_medium_light_skin_tone",
- "couple_with_heart_woman_woman_tone4_tone3",
- "couple_with_heart_woman_woman_medium_dark_skin_tone_medium_skin_tone",
- "couple_with_heart_woman_woman_tone4",
- "couple_with_heart_woman_woman_medium_dark_skin_tone",
- "couple_with_heart_woman_woman_tone4_tone5",
- "couple_with_heart_woman_woman_medium_dark_skin_tone_dark_skin_tone",
- "couple_with_heart_woman_woman_tone5_tone1",
- "couple_with_heart_woman_woman_dark_skin_tone_light_skin_tone",
- "couple_with_heart_woman_woman_tone5_tone2",
- "couple_with_heart_woman_woman_dark_skin_tone_medium_light_skin_tone",
- "couple_with_heart_woman_woman_tone5_tone3",
- "couple_with_heart_woman_woman_dark_skin_tone_medium_skin_tone",
- "couple_with_heart_woman_woman_tone5_tone4",
- "couple_with_heart_woman_woman_dark_skin_tone_medium_dark_skin_tone",
- "couple_with_heart_woman_woman_tone5",
- "couple_with_heart_woman_woman_dark_skin_tone",
- "couple_mm",
- "couple_with_heart_mm",
- "couple_with_heart_man_man_tone1",
- "couple_with_heart_man_man_light_skin_tone",
- "couple_with_heart_man_man_tone1_tone2",
- "couple_with_heart_man_man_light_skin_tone_medium_light_skin_tone",
- "couple_with_heart_man_man_tone1_tone3",
- "couple_with_heart_man_man_light_skin_tone_medium_skin_tone",
- "couple_with_heart_man_man_tone1_tone4",
- "couple_with_heart_man_man_light_skin_tone_medium_dark_skin_tone",
- "couple_with_heart_man_man_tone1_tone5",
- "couple_with_heart_man_man_light_skin_tone_dark_skin_tone",
- "couple_with_heart_man_man_tone2_tone1",
- "couple_with_heart_man_man_medium_light_skin_tone_light_skin_tone",
- "couple_with_heart_man_man_tone2",
- "couple_with_heart_man_man_medium_light_skin_tone",
- "couple_with_heart_man_man_tone2_tone3",
- "couple_with_heart_man_man_medium_light_skin_tone_medium_skin_tone",
- "couple_with_heart_man_man_tone2_tone4",
- "couple_with_heart_man_man_medium_light_skin_tone_medium_dark_skin_tone",
- "couple_with_heart_man_man_tone2_tone5",
- "couple_with_heart_man_man_medium_light_skin_tone_dark_skin_tone",
- "couple_with_heart_man_man_tone3_tone1",
- "couple_with_heart_man_man_medium_skin_tone_light_skin_tone",
- "couple_with_heart_man_man_tone3_tone2",
- "couple_with_heart_man_man_medium_skin_tone_medium_light_skin_tone",
- "couple_with_heart_man_man_tone3",
- "couple_with_heart_man_man_medium_skin_tone",
- "couple_with_heart_man_man_tone3_tone4",
- "couple_with_heart_man_man_medium_skin_tone_medium_dark_skin_tone",
- "couple_with_heart_man_man_tone3_tone5",
- "couple_with_heart_man_man_medium_skin_tone_dark_skin_tone",
- "couple_with_heart_man_man_tone4_tone1",
- "couple_with_heart_man_man_medium_dark_skin_tone_light_skin_tone",
- "couple_with_heart_man_man_tone4_tone2",
- "couple_with_heart_man_man_medium_dark_skin_tone_medium_light_skin_tone",
- "couple_with_heart_man_man_tone4_tone3",
- "couple_with_heart_man_man_medium_dark_skin_tone_medium_skin_tone",
- "couple_with_heart_man_man_tone4",
- "couple_with_heart_man_man_medium_dark_skin_tone",
- "couple_with_heart_man_man_tone4_tone5",
- "couple_with_heart_man_man_medium_dark_skin_tone_dark_skin_tone",
- "couple_with_heart_man_man_tone5_tone1",
- "couple_with_heart_man_man_dark_skin_tone_light_skin_tone",
- "couple_with_heart_man_man_tone5_tone2",
- "couple_with_heart_man_man_dark_skin_tone_medium_light_skin_tone",
- "couple_with_heart_man_man_tone5_tone3",
- "couple_with_heart_man_man_dark_skin_tone_medium_skin_tone",
- "couple_with_heart_man_man_tone5_tone4",
- "couple_with_heart_man_man_dark_skin_tone_medium_dark_skin_tone",
- "couple_with_heart_man_man_tone5",
- "couple_with_heart_man_man_dark_skin_tone",
- "couplekiss",
- "kiss_tone1",
- "kiss_light_skin_tone",
- "kiss_person_person_tone1_tone2",
- "kiss_person_person_light_skin_tone_medium_light_skin_tone",
- "kiss_person_person_tone1_tone3",
- "kiss_person_person_light_skin_tone_medium_skin_tone",
- "kiss_person_person_tone1_tone4",
- "kiss_person_person_light_skin_tone_medium_dark_skin_tone",
- "kiss_person_person_tone1_tone5",
- "kiss_person_person_light_skin_tone_dark_skin_tone",
- "kiss_person_person_tone2_tone1",
- "kiss_person_person_medium_light_skin_tone_light_skin_tone",
- "kiss_tone2",
- "kiss_medium_light_skin_tone",
- "kiss_person_person_tone2_tone3",
- "kiss_person_person_medium_light_skin_tone_medium_skin_tone",
- "kiss_person_person_tone2_tone4",
- "kiss_person_person_medium_light_skin_tone_medium_dark_skin_tone",
- "kiss_person_person_tone2_tone5",
- "kiss_person_person_medium_light_skin_tone_dark_skin_tone",
- "kiss_person_person_tone3_tone1",
- "kiss_person_person_medium_skin_tone_light_skin_tone",
- "kiss_person_person_tone3_tone2",
- "kiss_person_person_medium_skin_tone_medium_light_skin_tone",
- "kiss_tone3",
- "kiss_medium_skin_tone",
- "kiss_person_person_tone3_tone4",
- "kiss_person_person_medium_skin_tone_medium_dark_skin_tone",
- "kiss_person_person_tone3_tone5",
- "kiss_person_person_medium_skin_tone_dark_skin_tone",
- "kiss_person_person_tone4_tone1",
- "kiss_person_person_medium_dark_skin_tone_light_skin_tone",
- "kiss_person_person_tone4_tone2",
- "kiss_person_person_medium_dark_skin_tone_medium_light_skin_tone",
- "kiss_person_person_tone4_tone3",
- "kiss_person_person_medium_dark_skin_tone_medium_skin_tone",
- "kiss_tone4",
- "kiss_medium_dark_skin_tone",
- "kiss_person_person_tone4_tone5",
- "kiss_person_person_medium_dark_skin_tone_dark_skin_tone",
- "kiss_person_person_tone5_tone1",
- "kiss_person_person_dark_skin_tone_light_skin_tone",
- "kiss_person_person_tone5_tone2",
- "kiss_person_person_dark_skin_tone_medium_light_skin_tone",
- "kiss_person_person_tone5_tone3",
- "kiss_person_person_dark_skin_tone_medium_skin_tone",
- "kiss_person_person_tone5_tone4",
- "kiss_person_person_dark_skin_tone_medium_dark_skin_tone",
- "kiss_tone5",
- "kiss_dark_skin_tone",
- "kiss_woman_man",
- "kiss_woman_man_tone1",
- "kiss_woman_man_light_skin_tone",
- "kiss_woman_man_tone1_tone2",
- "kiss_woman_man_light_skin_tone_medium_light_skin_tone",
- "kiss_woman_man_tone1_tone3",
- "kiss_woman_man_light_skin_tone_medium_skin_tone",
- "kiss_woman_man_tone1_tone4",
- "kiss_woman_man_light_skin_tone_medium_dark_skin_tone",
- "kiss_woman_man_tone1_tone5",
- "kiss_woman_man_light_skin_tone_dark_skin_tone",
- "kiss_woman_man_tone2_tone1",
- "kiss_woman_man_medium_light_skin_tone_light_skin_tone",
- "kiss_woman_man_tone2",
- "kiss_woman_man_medium_light_skin_tone",
- "kiss_woman_man_tone2_tone3",
- "kiss_woman_man_medium_light_skin_tone_medium_skin_tone",
- "kiss_woman_man_tone2_tone4",
- "kiss_woman_man_medium_light_skin_tone_medium_dark_skin_tone",
- "kiss_woman_man_tone2_tone5",
- "kiss_woman_man_medium_light_skin_tone_dark_skin_tone",
- "kiss_woman_man_tone3_tone1",
- "kiss_woman_man_medium_skin_tone_light_skin_tone",
- "kiss_woman_man_tone3_tone2",
- "kiss_woman_man_medium_skin_tone_medium_light_skin_tone",
- "kiss_woman_man_tone3",
- "kiss_woman_man_medium_skin_tone",
- "kiss_woman_man_tone3_tone4",
- "kiss_woman_man_medium_skin_tone_medium_dark_skin_tone",
- "kiss_woman_man_tone3_tone5",
- "kiss_woman_man_medium_skin_tone_dark_skin_tone",
- "kiss_woman_man_tone4_tone1",
- "kiss_woman_man_medium_dark_skin_tone_light_skin_tone",
- "kiss_woman_man_tone4_tone2",
- "kiss_woman_man_medium_dark_skin_tone_medium_light_skin_tone",
- "kiss_woman_man_tone4_tone3",
- "kiss_woman_man_medium_dark_skin_tone_medium_skin_tone",
- "kiss_woman_man_tone4",
- "kiss_woman_man_medium_dark_skin_tone",
- "kiss_woman_man_tone4_tone5",
- "kiss_woman_man_medium_dark_skin_tone_dark_skin_tone",
- "kiss_woman_man_tone5_tone1",
- "kiss_woman_man_dark_skin_tone_light_skin_tone",
- "kiss_woman_man_tone5_tone2",
- "kiss_woman_man_dark_skin_tone_medium_light_skin_tone",
- "kiss_woman_man_tone5_tone3",
- "kiss_woman_man_dark_skin_tone_medium_skin_tone",
- "kiss_woman_man_tone5_tone4",
- "kiss_woman_man_dark_skin_tone_medium_dark_skin_tone",
- "kiss_woman_man_tone5",
- "kiss_woman_man_dark_skin_tone",
- "kiss_ww",
- "couplekiss_ww",
- "kiss_woman_woman_tone1",
- "kiss_woman_woman_light_skin_tone",
- "kiss_woman_woman_tone1_tone2",
- "kiss_woman_woman_light_skin_tone_medium_light_skin_tone",
- "kiss_woman_woman_tone1_tone3",
- "kiss_woman_woman_light_skin_tone_medium_skin_tone",
- "kiss_woman_woman_tone1_tone4",
- "kiss_woman_woman_light_skin_tone_medium_dark_skin_tone",
- "kiss_woman_woman_tone1_tone5",
- "kiss_woman_woman_light_skin_tone_dark_skin_tone",
- "kiss_woman_woman_tone2_tone1",
- "kiss_woman_woman_medium_light_skin_tone_light_skin_tone",
- "kiss_woman_woman_tone2",
- "kiss_woman_woman_medium_light_skin_tone",
- "kiss_woman_woman_tone2_tone3",
- "kiss_woman_woman_medium_light_skin_tone_medium_skin_tone",
- "kiss_woman_woman_tone2_tone4",
- "kiss_woman_woman_medium_light_skin_tone_medium_dark_skin_tone",
- "kiss_woman_woman_tone2_tone5",
- "kiss_woman_woman_medium_light_skin_tone_dark_skin_tone",
- "kiss_woman_woman_tone3_tone1",
- "kiss_woman_woman_medium_skin_tone_light_skin_tone",
- "kiss_woman_woman_tone3_tone2",
- "kiss_woman_woman_medium_skin_tone_medium_light_skin_tone",
- "kiss_woman_woman_tone3",
- "kiss_woman_woman_medium_skin_tone",
- "kiss_woman_woman_tone3_tone4",
- "kiss_woman_woman_medium_skin_tone_medium_dark_skin_tone",
- "kiss_woman_woman_tone3_tone5",
- "kiss_woman_woman_medium_skin_tone_dark_skin_tone",
- "kiss_woman_woman_tone4_tone1",
- "kiss_woman_woman_medium_dark_skin_tone_light_skin_tone",
- "kiss_woman_woman_tone4_tone2",
- "kiss_woman_woman_medium_dark_skin_tone_medium_light_skin_tone",
- "kiss_woman_woman_tone4_tone3",
- "kiss_woman_woman_medium_dark_skin_tone_medium_skin_tone",
- "kiss_woman_woman_tone4",
- "kiss_woman_woman_medium_dark_skin_tone",
- "kiss_woman_woman_tone4_tone5",
- "kiss_woman_woman_medium_dark_skin_tone_dark_skin_tone",
- "kiss_woman_woman_tone5_tone1",
- "kiss_woman_woman_dark_skin_tone_light_skin_tone",
- "kiss_woman_woman_tone5_tone2",
- "kiss_woman_woman_dark_skin_tone_medium_light_skin_tone",
- "kiss_woman_woman_tone5_tone3",
- "kiss_woman_woman_dark_skin_tone_medium_skin_tone",
- "kiss_woman_woman_tone5_tone4",
- "kiss_woman_woman_dark_skin_tone_medium_dark_skin_tone",
- "kiss_woman_woman_tone5",
- "kiss_woman_woman_dark_skin_tone",
- "kiss_mm",
- "couplekiss_mm",
- "kiss_man_man",
- "kiss_man_man_tone1",
- "kiss_man_man_light_skin_tone",
- "kiss_man_man_tone1_tone2",
- "kiss_man_man_light_skin_tone_medium_light_skin_tone",
- "kiss_man_man_tone1_tone3",
- "kiss_man_man_light_skin_tone_medium_skin_tone",
- "kiss_man_man_tone1_tone4",
- "kiss_man_man_light_skin_tone_medium_dark_skin_tone",
- "kiss_man_man_tone1_tone5",
- "kiss_man_man_light_skin_tone_dark_skin_tone",
- "kiss_man_man_tone2_tone1",
- "kiss_man_man_medium_light_skin_tone_light_skin_tone",
- "kiss_man_man_tone2",
- "kiss_man_man_medium_light_skin_tone",
- "kiss_man_man_tone2_tone3",
- "kiss_man_man_medium_light_skin_tone_medium_skin_tone",
- "kiss_man_man_tone2_tone4",
- "kiss_man_man_medium_light_skin_tone_medium_dark_skin_tone",
- "kiss_man_man_tone2_tone5",
- "kiss_man_man_medium_light_skin_tone_dark_skin_tone",
- "kiss_man_man_tone3_tone1",
- "kiss_man_man_medium_skin_tone_light_skin_tone",
- "kiss_man_man_tone3_tone2",
- "kiss_man_man_medium_skin_tone_medium_light_skin_tone",
- "kiss_man_man_tone3",
- "kiss_man_man_medium_skin_tone",
- "kiss_man_man_tone3_tone4",
- "kiss_man_man_medium_skin_tone_medium_dark_skin_tone",
- "kiss_man_man_tone3_tone5",
- "kiss_man_man_medium_skin_tone_dark_skin_tone",
- "kiss_man_man_tone4_tone1",
- "kiss_man_man_medium_dark_skin_tone_light_skin_tone",
- "kiss_man_man_tone4_tone2",
- "kiss_man_man_medium_dark_skin_tone_medium_light_skin_tone",
- "kiss_man_man_tone4_tone3",
- "kiss_man_man_medium_dark_skin_tone_medium_skin_tone",
- "kiss_man_man_tone4",
- "kiss_man_man_medium_dark_skin_tone",
- "kiss_man_man_tone4_tone5",
- "kiss_man_man_medium_dark_skin_tone_dark_skin_tone",
- "kiss_man_man_tone5_tone1",
- "kiss_man_man_dark_skin_tone_light_skin_tone",
- "kiss_man_man_tone5_tone2",
- "kiss_man_man_dark_skin_tone_medium_light_skin_tone",
- "kiss_man_man_tone5_tone3",
- "kiss_man_man_dark_skin_tone_medium_skin_tone",
- "kiss_man_man_tone5_tone4",
- "kiss_man_man_dark_skin_tone_medium_dark_skin_tone",
- "kiss_man_man_tone5",
- "kiss_man_man_dark_skin_tone",
- "family",
- "family_man_woman_boy",
- "family_mwg",
- "family_mwgb",
- "family_mwbb",
- "family_mwgg",
- "family_wwb",
- "family_wwg",
- "family_wwgb",
- "family_wwbb",
- "family_wwgg",
- "family_mmb",
- "family_mmg",
- "family_mmgb",
- "family_mmbb",
- "family_mmgg",
- "family_woman_boy",
- "family_woman_girl",
- "family_woman_girl_boy",
- "family_woman_boy_boy",
- "family_woman_girl_girl",
- "family_man_boy",
- "family_man_girl",
- "family_man_girl_boy",
- "family_man_boy_boy",
- "family_man_girl_girl",
- "knot",
- "yarn",
- "thread",
- "sewing_needle",
- "coat",
- "lab_coat",
- "safety_vest",
- "womans_clothes",
- "shirt",
- "t_shirt",
- "jeans",
- "briefs",
- "shorts",
- "necktie",
- "dress",
- "bikini",
- "one_piece_swimsuit",
- "kimono",
- "sari",
- "thong_sandal",
- "womans_flat_shoe",
- "flat_shoe",
- "high_heel",
- "sandal",
- "womans_sandal",
- "boot",
- "womans_boot",
- "mans_shoe",
- "athletic_shoe",
- "running_shoe",
- "hiking_boot",
- "socks",
- "gloves",
- "scarf",
- "tophat",
- "top_hat",
- "billed_cap",
- "womans_hat",
- "mortar_board",
- "helmet_with_cross",
- "helmet_with_white_cross",
- "military_helmet",
- "crown",
- "ring",
- "pouch",
- "clutch_bag",
- "purse",
- "handbag",
- "briefcase",
- "school_satchel",
- "backpack",
- "luggage",
- "eyeglasses",
- "glasses",
- "dark_sunglasses",
- "goggles",
- "closed_umbrella",
- "pink_heart",
- "heart",
- "red_heart",
- "orange_heart",
- "yellow_heart",
- "green_heart",
- "light_blue_heart",
- "blue_heart",
- "purple_heart",
- "black_heart",
- "grey_heart",
- "white_heart",
- "brown_heart",
- "broken_heart",
- "heart_exclamation",
- "heavy_heart_exclamation_mark_ornament",
- "two_hearts",
- "revolving_hearts",
- "heartbeat",
- "beating_heart",
- "heartpulse",
- "growing_heart",
- "sparkling_heart",
- "cupid",
- "gift_heart",
- "mending_heart",
- "heart_on_fire",
- "heart_decoration",
- "peace",
- "peace_symbol",
- "cross",
- "latin_cross",
- "star_and_crescent",
- "om_symbol",
- "wheel_of_dharma",
- "khanda",
- "star_of_david",
- "six_pointed_star",
- "menorah",
- "yin_yang",
- "orthodox_cross",
- "place_of_worship",
- "worship_symbol",
- "ophiuchus",
- "aries",
- "taurus",
- "gemini",
- "cancer",
- "leo",
- "virgo",
- "libra",
- "scorpius",
- "scorpio",
- "sagittarius",
- "capricorn",
- "aquarius",
- "pisces",
- "id",
- "atom",
- "atom_symbol",
- "accept",
- "radioactive",
- "radioactive_sign",
- "biohazard",
- "biohazard_sign",
- "mobile_phone_off",
- "vibration_mode",
- "u6709",
- "u7121",
- "u7533",
- "u55b6",
- "u6708",
- "eight_pointed_black_star",
- "vs",
- "white_flower",
- "ideograph_advantage",
- "secret",
- "congratulations",
- "u5408",
- "u6e80",
- "u5272",
- "u7981",
- "a",
- "b",
- "ab",
- "cl",
- "o2",
- "sos",
- "x",
- "cross_mark",
- "o",
- "octagonal_sign",
- "stop_sign",
- "no_entry",
- "name_badge",
- "no_entry_sign",
- "prohibited",
- "anger",
- "hotsprings",
- "hot_springs",
- "no_pedestrians",
- "do_not_litter",
- "no_littering",
- "no_bicycles",
- "non_potable_water",
- "underage",
- "no_mobile_phones",
- "no_smoking",
- "exclamation",
- "grey_exclamation",
- "question",
- "question_mark",
- "grey_question",
- "bangbang",
- "interrobang",
- "low_brightness",
- "high_brightness",
- "part_alternation_mark",
- "warning",
- "children_crossing",
- "trident",
- "fleur_de_lis",
- "beginner",
- "recycle",
- "white_check_mark",
- "u6307",
- "chart",
- "sparkle",
- "eight_spoked_asterisk",
- "negative_squared_cross_mark",
- "globe_with_meridians",
- "diamond_shape_with_a_dot_inside",
- "m",
- "circled_m",
- "cyclone",
- "zzz",
- "atm",
- "wc",
- "water_closet",
- "wheelchair",
- "parking",
- "elevator",
- "u7a7a",
- "sa",
- "passport_control",
- "customs",
- "baggage_claim",
- "left_luggage",
- "wireless",
- "mens",
- "mens_room",
- "womens",
- "womens_room",
- "baby_symbol",
- "restroom",
- "put_litter_in_its_place",
- "cinema",
- "signal_strength",
- "antenna_bars",
- "koko",
- "symbols",
- "input_symbols",
- "information_source",
- "information",
- "abc",
- "abcd",
- "capital_abcd",
- "ng",
- "ok",
- "up",
- "cool",
- "new",
- "free",
- "zero",
- "one",
- "two",
- "three",
- "four",
- "five",
- "six",
- "seven",
- "eight",
- "nine",
- "keycap_ten",
- "input_numbers",
- "hash",
- "asterisk",
- "keycap_asterisk",
- "eject",
- "eject_symbol",
- "arrow_forward",
- "pause_button",
- "double_vertical_bar",
- "play_pause",
- "stop_button",
- "record_button",
- "track_next",
- "next_track",
- "track_previous",
- "previous_track",
- "fast_forward",
- "rewind",
- "arrow_double_up",
- "arrow_double_down",
- "arrow_backward",
- "arrow_up_small",
- "arrow_down_small",
- "arrow_right",
- "right_arrow",
- "arrow_left",
- "left_arrow",
- "arrow_up",
- "up_arrow",
- "arrow_down",
- "down_arrow",
- "arrow_upper_right",
- "arrow_lower_right",
- "arrow_lower_left",
- "arrow_upper_left",
- "up_left_arrow",
- "arrow_up_down",
- "up_down_arrow",
- "left_right_arrow",
- "arrow_right_hook",
- "leftwards_arrow_with_hook",
- "arrow_heading_up",
- "arrow_heading_down",
- "twisted_rightwards_arrows",
- "repeat",
- "repeat_one",
- "arrows_counterclockwise",
- "arrows_clockwise",
- "musical_note",
- "notes",
- "musical_notes",
- "heavy_plus_sign",
- "heavy_minus_sign",
- "heavy_division_sign",
- "heavy_multiplication_x",
- "heavy_equals_sign",
- "infinity",
- "heavy_dollar_sign",
- "currency_exchange",
- "tm",
- "trade_mark",
- "copyright",
- "registered",
- "wavy_dash",
- "curly_loop",
- "loop",
- "end",
- "end_arrow",
- "back",
- "back_arrow",
- "on",
- "on_arrow",
- "top",
- "top_arrow",
- "soon",
- "soon_arrow",
- "heavy_check_mark",
- "check_mark",
- "ballot_box_with_check",
- "radio_button",
- "white_circle",
- "black_circle",
- "red_circle",
- "blue_circle",
- "brown_circle",
- "purple_circle",
- "green_circle",
- "yellow_circle",
- "orange_circle",
- "small_red_triangle",
- "small_red_triangle_down",
- "small_orange_diamond",
- "small_blue_diamond",
- "large_orange_diamond",
- "large_blue_diamond",
- "white_square_button",
- "black_square_button",
- "black_small_square",
- "white_small_square",
- "black_medium_small_square",
- "white_medium_small_square",
- "black_medium_square",
- "white_medium_square",
- "black_large_square",
- "white_large_square",
- "orange_square",
- "blue_square",
- "red_square",
- "brown_square",
- "purple_square",
- "green_square",
- "yellow_square",
- "speaker",
- "mute",
- "muted_speaker",
- "sound",
- "loud_sound",
- "bell",
- "no_bell",
- "mega",
- "megaphone",
- "loudspeaker",
- "speech_left",
- "left_speech_bubble",
- "eye_in_speech_bubble",
- "speech_balloon",
- "thought_balloon",
- "anger_right",
- "right_anger_bubble",
- "spades",
- "spade_suit",
- "clubs",
- "club_suit",
- "hearts",
- "heart_suit",
- "diamonds",
- "diamond_suit",
- "black_joker",
- "joker",
- "flower_playing_cards",
- "mahjong",
- "clock1",
- "one_oclock",
- "clock2",
- "two_oclock",
- "clock3",
- "three_oclock",
- "clock4",
- "four_oclock",
- "clock5",
- "five_oclock",
- "clock6",
- "six_oclock",
- "clock7",
- "seven_oclock",
- "clock8",
- "eight_oclock",
- "clock9",
- "nine_oclock",
- "clock10",
- "ten_oclock",
- "clock11",
- "eleven_oclock",
- "clock12",
- "twelve_oclock",
- "clock130",
- "one_thirty",
- "clock230",
- "two_thirty",
- "clock330",
- "three_thirty",
- "clock430",
- "four_thirty",
- "clock530",
- "five_thirty",
- "clock630",
- "six_thirty",
- "clock730",
- "seven_thirty",
- "clock830",
- "eight_thirty",
- "clock930",
- "nine_thirty",
- "clock1030",
- "ten_thirty",
- "clock1130",
- "eleven_thirty",
- "clock1230",
- "twelve_thirty",
- "female_sign",
- "male_sign",
- "transgender_symbol",
- "medical_symbol",
- "regional_indicator_z",
- "regional_indicator_y",
- "regional_indicator_x",
- "regional_indicator_w",
- "regional_indicator_v",
- "regional_indicator_u",
- "regional_indicator_t",
- "regional_indicator_s",
- "regional_indicator_r",
- "regional_indicator_q",
- "regional_indicator_p",
- "regional_indicator_o",
- "regional_indicator_n",
- "regional_indicator_m",
- "regional_indicator_l",
- "regional_indicator_k",
- "regional_indicator_j",
- "regional_indicator_i",
- "regional_indicator_h",
- "regional_indicator_g",
- "regional_indicator_f",
- "regional_indicator_e",
- "regional_indicator_d",
- "regional_indicator_c",
- "regional_indicator_b",
- "regional_indicator_a",
- "red_car",
- "automobile",
- "taxi",
- "blue_car",
- "pickup_truck",
- "minibus",
- "bus",
- "trolleybus",
- "race_car",
- "racing_car",
- "police_car",
- "ambulance",
- "fire_engine",
- "truck",
- "articulated_lorry",
- "tractor",
- "probing_cane",
- "manual_wheelchair",
- "motorized_wheelchair",
- "crutch",
- "scooter",
- "kick_scooter",
- "bike",
- "bicycle",
- "motor_scooter",
- "motorbike",
- "motorcycle",
- "racing_motorcycle",
- "auto_rickshaw",
- "wheel",
- "rotating_light",
- "oncoming_police_car",
- "oncoming_bus",
- "oncoming_automobile",
- "oncoming_taxi",
- "aerial_tramway",
- "mountain_cableway",
- "suspension_railway",
- "railway_car",
- "train",
- "tram_car",
- "mountain_railway",
- "monorail",
- "bullettrain_side",
- "bullettrain_front",
- "bullet_train",
- "light_rail",
- "steam_locomotive",
- "locomotive",
- "train2",
- "metro",
- "tram",
- "station",
- "airplane",
- "airplane_departure",
- "airplane_arriving",
- "airplane_small",
- "small_airplane",
- "seat",
- "satellite_orbital",
- "rocket",
- "flying_saucer",
- "helicopter",
- "canoe",
- "kayak",
- "sailboat",
- "speedboat",
- "motorboat",
- "motor_boat",
- "cruise_ship",
- "passenger_ship",
- "ferry",
- "ship",
- "ring_buoy",
- "anchor",
- "hook",
- "fuelpump",
- "fuel_pump",
- "construction",
- "vertical_traffic_light",
- "traffic_light",
- "busstop",
- "bus_stop",
- "map",
- "world_map",
- "moyai",
- "moai",
- "statue_of_liberty",
- "tokyo_tower",
- "european_castle",
- "castle",
- "japanese_castle",
- "stadium",
- "ferris_wheel",
- "roller_coaster",
- "carousel_horse",
- "fountain",
- "beach_umbrella",
- "umbrella_on_ground",
- "beach",
- "beach_with_umbrella",
- "island",
- "desert_island",
- "desert",
- "volcano",
- "mountain",
- "mountain_snow",
- "snow_capped_mountain",
- "mount_fuji",
- "camping",
- "tent",
- "house",
- "house_with_garden",
- "homes",
- "house_buildings",
- "houses",
- "house_abandoned",
- "derelict_house_building",
- "hut",
- "construction_site",
- "building_construction",
- "factory",
- "office",
- "department_store",
- "post_office",
- "european_post_office",
- "hospital",
- "bank",
- "hotel",
- "convenience_store",
- "school",
- "love_hotel",
- "wedding",
- "classical_building",
- "church",
- "mosque",
- "synagogue",
- "hindu_temple",
- "kaaba",
- "shinto_shrine",
- "railway_track",
- "railroad_track",
- "motorway",
- "japan",
- "map_of_japan",
- "rice_scene",
- "park",
- "national_park",
- "sunrise",
- "sunrise_over_mountains",
- "stars",
- "shooting_star",
- "sparkler",
- "fireworks",
- "city_sunset",
- "city_sunrise",
- "sunset",
- "city_dusk",
- "cityscape",
- "night_with_stars",
- "milky_way",
- "bridge_at_night",
- "foggy"
-];
-
-# List of all emojis.
-list emoji_values = [
- "💯",
- "🔢",
- "⚽",
- "⚽",
- "🏀",
- "🏈",
- "⚾",
- "🥎",
- "🎾",
- "🏐",
- "🏉",
- "🥏",
- "🎱",
- "🪀",
- "🏓",
- "🏓",
- "🏸",
- "🏒",
- "🏒",
- "🏑",
- "🥍",
- "🏏",
- "🏏",
- "🪃",
- "🥅",
- "🥅",
- "⛳",
- "⛳",
- "🪁",
- "🛝",
- "🏹",
- "🏹",
- "🎣",
- "🎣",
- "🤿",
- "🥊",
- "🥊",
- "🥋",
- "🥋",
- "🎽",
- "🎽",
- "🛹",
- "🛼",
- "🛷",
- "⛸️",
- "🥌",
- "🎿",
- "🎿",
- "⛷️",
- "🏂",
- "🏂🏻",
- "🏂🏻",
- "🏂🏼",
- "🏂🏼",
- "🏂🏽",
- "🏂🏽",
- "🏂🏾",
- "🏂🏾",
- "🏂🏿",
- "🏂🏿",
- "🪂",
- "🏋️",
- "🏋️",
- "🏋️",
- "🏋🏻",
- "🏋🏻",
- "🏋🏻",
- "🏋🏼",
- "🏋🏼",
- "🏋🏼",
- "🏋🏽",
- "🏋🏽",
- "🏋🏽",
- "🏋🏾",
- "🏋🏾",
- "🏋🏾",
- "🏋🏿",
- "🏋🏿",
- "🏋🏿",
- "🏋️♀️",
- "🏋🏻♀️",
- "🏋🏻♀️",
- "🏋🏼♀️",
- "🏋🏼♀️",
- "🏋🏽♀️",
- "🏋🏽♀️",
- "🏋🏾♀️",
- "🏋🏾♀️",
- "🏋🏿♀️",
- "🏋🏿♀️",
- "🏋️♂️",
- "🏋🏻♂️",
- "🏋🏻♂️",
- "🏋🏼♂️",
- "🏋🏼♂️",
- "🏋🏽♂️",
- "🏋🏽♂️",
- "🏋🏾♂️",
- "🏋🏾♂️",
- "🏋🏿♂️",
- "🏋🏿♂️",
- "🤼",
- "🤼",
- "🤼",
- "🤼♀️",
- "🤼♂️",
- "🤸",
- "🤸",
- "🤸🏻",
- "🤸🏻",
- "🤸🏼",
- "🤸🏼",
- "🤸🏽",
- "🤸🏽",
- "🤸🏾",
- "🤸🏾",
- "🤸🏿",
- "🤸🏿",
- "🤸♀️",
- "🤸🏻♀️",
- "🤸🏻♀️",
- "🤸🏼♀️",
- "🤸🏼♀️",
- "🤸🏽♀️",
- "🤸🏽♀️",
- "🤸🏾♀️",
- "🤸🏾♀️",
- "🤸🏿♀️",
- "🤸🏿♀️",
- "🤸♂️",
- "🤸🏻♂️",
- "🤸🏻♂️",
- "🤸🏼♂️",
- "🤸🏼♂️",
- "🤸🏽♂️",
- "🤸🏽♂️",
- "🤸🏾♂️",
- "🤸🏾♂️",
- "🤸🏿♂️",
- "🤸🏿♂️",
- "⛹️",
- "⛹️",
- "⛹️",
- "⛹🏻",
- "⛹🏻",
- "⛹🏻",
- "⛹🏼",
- "⛹🏼",
- "⛹🏼",
- "⛹🏽",
- "⛹🏽",
- "⛹🏽",
- "⛹🏾",
- "⛹🏾",
- "⛹🏾",
- "⛹🏿",
- "⛹🏿",
- "⛹🏿",
- "⛹️♀️",
- "⛹🏻♀️",
- "⛹🏻♀️",
- "⛹🏼♀️",
- "⛹🏼♀️",
- "⛹🏽♀️",
- "⛹🏽♀️",
- "⛹🏾♀️",
- "⛹🏾♀️",
- "⛹🏿♀️",
- "⛹🏿♀️",
- "⛹️♂️",
- "⛹🏻♂️",
- "⛹🏻♂️",
- "⛹🏼♂️",
- "⛹🏼♂️",
- "⛹🏽♂️",
- "⛹🏽♂️",
- "⛹🏾♂️",
- "⛹🏾♂️",
- "⛹🏿♂️",
- "⛹🏿♂️",
- "🤺",
- "🤺",
- "🤺",
- "🤾",
- "🤾",
- "🤾🏻",
- "🤾🏻",
- "🤾🏼",
- "🤾🏼",
- "🤾🏽",
- "🤾🏽",
- "🤾🏾",
- "🤾🏾",
- "🤾🏿",
- "🤾🏿",
- "🤾♀️",
- "🤾🏻♀️",
- "🤾🏻♀️",
- "🤾🏼♀️",
- "🤾🏼♀️",
- "🤾🏽♀️",
- "🤾🏽♀️",
- "🤾🏾♀️",
- "🤾🏾♀️",
- "🤾🏿♀️",
- "🤾🏿♀️",
- "🤾♂️",
- "🤾🏻♂️",
- "🤾🏻♂️",
- "🤾🏼♂️",
- "🤾🏼♂️",
- "🤾🏽♂️",
- "🤾🏽♂️",
- "🤾🏾♂️",
- "🤾🏾♂️",
- "🤾🏿♂️",
- "🤾🏿♂️",
- "🏌️",
- "🏌️",
- "🏌🏻",
- "🏌🏻",
- "🏌🏼",
- "🏌🏼",
- "🏌🏽",
- "🏌🏽",
- "🏌🏾",
- "🏌🏾",
- "🏌🏿",
- "🏌🏿",
- "🏌️♀️",
- "🏌🏻♀️",
- "🏌🏻♀️",
- "🏌🏼♀️",
- "🏌🏼♀️",
- "🏌🏽♀️",
- "🏌🏽♀️",
- "🏌🏾♀️",
- "🏌🏾♀️",
- "🏌🏿♀️",
- "🏌🏿♀️",
- "🏌️♂️",
- "🏌🏻♂️",
- "🏌🏻♂️",
- "🏌🏼♂️",
- "🏌🏼♂️",
- "🏌🏽♂️",
- "🏌🏽♂️",
- "🏌🏾♂️",
- "🏌🏾♂️",
- "🏌🏿♂️",
- "🏌🏿♂️",
- "🏇",
- "🏇🏻",
- "🏇🏼",
- "🏇🏽",
- "🏇🏾",
- "🏇🏿",
- "🧘",
- "🧘🏻",
- "🧘🏻",
- "🧘🏼",
- "🧘🏼",
- "🧘🏽",
- "🧘🏽",
- "🧘🏾",
- "🧘🏾",
- "🧘🏿",
- "🧘🏿",
- "🧘♀️",
- "🧘🏻♀️",
- "🧘🏻♀️",
- "🧘🏼♀️",
- "🧘🏼♀️",
- "🧘🏽♀️",
- "🧘🏽♀️",
- "🧘🏾♀️",
- "🧘🏾♀️",
- "🧘🏿♀️",
- "🧘🏿♀️",
- "🧘♂️",
- "🧘🏻♂️",
- "🧘🏻♂️",
- "🧘🏼♂️",
- "🧘🏼♂️",
- "🧘🏽♂️",
- "🧘🏽♂️",
- "🧘🏾♂️",
- "🧘🏾♂️",
- "🧘🏿♂️",
- "🧘🏿♂️",
- "🏄",
- "🏄",
- "🏄🏻",
- "🏄🏻",
- "🏄🏼",
- "🏄🏼",
- "🏄🏽",
- "🏄🏽",
- "🏄🏾",
- "🏄🏾",
- "🏄🏿",
- "🏄🏿",
- "🏄♀️",
- "🏄🏻♀️",
- "🏄🏻♀️",
- "🏄🏼♀️",
- "🏄🏼♀️",
- "🏄🏽♀️",
- "🏄🏽♀️",
- "🏄🏾♀️",
- "🏄🏾♀️",
- "🏄🏿♀️",
- "🏄🏿♀️",
- "🏄♂️",
- "🏄🏻♂️",
- "🏄🏻♂️",
- "🏄🏼♂️",
- "🏄🏼♂️",
- "🏄🏽♂️",
- "🏄🏽♂️",
- "🏄🏾♂️",
- "🏄🏾♂️",
- "🏄🏿♂️",
- "🏄🏿♂️",
- "🏊",
- "🏊",
- "🏊🏻",
- "🏊🏻",
- "🏊🏼",
- "🏊🏼",
- "🏊🏽",
- "🏊🏽",
- "🏊🏾",
- "🏊🏾",
- "🏊🏿",
- "🏊🏿",
- "🏊♀️",
- "🏊🏻♀️",
- "🏊🏻♀️",
- "🏊🏼♀️",
- "🏊🏼♀️",
- "🏊🏽♀️",
- "🏊🏽♀️",
- "🏊🏾♀️",
- "🏊🏾♀️",
- "🏊🏿♀️",
- "🏊🏿♀️",
- "🏊♂️",
- "🏊🏻♂️",
- "🏊🏻♂️",
- "🏊🏼♂️",
- "🏊🏼♂️",
- "🏊🏽♂️",
- "🏊🏽♂️",
- "🏊🏾♂️",
- "🏊🏾♂️",
- "🏊🏿♂️",
- "🏊🏿♂️",
- "🤽",
- "🤽",
- "🤽🏻",
- "🤽🏻",
- "🤽🏼",
- "🤽🏼",
- "🤽🏽",
- "🤽🏽",
- "🤽🏾",
- "🤽🏾",
- "🤽🏿",
- "🤽🏿",
- "🤽♀️",
- "🤽🏻♀️",
- "🤽🏻♀️",
- "🤽🏼♀️",
- "🤽🏼♀️",
- "🤽🏽♀️",
- "🤽🏽♀️",
- "🤽🏾♀️",
- "🤽🏾♀️",
- "🤽🏿♀️",
- "🤽🏿♀️",
- "🤽♂️",
- "🤽🏻♂️",
- "🤽🏻♂️",
- "🤽🏼♂️",
- "🤽🏼♂️",
- "🤽🏽♂️",
- "🤽🏽♂️",
- "🤽🏾♂️",
- "🤽🏾♂️",
- "🤽🏿♂️",
- "🤽🏿♂️",
- "🚣",
- "🚣",
- "🚣🏻",
- "🚣🏻",
- "🚣🏼",
- "🚣🏼",
- "🚣🏽",
- "🚣🏽",
- "🚣🏾",
- "🚣🏾",
- "🚣🏿",
- "🚣🏿",
- "🚣♀️",
- "🚣🏻♀️",
- "🚣🏻♀️",
- "🚣🏼♀️",
- "🚣🏼♀️",
- "🚣🏽♀️",
- "🚣🏽♀️",
- "🚣🏾♀️",
- "🚣🏾♀️",
- "🚣🏿♀️",
- "🚣🏿♀️",
- "🚣♂️",
- "🚣🏻♂️",
- "🚣🏻♂️",
- "🚣🏼♂️",
- "🚣🏼♂️",
- "🚣🏽♂️",
- "🚣🏽♂️",
- "🚣🏾♂️",
- "🚣🏾♂️",
- "🚣🏿♂️",
- "🚣🏿♂️",
- "🧗",
- "🧗🏻",
- "🧗🏻",
- "🧗🏼",
- "🧗🏼",
- "🧗🏽",
- "🧗🏽",
- "🧗🏾",
- "🧗🏾",
- "🧗🏿",
- "🧗🏿",
- "🧗♀️",
- "🧗🏻♀️",
- "🧗🏻♀️",
- "🧗🏼♀️",
- "🧗🏼♀️",
- "🧗🏽♀️",
- "🧗🏽♀️",
- "🧗🏾♀️",
- "🧗🏾♀️",
- "🧗🏿♀️",
- "🧗🏿♀️",
- "🧗♂️",
- "🧗🏻♂️",
- "🧗🏻♂️",
- "🧗🏼♂️",
- "🧗🏼♂️",
- "🧗🏽♂️",
- "🧗🏽♂️",
- "🧗🏾♂️",
- "🧗🏾♂️",
- "🧗🏿♂️",
- "🧗🏿♂️",
- "🚵",
- "🚵",
- "🚵🏻",
- "🚵🏻",
- "🚵🏼",
- "🚵🏼",
- "🚵🏽",
- "🚵🏽",
- "🚵🏾",
- "🚵🏾",
- "🚵🏿",
- "🚵🏿",
- "🚵♀️",
- "🚵🏻♀️",
- "🚵🏻♀️",
- "🚵🏼♀️",
- "🚵🏼♀️",
- "🚵🏽♀️",
- "🚵🏽♀️",
- "🚵🏾♀️",
- "🚵🏾♀️",
- "🚵🏿♀️",
- "🚵🏿♀️",
- "🚵♂️",
- "🚵🏻♂️",
- "🚵🏻♂️",
- "🚵🏼♂️",
- "🚵🏼♂️",
- "🚵🏽♂️",
- "🚵🏽♂️",
- "🚵🏾♂️",
- "🚵🏾♂️",
- "🚵🏿♂️",
- "🚵🏿♂️",
- "🚴",
- "🚴",
- "🚴🏻",
- "🚴🏻",
- "🚴🏼",
- "🚴🏼",
- "🚴🏽",
- "🚴🏽",
- "🚴🏾",
- "🚴🏾",
- "🚴🏿",
- "🚴🏿",
- "🚴♀️",
- "🚴🏻♀️",
- "🚴🏻♀️",
- "🚴🏼♀️",
- "🚴🏼♀️",
- "🚴🏽♀️",
- "🚴🏽♀️",
- "🚴🏾♀️",
- "🚴🏾♀️",
- "🚴🏿♀️",
- "🚴🏿♀️",
- "🚴♂️",
- "🚴🏻♂️",
- "🚴🏻♂️",
- "🚴🏼♂️",
- "🚴🏼♂️",
- "🚴🏽♂️",
- "🚴🏽♂️",
- "🚴🏾♂️",
- "🚴🏾♂️",
- "🚴🏿♂️",
- "🚴🏿♂️",
- "🏆",
- "🥇",
- "🥇",
- "🥈",
- "🥈",
- "🥉",
- "🥉",
- "🏅",
- "🏅",
- "🎖️",
- "🏵️",
- "🎗️",
- "🎫",
- "🎟️",
- "🎟️",
- "🎪",
- "🤹",
- "🤹",
- "🤹",
- "🤹🏻",
- "🤹🏻",
- "🤹🏻",
- "🤹🏼",
- "🤹🏼",
- "🤹🏼",
- "🤹🏽",
- "🤹🏽",
- "🤹🏽",
- "🤹🏾",
- "🤹🏾",
- "🤹🏾",
- "🤹🏿",
- "🤹🏿",
- "🤹🏿",
- "🤹♀️",
- "🤹🏻♀️",
- "🤹🏻♀️",
- "🤹🏼♀️",
- "🤹🏼♀️",
- "🤹🏽♀️",
- "🤹🏽♀️",
- "🤹🏾♀️",
- "🤹🏾♀️",
- "🤹🏿♀️",
- "🤹🏿♀️",
- "🤹♂️",
- "🤹🏻♂️",
- "🤹🏻♂️",
- "🤹🏼♂️",
- "🤹🏼♂️",
- "🤹🏽♂️",
- "🤹🏽♂️",
- "🤹🏾♂️",
- "🤹🏾♂️",
- "🤹🏿♂️",
- "🤹🏿♂️",
- "🎭",
- "🩰",
- "🎨",
- "🎬",
- "🎬",
- "🎤",
- "🎧",
- "🎧",
- "🎼",
- "🎹",
- "🪇",
- "🥁",
- "🥁",
- "🪘",
- "🎷",
- "🎺",
- "🪗",
- "🎸",
- "🪕",
- "🎻",
- "🪈",
- "🎲",
- "♟️",
- "🎯",
- "🎯",
- "🎳",
- "🎮",
- "🎰",
- "🧩",
- "🧩",
- "🏳️",
- "🏴",
- "🏴☠️",
- "🏁",
- "🚩",
- "🏳️🌈",
- "🏳️🌈",
- "🏳️⚧️",
- "🇺🇳",
- "🇦🇫",
- "🇦🇽",
- "🇦🇱",
- "🇩🇿",
- "🇦🇸",
- "🇦🇩",
- "🇦🇴",
- "🇦🇮",
- "🇦🇶",
- "🇦🇬",
- "🇦🇷",
- "🇦🇲",
- "🇦🇼",
- "🇦🇺",
- "🇦🇹",
- "🇦🇿",
- "🇧🇸",
- "🇧🇭",
- "🇧🇩",
- "🇧🇧",
- "🇧🇾",
- "🇧🇪",
- "🇧🇿",
- "🇧🇯",
- "🇧🇲",
- "🇧🇹",
- "🇧🇴",
- "🇧🇦",
- "🇧🇼",
- "🇧🇷",
- "🇮🇴",
- "🇻🇬",
- "🇧🇳",
- "🇧🇬",
- "🇧🇫",
- "🇧🇮",
- "🇰🇭",
- "🇨🇲",
- "🇨🇦",
- "🇮🇨",
- "🇨🇻",
- "🇧🇶",
- "🇰🇾",
- "🇨🇫",
- "🇹🇩",
- "🇨🇱",
- "🇨🇳",
- "🇨🇽",
- "🇨🇨",
- "🇨🇴",
- "🇰🇲",
- "🇨🇬",
- "🇨🇩",
- "🇨🇰",
- "🇨🇷",
- "🇨🇮",
- "🇭🇷",
- "🇨🇺",
- "🇨🇼",
- "🇨🇾",
- "🇨🇿",
- "🇩🇰",
- "🇩🇯",
- "🇩🇲",
- "🇩🇴",
- "🇪🇨",
- "🇪🇬",
- "🇸🇻",
- "🇬🇶",
- "🇪🇷",
- "🇪🇪",
- "🇪🇹",
- "🇪🇺",
- "🇫🇰",
- "🇫🇴",
- "🇫🇯",
- "🇫🇮",
- "🇫🇷",
- "🇬🇫",
- "🇵🇫",
- "🇹🇫",
- "🇬🇦",
- "🇬🇲",
- "🇬🇪",
- "🇩🇪",
- "🇬🇭",
- "🇬🇮",
- "🇬🇷",
- "🇬🇱",
- "🇬🇩",
- "🇬🇵",
- "🇬🇺",
- "🇬🇹",
- "🇬🇬",
- "🇬🇳",
- "🇬🇼",
- "🇬🇾",
- "🇭🇹",
- "🇭🇳",
- "🇭🇰",
- "🇭🇺",
- "🇮🇸",
- "🇮🇳",
- "🇮🇩",
- "🇮🇷",
- "🇮🇶",
- "🇮🇪",
- "🇮🇲",
- "🇮🇱",
- "🇮🇹",
- "🇯🇲",
- "🇯🇵",
- "🎌",
- "🇯🇪",
- "🇯🇴",
- "🇰🇿",
- "🇰🇪",
- "🇰🇮",
- "🇽🇰",
- "🇰🇼",
- "🇰🇬",
- "🇱🇦",
- "🇱🇻",
- "🇱🇧",
- "🇱🇸",
- "🇱🇷",
- "🇱🇾",
- "🇱🇮",
- "🇱🇹",
- "🇱🇺",
- "🇲🇴",
- "🇲🇰",
- "🇲🇬",
- "🇲🇼",
- "🇲🇾",
- "🇲🇻",
- "🇲🇱",
- "🇲🇹",
- "🇲🇭",
- "🇲🇶",
- "🇲🇷",
- "🇲🇺",
- "🇾🇹",
- "🇲🇽",
- "🇫🇲",
- "🇲🇩",
- "🇲🇨",
- "🇲🇳",
- "🇲🇪",
- "🇲🇸",
- "🇲🇦",
- "🇲🇿",
- "🇲🇲",
- "🇳🇦",
- "🇳🇷",
- "🇳🇵",
- "🇳🇱",
- "🇳🇨",
- "🇳🇿",
- "🇳🇮",
- "🇳🇪",
- "🇳🇬",
- "🇳🇺",
- "🇳🇫",
- "🇰🇵",
- "🇲🇵",
- "🇳🇴",
- "🇴🇲",
- "🇵🇰",
- "🇵🇼",
- "🇵🇸",
- "🇵🇦",
- "🇵🇬",
- "🇵🇾",
- "🇵🇪",
- "🇵🇭",
- "🇵🇳",
- "🇵🇱",
- "🇵🇹",
- "🇵🇷",
- "🇶🇦",
- "🇷🇪",
- "🇷🇴",
- "🇷🇺",
- "🇷🇼",
- "🇼🇸",
- "🇸🇲",
- "🇸🇹",
- "🇸🇦",
- "🇸🇳",
- "🇷🇸",
- "🇸🇨",
- "🇸🇱",
- "🇸🇬",
- "🇸🇽",
- "🇸🇰",
- "🇸🇮",
- "🇬🇸",
- "🇸🇧",
- "🇸🇴",
- "🇿🇦",
- "🇰🇷",
- "🇸🇸",
- "🇪🇸",
- "🇱🇰",
- "🇧🇱",
- "🇸🇭",
- "🇰🇳",
- "🇱🇨",
- "🇵🇲",
- "🇻🇨",
- "🇸🇩",
- "🇸🇷",
- "🇸🇿",
- "🇸🇪",
- "🇨🇭",
- "🇸🇾",
- "🇹🇼",
- "🇹🇯",
- "🇹🇿",
- "🇹🇭",
- "🇹🇱",
- "🇹🇬",
- "🇹🇰",
- "🇹🇴",
- "🇹🇹",
- "🇹🇳",
- "🇹🇷",
- "🇹🇲",
- "🇹🇨",
- "🇻🇮",
- "🇹🇻",
- "🇺🇬",
- "🇺🇦",
- "🇦🇪",
- "🇬🇧",
- "🏴",
- "🏴",
- "🏴",
- "🇺🇸",
- "🇺🇾",
- "🇺🇿",
- "🇻🇺",
- "🇻🇦",
- "🇻🇪",
- "🇻🇳",
- "🇼🇫",
- "🇪🇭",
- "🇾🇪",
- "🇿🇲",
- "🇿🇼",
- "🇦🇨",
- "🇧🇻",
- "🇨🇵",
- "🇪🇦",
- "🇩🇬",
- "🇭🇲",
- "🇲🇫",
- "🇸🇯",
- "🇹🇦",
- "🇺🇲",
- "🍏",
- "🍎",
- "🍎",
- "🍐",
- "🍊",
- "🍋",
- "🍌",
- "🍉",
- "🍇",
- "🍓",
- "🫐",
- "🍈",
- "🍒",
- "🍑",
- "🥭",
- "🍍",
- "🥥",
- "🥝",
- "🥝",
- "🥝",
- "🍅",
- "🍆",
- "🥑",
- "🫛",
- "🥦",
- "🥬",
- "🥒",
- "🌶️",
- "🫑",
- "🌽",
- "🌽",
- "🥕",
- "🫒",
- "🧄",
- "🧅",
- "🥔",
- "🍠",
- "🫚",
- "🥐",
- "🥯",
- "🍞",
- "🥖",
- "🥖",
- "🥨",
- "🧀",
- "🧀",
- "🥚",
- "🍳",
- "🧈",
- "🥞",
- "🧇",
- "🥓",
- "🥩",
- "🍗",
- "🍖",
- "🦴",
- "🌭",
- "🌭",
- "🍔",
- "🍟",
- "🍟",
- "🍕",
- "🫓",
- "🥪",
- "🥙",
- "🥙",
- "🧆",
- "🌮",
- "🌯",
- "🫔",
- "🥗",
- "🥗",
- "🥘",
- "🥘",
- "🫕",
- "🥫",
- "🫙",
- "🍝",
- "🍜",
- "🍜",
- "🍲",
- "🍲",
- "🍛",
- "🍛",
- "🍣",
- "🍱",
- "🍱",
- "🥟",
- "🦪",
- "🍤",
- "🍙",
- "🍚",
- "🍚",
- "🍘",
- "🍥",
- "🥠",
- "🥮",
- "🍢",
- "🍡",
- "🍧",
- "🍨",
- "🍦",
- "🥧",
- "🧁",
- "🍰",
- "🍰",
- "🎂",
- "🎂",
- "🍮",
- "🍮",
- "🍮",
- "🍭",
- "🍬",
- "🍫",
- "🍿",
- "🍩",
- "🍪",
- "🌰",
- "🥜",
- "🥜",
- "🫘",
- "🍯",
- "🥛",
- "🥛",
- "🫗",
- "🍼",
- "🫖",
- "☕",
- "☕",
- "🍵",
- "🧉",
- "🧃",
- "🥤",
- "🧋",
- "🍶",
- "🍺",
- "🍺",
- "🍻",
- "🥂",
- "🥂",
- "🍷",
- "🥃",
- "🥃",
- "🍸",
- "🍹",
- "🍾",
- "🍾",
- "🧊",
- "🥄",
- "🍴",
- "🍽️",
- "🍽️",
- "🥣",
- "🥡",
- "🥢",
- "🧂",
- "🐶",
- "🐶",
- "🐱",
- "🐱",
- "🐭",
- "🐭",
- "🐹",
- "🐰",
- "🐰",
- "🦊",
- "🦊",
- "🐻",
- "🐼",
- "🐼",
- "🐻❄️",
- "🐨",
- "🐯",
- "🐯",
- "🦁",
- "🦁",
- "🐮",
- "🐮",
- "🐷",
- "🐷",
- "🐽",
- "🐸",
- "🐵",
- "🙈",
- "🙉",
- "🙊",
- "🐒",
- "🐔",
- "🐧",
- "🐦",
- "🐤",
- "🐣",
- "🐥",
- "🪿",
- "🦆",
- "🐦⬛",
- "🦅",
- "🦉",
- "🦇",
- "🐺",
- "🐗",
- "🐴",
- "🐴",
- "🦄",
- "🦄",
- "🫎",
- "🐝",
- "🐝",
- "🪱",
- "🐛",
- "🦋",
- "🐌",
- "🐞",
- "🐜",
- "🪰",
- "🪲",
- "🪳",
- "🦟",
- "🦗",
- "🕷️",
- "🕸️",
- "🦂",
- "🐢",
- "🐍",
- "🦎",
- "🦖",
- "🦕",
- "🐙",
- "🦑",
- "🪼",
- "🦐",
- "🦞",
- "🦀",
- "🐡",
- "🐠",
- "🐟",
- "🐬",
- "🐳",
- "🐋",
- "🦈",
- "🦭",
- "🐊",
- "🐅",
- "🐆",
- "🦓",
- "🦍",
- "🦧",
- "🦣",
- "🐘",
- "🦛",
- "🦏",
- "🦏",
- "🐪",
- "🐫",
- "🦒",
- "🦘",
- "🦬",
- "🐃",
- "🐂",
- "🐄",
- "🫏",
- "🐎",
- "🐖",
- "🐏",
- "🐑",
- "🐑",
- "🦙",
- "🐐",
- "🦌",
- "🐕",
- "🐩",
- "🦮",
- "🐕🦺",
- "🐈",
- "🐈⬛",
- "🪶",
- "🪽",
- "🐓",
- "🦃",
- "🦤",
- "🦚",
- "🦜",
- "🦢",
- "🦩",
- "🕊️",
- "🕊️",
- "🐇",
- "🦝",
- "🦨",
- "🦡",
- "🦫",
- "🦦",
- "🦥",
- "🐁",
- "🐀",
- "🐿️",
- "🦔",
- "🐾",
- "🐾",
- "🐉",
- "🐲",
- "🌵",
- "🎄",
- "🌲",
- "🌳",
- "🌴",
- "🪵",
- "🌱",
- "🌿",
- "☘️",
- "🍀",
- "🎍",
- "🪴",
- "🎋",
- "🍃",
- "🍂",
- "🍁",
- "🪺",
- "🪹",
- "🍄",
- "🐚",
- "🐚",
- "🪸",
- "🪨",
- "🌾",
- "🌾",
- "💐",
- "🌷",
- "🌹",
- "🥀",
- "🥀",
- "🪻",
- "🪷",
- "🌺",
- "🌸",
- "🌼",
- "🌻",
- "🌞",
- "🌝",
- "🌛",
- "🌜",
- "🌚",
- "🌚",
- "🌕",
- "🌖",
- "🌗",
- "🌘",
- "🌑",
- "🌒",
- "🌓",
- "🌔",
- "🌙",
- "🌎",
- "🌍",
- "🌏",
- "🪐",
- "💫",
- "⭐",
- "🌟",
- "🌟",
- "✨",
- "⚡",
- "⚡",
- "☄️",
- "💥",
- "💥",
- "🔥",
- "🔥",
- "🌪️",
- "🌪️",
- "🌪️",
- "🌈",
- "☀️",
- "☀️",
- "🌤️",
- "🌤️",
- "⛅",
- "🌥️",
- "🌥️",
- "☁️",
- "🌦️",
- "🌦️",
- "🌧️",
- "🌧️",
- "⛈️",
- "⛈️",
- "🌩️",
- "🌩️",
- "🌨️",
- "🌨️",
- "❄️",
- "☃️",
- "⛄",
- "🌬️",
- "🌬️",
- "💨",
- "💨",
- "💧",
- "💦",
- "🫧",
- "☔",
- "☂️",
- "🌊",
- "🌊",
- "🌫️",
- "⌚",
- "📱",
- "📱",
- "📲",
- "💻",
- "⌨️",
- "🖥️",
- "🖥️",
- "🖨️",
- "🖱️",
- "🖱️",
- "🖲️",
- "🕹️",
- "🗜️",
- "🗜️",
- "💽",
- "💽",
- "💾",
- "💿",
- "💿",
- "📀",
- "📼",
- "📼",
- "📷",
- "📸",
- "📹",
- "🎥",
- "📽️",
- "📽️",
- "🎞️",
- "📞",
- "☎️",
- "📟",
- "📠",
- "📠",
- "📺",
- "📺",
- "📻",
- "🎙️",
- "🎙️",
- "🎚️",
- "🎛️",
- "🧭",
- "⏱️",
- "⏲️",
- "⏲️",
- "⏰",
- "🕰️",
- "🕰️",
- "⌛",
- "⏳",
- "📡",
- "🔋",
- "🪫",
- "🔌",
- "💡",
- "💡",
- "🔦",
- "🕯️",
- "🪔",
- "🧯",
- "🛢️",
- "🛢️",
- "💸",
- "💵",
- "💴",
- "💴",
- "💶",
- "💶",
- "💷",
- "🪙",
- "💰",
- "💰",
- "💳",
- "🪪",
- "💎",
- "💎",
- "⚖️",
- "⚖️",
- "🪜",
- "🧰",
- "🪛",
- "🔧",
- "🔨",
- "⚒️",
- "⚒️",
- "🛠️",
- "🛠️",
- "⛏️",
- "🪚",
- "🔩",
- "⚙️",
- "🪤",
- "🧱",
- "🧱",
- "⛓️",
- "🧲",
- "🔫",
- "🔫",
- "💣",
- "🧨",
- "🪓",
- "🔪",
- "🔪",
- "🗡️",
- "🗡️",
- "⚔️",
- "🛡️",
- "🚬",
- "🚬",
- "⚰️",
- "🪦",
- "⚱️",
- "⚱️",
- "🏺",
- "🔮",
- "📿",
- "🧿",
- "🪬",
- "💈",
- "💈",
- "⚗️",
- "🔭",
- "🔬",
- "🕳️",
- "🩻",
- "🩹",
- "🩺",
- "💊",
- "💉",
- "🩸",
- "🧬",
- "🦠",
- "🧫",
- "🧪",
- "🌡️",
- "🧹",
- "🪠",
- "🧺",
- "🧻",
- "🚽",
- "🚰",
- "🚿",
- "🛁",
- "🛀",
- "🛀🏻",
- "🛀🏼",
- "🛀🏽",
- "🛀🏾",
- "🛀🏿",
- "🧼",
- "🪥",
- "🪒",
- "🪮",
- "🧽",
- "🪣",
- "🧴",
- "🧴",
- "🛎️",
- "🛎️",
- "🔑",
- "🗝️",
- "🗝️",
- "🚪",
- "🪑",
- "🛋️",
- "🛋️",
- "🛏️",
- "🛌",
- "🛌",
- "🛌🏻",
- "🛌🏻",
- "🛌🏼",
- "🛌🏼",
- "🛌🏽",
- "🛌🏽",
- "🛌🏾",
- "🛌🏾",
- "🛌🏿",
- "🛌🏿",
- "🧸",
- "🪆",
- "🖼️",
- "🖼️",
- "🪞",
- "🪟",
- "🛍️",
- "🛒",
- "🛒",
- "🎁",
- "🎁",
- "🎈",
- "🎏",
- "🎏",
- "🎀",
- "🪄",
- "🪅",
- "🎊",
- "🎉",
- "🎉",
- "🎎",
- "🪭",
- "🏮",
- "🎐",
- "🪩",
- "🧧",
- "✉️",
- "📩",
- "📨",
- "📧",
- "📧",
- "💌",
- "📥",
- "📤",
- "📦",
- "🏷️",
- "🪧",
- "📪",
- "📫",
- "📬",
- "📭",
- "📮",
- "📯",
- "📜",
- "📃",
- "📄",
- "📑",
- "🧾",
- "📊",
- "📈",
- "📉",
- "🗒️",
- "🗒️",
- "🗓️",
- "🗓️",
- "📆",
- "📅",
- "🗑️",
- "📇",
- "🗃️",
- "🗃️",
- "🗳️",
- "🗳️",
- "🗄️",
- "📋",
- "📁",
- "📂",
- "🗂️",
- "🗂️",
- "🗞️",
- "🗞️",
- "📰",
- "📓",
- "📔",
- "📒",
- "📕",
- "📗",
- "📘",
- "📙",
- "📚",
- "📖",
- "📖",
- "🔖",
- "🧷",
- "🔗",
- "📎",
- "🖇️",
- "🖇️",
- "📐",
- "📏",
- "🧮",
- "📌",
- "📍",
- "✂️",
- "🖊️",
- "🖊️",
- "🖊️",
- "🖋️",
- "🖋️",
- "🖋️",
- "✒️",
- "🖌️",
- "🖌️",
- "🖍️",
- "🖍️",
- "📝",
- "📝",
- "✏️",
- "🔍",
- "🔎",
- "🔏",
- "🔐",
- "🔒",
- "🔒",
- "🔓",
- "🔓",
- "😀",
- "😀",
- "😃",
- "😄",
- "😁",
- "😆",
- "😆",
- "🥹",
- "😅",
- "😂",
- "🤣",
- "🤣",
- "🥲",
- "☺️",
- "☺️",
- "😊",
- "😇",
- "🙂",
- "🙂",
- "🙃",
- "🙃",
- "😉",
- "😉",
- "😌",
- "😌",
- "😍",
- "🥰",
- "😘",
- "😗",
- "😗",
- "😙",
- "😚",
- "😋",
- "😛",
- "😝",
- "😜",
- "🤪",
- "🤨",
- "🧐",
- "🤓",
- "🤓",
- "😎",
- "🥸",
- "🤩",
- "🥳",
- "😏",
- "😏",
- "😒",
- "😒",
- "😞",
- "😔",
- "😔",
- "😟",
- "😟",
- "😕",
- "😕",
- "🙁",
- "🙁",
- "☹️",
- "☹️",
- "☹️",
- "😣",
- "😖",
- "😫",
- "😩",
- "😩",
- "🥺",
- "😢",
- "😢",
- "😭",
- "😤",
- "😠",
- "😠",
- "😡",
- "😡",
- "🤬",
- "🤯",
- "😳",
- "😳",
- "🥵",
- "🥶",
- "😶🌫️",
- "😱",
- "😨",
- "😨",
- "😰",
- "😥",
- "😓",
- "🤗",
- "🤗",
- "🤔",
- "🤔",
- "🫣",
- "🤭",
- "🫢",
- "🫡",
- "🤫",
- "🫠",
- "🤥",
- "🤥",
- "😶",
- "🫥",
- "😐",
- "🫤",
- "😑",
- "🫨",
- "😬",
- "🙄",
- "🙄",
- "😯",
- "😯",
- "😦",
- "😧",
- "😮",
- "😲",
- "🥱",
- "😴",
- "😴",
- "🤤",
- "🤤",
- "😪",
- "😪",
- "😮💨",
- "😵",
- "😵💫",
- "🤐",
- "🤐",
- "🥴",
- "🤢",
- "🤢",
- "🤮",
- "🤧",
- "🤧",
- "😷",
- "🤒",
- "🤒",
- "🤕",
- "🤕",
- "🤑",
- "🤑",
- "🤠",
- "🤠",
- "😈",
- "👿",
- "👹",
- "👹",
- "👺",
- "👺",
- "🤡",
- "🤡",
- "💩",
- "💩",
- "💩",
- "💩",
- "💩",
- "👻",
- "💀",
- "💀",
- "☠️",
- "☠️",
- "👽",
- "👾",
- "👾",
- "🤖",
- "🤖",
- "🎃",
- "😺",
- "😺",
- "😸",
- "😹",
- "😻",
- "😼",
- "😽",
- "🙀",
- "🙀",
- "😿",
- "😿",
- "😾",
- "🫶",
- "🫶🏻",
- "🫶🏻",
- "🫶🏼",
- "🫶🏼",
- "🫶🏽",
- "🫶🏽",
- "🫶🏾",
- "🫶🏾",
- "🫶🏿",
- "🫶🏿",
- "🤲",
- "🤲🏻",
- "🤲🏻",
- "🤲🏼",
- "🤲🏼",
- "🤲🏽",
- "🤲🏽",
- "🤲🏾",
- "🤲🏾",
- "🤲🏿",
- "🤲🏿",
- "👐",
- "👐🏻",
- "👐🏼",
- "👐🏽",
- "👐🏾",
- "👐🏿",
- "🙌",
- "🙌",
- "🙌🏻",
- "🙌🏼",
- "🙌🏽",
- "🙌🏾",
- "🙌🏿",
- "👏",
- "👏🏻",
- "👏🏼",
- "👏🏽",
- "👏🏾",
- "👏🏿",
- "🤝",
- "🤝",
- "🤝🏻",
- "🤝🏻",
- "🫱🏻🫲🏼",
- "🫱🏻🫲🏼",
- "🫱🏻🫲🏽",
- "🫱🏻🫲🏽",
- "🫱🏻🫲🏾",
- "🫱🏻🫲🏾",
- "🫱🏻🫲🏿",
- "🫱🏻🫲🏿",
- "🫱🏼🫲🏻",
- "🫱🏼🫲🏻",
- "🤝🏼",
- "🤝🏼",
- "🫱🏼🫲🏽",
- "🫱🏼🫲🏽",
- "🫱🏼🫲🏾",
- "🫱🏼🫲🏾",
- "🫱🏼🫲🏿",
- "🫱🏼🫲🏿",
- "🫱🏽🫲🏻",
- "🫱🏽🫲🏻",
- "🫱🏽🫲🏼",
- "🫱🏽🫲🏼",
- "🤝🏽",
- "🤝🏽",
- "🫱🏽🫲🏾",
- "🫱🏽🫲🏾",
- "🫱🏽🫲🏿",
- "🫱🏽🫲🏿",
- "🫱🏾🫲🏻",
- "🫱🏾🫲🏻",
- "🫱🏾🫲🏼",
- "🫱🏾🫲🏼",
- "🫱🏾🫲🏽",
- "🫱🏾🫲🏽",
- "🤝🏾",
- "🤝🏾",
- "🫱🏾🫲🏿",
- "🫱🏾🫲🏿",
- "🫱🏿🫲🏻",
- "🫱🏿🫲🏻",
- "🫱🏿🫲🏼",
- "🫱🏿🫲🏼",
- "🫱🏿🫲🏽",
- "🫱🏿🫲🏽",
- "🫱🏿🫲🏾",
- "🫱🏿🫲🏾",
- "🤝🏿",
- "🤝🏿",
- "👍",
- "👍",
- "👍",
- "👍",
- "👍🏻",
- "👍🏻",
- "👍🏻",
- "👍🏼",
- "👍🏼",
- "👍🏼",
- "👍🏽",
- "👍🏽",
- "👍🏽",
- "👍🏾",
- "👍🏾",
- "👍🏾",
- "👍🏿",
- "👍🏿",
- "👍🏿",
- "👎",
- "👎",
- "👎",
- "👎",
- "👎🏻",
- "👎🏻",
- "👎🏻",
- "👎🏼",
- "👎🏼",
- "👎🏼",
- "👎🏽",
- "👎🏽",
- "👎🏽",
- "👎🏾",
- "👎🏾",
- "👎🏾",
- "👎🏿",
- "👎🏿",
- "👎🏿",
- "👊",
- "👊",
- "👊🏻",
- "👊🏼",
- "👊🏽",
- "👊🏾",
- "👊🏿",
- "✊",
- "✊",
- "✊🏻",
- "✊🏼",
- "✊🏽",
- "✊🏾",
- "✊🏿",
- "🤛",
- "🤛",
- "🤛🏻",
- "🤛🏻",
- "🤛🏼",
- "🤛🏼",
- "🤛🏽",
- "🤛🏽",
- "🤛🏾",
- "🤛🏾",
- "🤛🏿",
- "🤛🏿",
- "🤜",
- "🤜",
- "🤜🏻",
- "🤜🏻",
- "🤜🏼",
- "🤜🏼",
- "🤜🏽",
- "🤜🏽",
- "🤜🏾",
- "🤜🏾",
- "🤜🏿",
- "🤜🏿",
- "🫷",
- "🫷🏻",
- "🫷🏻",
- "🫷🏼",
- "🫷🏼",
- "🫷🏽",
- "🫷🏽",
- "🫷🏾",
- "🫷🏾",
- "🫷🏿",
- "🫷🏿",
- "🫸",
- "🫸🏻",
- "🫸🏻",
- "🫸🏼",
- "🫸🏼",
- "🫸🏽",
- "🫸🏽",
- "🫸🏾",
- "🫸🏾",
- "🫸🏿",
- "🫸🏿",
- "🤞",
- "🤞",
- "🤞🏻",
- "🤞🏻",
- "🤞🏼",
- "🤞🏼",
- "🤞🏽",
- "🤞🏽",
- "🤞🏾",
- "🤞🏾",
- "🤞🏿",
- "🤞🏿",
- "✌️",
- "✌️",
- "✌🏻",
- "✌🏼",
- "✌🏽",
- "✌🏾",
- "✌🏿",
- "🫰",
- "🫰🏻",
- "🫰🏻",
- "🫰🏼",
- "🫰🏼",
- "🫰🏽",
- "🫰🏽",
- "🫰🏾",
- "🫰🏾",
- "🫰🏿",
- "🫰🏿",
- "🤟",
- "🤟🏻",
- "🤟🏻",
- "🤟🏼",
- "🤟🏼",
- "🤟🏽",
- "🤟🏽",
- "🤟🏾",
- "🤟🏾",
- "🤟🏿",
- "🤟🏿",
- "🤘",
- "🤘",
- "🤘🏻",
- "🤘🏻",
- "🤘🏼",
- "🤘🏼",
- "🤘🏽",
- "🤘🏽",
- "🤘🏾",
- "🤘🏾",
- "🤘🏿",
- "🤘🏿",
- "👌",
- "👌🏻",
- "👌🏼",
- "👌🏽",
- "👌🏾",
- "👌🏿",
- "🤌",
- "🤌🏼",
- "🤌🏼",
- "🤌🏻",
- "🤌🏻",
- "🤌🏽",
- "🤌🏽",
- "🤌🏾",
- "🤌🏾",
- "🤌🏿",
- "🤌🏿",
- "🤏",
- "🤏🏻",
- "🤏🏻",
- "🤏🏼",
- "🤏🏼",
- "🤏🏽",
- "🤏🏽",
- "🤏🏾",
- "🤏🏾",
- "🤏🏿",
- "🤏🏿",
- "🫳",
- "🫳🏻",
- "🫳🏻",
- "🫳🏼",
- "🫳🏼",
- "🫳🏽",
- "🫳🏽",
- "🫳🏾",
- "🫳🏾",
- "🫳🏿",
- "🫳🏿",
- "🫴",
- "🫴🏻",
- "🫴🏻",
- "🫴🏼",
- "🫴🏼",
- "🫴🏽",
- "🫴🏽",
- "🫴🏾",
- "🫴🏾",
- "🫴🏿",
- "🫴🏿",
- "👈",
- "👈🏻",
- "👈🏼",
- "👈🏽",
- "👈🏾",
- "👈🏿",
- "👉",
- "👉🏻",
- "👉🏼",
- "👉🏽",
- "👉🏾",
- "👉🏿",
- "👆",
- "👆🏻",
- "👆🏼",
- "👆🏽",
- "👆🏾",
- "👆🏿",
- "👇",
- "👇🏻",
- "👇🏼",
- "👇🏽",
- "👇🏾",
- "👇🏿",
- "☝️",
- "☝🏻",
- "☝🏼",
- "☝🏽",
- "☝🏾",
- "☝🏿",
- "✋",
- "✋🏻",
- "✋🏼",
- "✋🏽",
- "✋🏾",
- "✋🏿",
- "🤚",
- "🤚",
- "🤚🏻",
- "🤚🏻",
- "🤚🏼",
- "🤚🏼",
- "🤚🏽",
- "🤚🏽",
- "🤚🏾",
- "🤚🏾",
- "🤚🏿",
- "🤚🏿",
- "🖐️",
- "🖐️",
- "🖐🏻",
- "🖐🏻",
- "🖐🏼",
- "🖐🏼",
- "🖐🏽",
- "🖐🏽",
- "🖐🏾",
- "🖐🏾",
- "🖐🏿",
- "🖐🏿",
- "🖖",
- "🖖",
- "🖖",
- "🖖🏻",
- "🖖🏻",
- "🖖🏼",
- "🖖🏼",
- "🖖🏽",
- "🖖🏽",
- "🖖🏾",
- "🖖🏾",
- "🖖🏿",
- "🖖🏿",
- "👋",
- "👋",
- "👋🏻",
- "👋🏼",
- "👋🏽",
- "👋🏾",
- "👋🏿",
- "🤙",
- "🤙",
- "🤙🏻",
- "🤙🏻",
- "🤙🏼",
- "🤙🏼",
- "🤙🏽",
- "🤙🏽",
- "🤙🏾",
- "🤙🏾",
- "🤙🏿",
- "🤙🏿",
- "🫲",
- "🫲🏻",
- "🫲🏻",
- "🫲🏼",
- "🫲🏼",
- "🫲🏽",
- "🫲🏽",
- "🫲🏾",
- "🫲🏾",
- "🫲🏿",
- "🫲🏿",
- "🫱",
- "🫱🏻",
- "🫱🏻",
- "🫱🏼",
- "🫱🏼",
- "🫱🏽",
- "🫱🏽",
- "🫱🏾",
- "🫱🏾",
- "🫱🏿",
- "🫱🏿",
- "💪",
- "💪",
- "💪🏻",
- "💪🏼",
- "💪🏽",
- "💪🏾",
- "💪🏿",
- "🦾",
- "🖕",
- "🖕",
- "🖕🏻",
- "🖕🏻",
- "🖕🏼",
- "🖕🏼",
- "🖕🏽",
- "🖕🏽",
- "🖕🏾",
- "🖕🏾",
- "🖕🏿",
- "🖕🏿",
- "✍️",
- "✍🏻",
- "✍🏼",
- "✍🏽",
- "✍🏾",
- "✍🏿",
- "🙏",
- "🙏",
- "🙏🏻",
- "🙏🏼",
- "🙏🏽",
- "🙏🏾",
- "🙏🏿",
- "🫵",
- "🫵🏻",
- "🫵🏻",
- "🫵🏼",
- "🫵🏼",
- "🫵🏽",
- "🫵🏽",
- "🫵🏾",
- "🫵🏾",
- "🫵🏿",
- "🫵🏿",
- "🦶",
- "🦶🏻",
- "🦶🏻",
- "🦶🏼",
- "🦶🏼",
- "🦶🏽",
- "🦶🏽",
- "🦶🏾",
- "🦶🏾",
- "🦶🏿",
- "🦶🏿",
- "🦵",
- "🦵🏻",
- "🦵🏻",
- "🦵🏼",
- "🦵🏼",
- "🦵🏽",
- "🦵🏽",
- "🦵🏾",
- "🦵🏾",
- "🦵🏿",
- "🦵🏿",
- "🦿",
- "💄",
- "💋",
- "💋",
- "👄",
- "👄",
- "🫦",
- "🦷",
- "👅",
- "👂",
- "👂🏻",
- "👂🏼",
- "👂🏽",
- "👂🏾",
- "👂🏿",
- "🦻",
- "🦻🏻",
- "🦻🏻",
- "🦻🏼",
- "🦻🏼",
- "🦻🏽",
- "🦻🏽",
- "🦻🏾",
- "🦻🏾",
- "🦻🏿",
- "🦻🏿",
- "👃",
- "👃🏻",
- "👃🏼",
- "👃🏽",
- "👃🏾",
- "👃🏿",
- "👣",
- "👁️",
- "👀",
- "🫀",
- "🫁",
- "🧠",
- "🗣️",
- "🗣️",
- "👤",
- "👥",
- "🫂",
- "👶",
- "👶🏻",
- "👶🏼",
- "👶🏽",
- "👶🏾",
- "👶🏿",
- "🧒",
- "🧒🏻",
- "🧒🏻",
- "🧒🏼",
- "🧒🏼",
- "🧒🏽",
- "🧒🏽",
- "🧒🏾",
- "🧒🏾",
- "🧒🏿",
- "🧒🏿",
- "👧",
- "👧🏻",
- "👧🏼",
- "👧🏽",
- "👧🏾",
- "👧🏿",
- "👦",
- "👦🏻",
- "👦🏼",
- "👦🏽",
- "👦🏾",
- "👦🏿",
- "🧑",
- "🧑",
- "🧑🏻",
- "🧑🏻",
- "🧑🏼",
- "🧑🏼",
- "🧑🏽",
- "🧑🏽",
- "🧑🏾",
- "🧑🏾",
- "🧑🏿",
- "🧑🏿",
- "👩",
- "👩🏻",
- "👩🏼",
- "👩🏽",
- "👩🏾",
- "👩🏿",
- "👨",
- "👨🏻",
- "👨🏼",
- "👨🏽",
- "👨🏾",
- "👨🏿",
- "🧑🦱",
- "🧑🏻🦱",
- "🧑🏻🦱",
- "🧑🏼🦱",
- "🧑🏼🦱",
- "🧑🏽🦱",
- "🧑🏽🦱",
- "🧑🏾🦱",
- "🧑🏾🦱",
- "🧑🏿🦱",
- "🧑🏿🦱",
- "👩🦱",
- "👩🏻🦱",
- "👩🏻🦱",
- "👩🏼🦱",
- "👩🏼🦱",
- "👩🏽🦱",
- "👩🏽🦱",
- "👩🏾🦱",
- "👩🏾🦱",
- "👩🏿🦱",
- "👩🏿🦱",
- "👨🦱",
- "👨🏻🦱",
- "👨🏻🦱",
- "👨🏼🦱",
- "👨🏼🦱",
- "👨🏽🦱",
- "👨🏽🦱",
- "👨🏾🦱",
- "👨🏾🦱",
- "👨🏿🦱",
- "👨🏿🦱",
- "🧑🦰",
- "🧑🏻🦰",
- "🧑🏻🦰",
- "🧑🏼🦰",
- "🧑🏼🦰",
- "🧑🏽🦰",
- "🧑🏽🦰",
- "🧑🏾🦰",
- "🧑🏾🦰",
- "🧑🏿🦰",
- "🧑🏿🦰",
- "👩🦰",
- "👩🏻🦰",
- "👩🏻🦰",
- "👩🏼🦰",
- "👩🏼🦰",
- "👩🏽🦰",
- "👩🏽🦰",
- "👩🏾🦰",
- "👩🏾🦰",
- "👩🏿🦰",
- "👩🏿🦰",
- "👨🦰",
- "👨🦰",
- "👨🏻🦰",
- "👨🏻🦰",
- "👨🏼🦰",
- "👨🏼🦰",
- "👨🏽🦰",
- "👨🏽🦰",
- "👨🏾🦰",
- "👨🏾🦰",
- "👨🏿🦰",
- "👨🏿🦰",
- "👱",
- "👱",
- "👱🏻",
- "👱🏻",
- "👱🏼",
- "👱🏼",
- "👱🏽",
- "👱🏽",
- "👱🏾",
- "👱🏾",
- "👱🏿",
- "👱🏿",
- "👱♀️",
- "👱🏻♀️",
- "👱🏻♀️",
- "👱🏼♀️",
- "👱🏼♀️",
- "👱🏽♀️",
- "👱🏽♀️",
- "👱🏾♀️",
- "👱🏾♀️",
- "👱🏿♀️",
- "👱🏿♀️",
- "👱♂️",
- "👱🏻♂️",
- "👱🏻♂️",
- "👱🏼♂️",
- "👱🏼♂️",
- "👱🏽♂️",
- "👱🏽♂️",
- "👱🏾♂️",
- "👱🏾♂️",
- "👱🏿♂️",
- "👱🏿♂️",
- "🧑🦳",
- "🧑🏻🦳",
- "🧑🏻🦳",
- "🧑🏼🦳",
- "🧑🏼🦳",
- "🧑🏽🦳",
- "🧑🏽🦳",
- "🧑🏾🦳",
- "🧑🏾🦳",
- "🧑🏿🦳",
- "🧑🏿🦳",
- "👩🦳",
- "👩🏻🦳",
- "👩🏻🦳",
- "👩🏼🦳",
- "👩🏼🦳",
- "👩🏽🦳",
- "👩🏽🦳",
- "👩🏾🦳",
- "👩🏾🦳",
- "👩🏿🦳",
- "👩🏿🦳",
- "👨🦳",
- "👨🏻🦳",
- "👨🏻🦳",
- "👨🏼🦳",
- "👨🏼🦳",
- "👨🏽🦳",
- "👨🏽🦳",
- "👨🏾🦳",
- "👨🏾🦳",
- "👨🏿🦳",
- "👨🏿🦳",
- "🧑🦲",
- "🧑🏻🦲",
- "🧑🏻🦲",
- "🧑🏼🦲",
- "🧑🏼🦲",
- "🧑🏽🦲",
- "🧑🏽🦲",
- "🧑🏾🦲",
- "🧑🏾🦲",
- "🧑🏿🦲",
- "🧑🏿🦲",
- "👩🦲",
- "👩🏻🦲",
- "👩🏻🦲",
- "👩🏼🦲",
- "👩🏼🦲",
- "👩🏽🦲",
- "👩🏽🦲",
- "👩🏾🦲",
- "👩🏾🦲",
- "👩🏿🦲",
- "👩🏿🦲",
- "👨🦲",
- "👨🏻🦲",
- "👨🏻🦲",
- "👨🏼🦲",
- "👨🏼🦲",
- "👨🏽🦲",
- "👨🏽🦲",
- "👨🏾🦲",
- "👨🏾🦲",
- "👨🏿🦲",
- "👨🏿🦲",
- "🧔",
- "🧔",
- "🧔🏻",
- "🧔🏻",
- "🧔🏼",
- "🧔🏼",
- "🧔🏽",
- "🧔🏽",
- "🧔🏾",
- "🧔🏾",
- "🧔🏿",
- "🧔🏿",
- "🧔♀️",
- "🧔🏻♀️",
- "🧔🏻♀️",
- "🧔🏼♀️",
- "🧔🏼♀️",
- "🧔🏽♀️",
- "🧔🏽♀️",
- "🧔🏾♀️",
- "🧔🏾♀️",
- "🧔🏿♀️",
- "🧔🏿♀️",
- "🧔♂️",
- "🧔🏻♂️",
- "🧔🏻♂️",
- "🧔🏼♂️",
- "🧔🏼♂️",
- "🧔🏽♂️",
- "🧔🏽♂️",
- "🧔🏾♂️",
- "🧔🏾♂️",
- "🧔🏿♂️",
- "🧔🏿♂️",
- "🧓",
- "🧓",
- "🧓🏻",
- "🧓🏻",
- "🧓🏼",
- "🧓🏼",
- "🧓🏽",
- "🧓🏽",
- "🧓🏾",
- "🧓🏾",
- "🧓🏿",
- "🧓🏿",
- "👵",
- "👵",
- "👵",
- "👵🏻",
- "👵🏻",
- "👵🏼",
- "👵🏼",
- "👵🏽",
- "👵🏽",
- "👵🏾",
- "👵🏾",
- "👵🏿",
- "👵🏿",
- "👴",
- "👴",
- "👴🏻",
- "👴🏼",
- "👴🏽",
- "👴🏾",
- "👴🏿",
- "👲",
- "👲",
- "👲🏻",
- "👲🏻",
- "👲🏼",
- "👲🏼",
- "👲🏽",
- "👲🏽",
- "👲🏾",
- "👲🏾",
- "👲🏿",
- "👲🏿",
- "👳",
- "👳",
- "👳🏻",
- "👳🏻",
- "👳🏼",
- "👳🏼",
- "👳🏽",
- "👳🏽",
- "👳🏾",
- "👳🏾",
- "👳🏿",
- "👳🏿",
- "👳♀️",
- "👳🏻♀️",
- "👳🏻♀️",
- "👳🏼♀️",
- "👳🏼♀️",
- "👳🏽♀️",
- "👳🏽♀️",
- "👳🏾♀️",
- "👳🏾♀️",
- "👳🏿♀️",
- "👳🏿♀️",
- "👳♂️",
- "👳🏻♂️",
- "👳🏻♂️",
- "👳🏼♂️",
- "👳🏼♂️",
- "👳🏽♂️",
- "👳🏽♂️",
- "👳🏾♂️",
- "👳🏾♂️",
- "👳🏿♂️",
- "👳🏿♂️",
- "🧕",
- "🧕🏻",
- "🧕🏻",
- "🧕🏼",
- "🧕🏼",
- "🧕🏽",
- "🧕🏽",
- "🧕🏾",
- "🧕🏾",
- "🧕🏿",
- "🧕🏿",
- "👮",
- "👮",
- "👮🏻",
- "👮🏻",
- "👮🏼",
- "👮🏼",
- "👮🏽",
- "👮🏽",
- "👮🏾",
- "👮🏾",
- "👮🏿",
- "👮🏿",
- "👮♀️",
- "👮🏻♀️",
- "👮🏻♀️",
- "👮🏼♀️",
- "👮🏼♀️",
- "👮🏽♀️",
- "👮🏽♀️",
- "👮🏾♀️",
- "👮🏾♀️",
- "👮🏿♀️",
- "👮🏿♀️",
- "👮♂️",
- "👮🏻♂️",
- "👮🏻♂️",
- "👮🏼♂️",
- "👮🏼♂️",
- "👮🏽♂️",
- "👮🏽♂️",
- "👮🏾♂️",
- "👮🏾♂️",
- "👮🏿♂️",
- "👮🏿♂️",
- "👷",
- "👷🏻",
- "👷🏼",
- "👷🏽",
- "👷🏾",
- "👷🏿",
- "👷♀️",
- "👷🏻♀️",
- "👷🏻♀️",
- "👷🏼♀️",
- "👷🏼♀️",
- "👷🏽♀️",
- "👷🏽♀️",
- "👷🏾♀️",
- "👷🏾♀️",
- "👷🏿♀️",
- "👷🏿♀️",
- "👷♂️",
- "👷🏻♂️",
- "👷🏻♂️",
- "👷🏼♂️",
- "👷🏼♂️",
- "👷🏽♂️",
- "👷🏽♂️",
- "👷🏾♂️",
- "👷🏾♂️",
- "👷🏿♂️",
- "👷🏿♂️",
- "💂",
- "💂",
- "💂🏻",
- "💂🏻",
- "💂🏼",
- "💂🏼",
- "💂🏽",
- "💂🏽",
- "💂🏾",
- "💂🏾",
- "💂🏿",
- "💂🏿",
- "💂♀️",
- "💂🏻♀️",
- "💂🏻♀️",
- "💂🏼♀️",
- "💂🏼♀️",
- "💂🏽♀️",
- "💂🏽♀️",
- "💂🏾♀️",
- "💂🏾♀️",
- "💂🏿♀️",
- "💂🏿♀️",
- "💂♂️",
- "💂🏻♂️",
- "💂🏻♂️",
- "💂🏼♂️",
- "💂🏼♂️",
- "💂🏽♂️",
- "💂🏽♂️",
- "💂🏾♂️",
- "💂🏾♂️",
- "💂🏿♂️",
- "💂🏿♂️",
- "🕵️",
- "🕵️",
- "🕵️",
- "🕵🏻",
- "🕵🏻",
- "🕵🏻",
- "🕵🏼",
- "🕵🏼",
- "🕵🏼",
- "🕵🏽",
- "🕵🏽",
- "🕵🏽",
- "🕵🏾",
- "🕵🏾",
- "🕵🏾",
- "🕵🏿",
- "🕵🏿",
- "🕵🏿",
- "🕵️♀️",
- "🕵🏻♀️",
- "🕵🏻♀️",
- "🕵🏼♀️",
- "🕵🏼♀️",
- "🕵🏽♀️",
- "🕵🏽♀️",
- "🕵🏾♀️",
- "🕵🏾♀️",
- "🕵🏿♀️",
- "🕵🏿♀️",
- "🕵️♂️",
- "🕵🏻♂️",
- "🕵🏻♂️",
- "🕵🏼♂️",
- "🕵🏼♂️",
- "🕵🏽♂️",
- "🕵🏽♂️",
- "🕵🏾♂️",
- "🕵🏾♂️",
- "🕵🏿♂️",
- "🕵🏿♂️",
- "🧑⚕️",
- "🧑🏻⚕️",
- "🧑🏻⚕️",
- "🧑🏼⚕️",
- "🧑🏼⚕️",
- "🧑🏽⚕️",
- "🧑🏽⚕️",
- "🧑🏾⚕️",
- "🧑🏾⚕️",
- "🧑🏿⚕️",
- "🧑🏿⚕️",
- "👩⚕️",
- "👩🏻⚕️",
- "👩🏻⚕️",
- "👩🏼⚕️",
- "👩🏼⚕️",
- "👩🏽⚕️",
- "👩🏽⚕️",
- "👩🏾⚕️",
- "👩🏾⚕️",
- "👩🏿⚕️",
- "👩🏿⚕️",
- "👨⚕️",
- "👨🏻⚕️",
- "👨🏻⚕️",
- "👨🏼⚕️",
- "👨🏼⚕️",
- "👨🏽⚕️",
- "👨🏽⚕️",
- "👨🏾⚕️",
- "👨🏾⚕️",
- "👨🏿⚕️",
- "👨🏿⚕️",
- "🧑🌾",
- "🧑🏻🌾",
- "🧑🏻🌾",
- "🧑🏼🌾",
- "🧑🏼🌾",
- "🧑🏽🌾",
- "🧑🏽🌾",
- "🧑🏾🌾",
- "🧑🏾🌾",
- "🧑🏿🌾",
- "🧑🏿🌾",
- "👩🌾",
- "👩🏻🌾",
- "👩🏻🌾",
- "👩🏼🌾",
- "👩🏼🌾",
- "👩🏽🌾",
- "👩🏽🌾",
- "👩🏾🌾",
- "👩🏾🌾",
- "👩🏿🌾",
- "👩🏿🌾",
- "👨🌾",
- "👨🏻🌾",
- "👨🏻🌾",
- "👨🏼🌾",
- "👨🏼🌾",
- "👨🏽🌾",
- "👨🏽🌾",
- "👨🏾🌾",
- "👨🏾🌾",
- "👨🏿🌾",
- "👨🏿🌾",
- "🧑🍳",
- "🧑🏻🍳",
- "🧑🏻🍳",
- "🧑🏼🍳",
- "🧑🏼🍳",
- "🧑🏽🍳",
- "🧑🏽🍳",
- "🧑🏾🍳",
- "🧑🏾🍳",
- "🧑🏿🍳",
- "🧑🏿🍳",
- "👩🍳",
- "👩🏻🍳",
- "👩🏻🍳",
- "👩🏼🍳",
- "👩🏼🍳",
- "👩🏽🍳",
- "👩🏽🍳",
- "👩🏾🍳",
- "👩🏾🍳",
- "👩🏿🍳",
- "👩🏿🍳",
- "👨🍳",
- "👨🏻🍳",
- "👨🏻🍳",
- "👨🏼🍳",
- "👨🏼🍳",
- "👨🏽🍳",
- "👨🏽🍳",
- "👨🏾🍳",
- "👨🏾🍳",
- "👨🏿🍳",
- "👨🏿🍳",
- "🧑🎓",
- "🧑🏻🎓",
- "🧑🏻🎓",
- "🧑🏼🎓",
- "🧑🏼🎓",
- "🧑🏽🎓",
- "🧑🏽🎓",
- "🧑🏾🎓",
- "🧑🏾🎓",
- "🧑🏿🎓",
- "🧑🏿🎓",
- "👩🎓",
- "👩🏻🎓",
- "👩🏻🎓",
- "👩🏼🎓",
- "👩🏼🎓",
- "👩🏽🎓",
- "👩🏽🎓",
- "👩🏾🎓",
- "👩🏾🎓",
- "👩🏿🎓",
- "👩🏿🎓",
- "👨🎓",
- "👨🏻🎓",
- "👨🏻🎓",
- "👨🏼🎓",
- "👨🏼🎓",
- "👨🏽🎓",
- "👨🏽🎓",
- "👨🏾🎓",
- "👨🏾🎓",
- "👨🏿🎓",
- "👨🏿🎓",
- "🧑🎤",
- "🧑🏻🎤",
- "🧑🏻🎤",
- "🧑🏼🎤",
- "🧑🏼🎤",
- "🧑🏽🎤",
- "🧑🏽🎤",
- "🧑🏾🎤",
- "🧑🏾🎤",
- "🧑🏿🎤",
- "🧑🏿🎤",
- "👩🎤",
- "👩🏻🎤",
- "👩🏻🎤",
- "👩🏼🎤",
- "👩🏼🎤",
- "👩🏽🎤",
- "👩🏽🎤",
- "👩🏾🎤",
- "👩🏾🎤",
- "👩🏿🎤",
- "👩🏿🎤",
- "👨🎤",
- "👨🏻🎤",
- "👨🏻🎤",
- "👨🏼🎤",
- "👨🏼🎤",
- "👨🏽🎤",
- "👨🏽🎤",
- "👨🏾🎤",
- "👨🏾🎤",
- "👨🏿🎤",
- "👨🏿🎤",
- "🧑🏫",
- "🧑🏻🏫",
- "🧑🏻🏫",
- "🧑🏼🏫",
- "🧑🏼🏫",
- "🧑🏽🏫",
- "🧑🏽🏫",
- "🧑🏾🏫",
- "🧑🏾🏫",
- "🧑🏿🏫",
- "🧑🏿🏫",
- "👩🏫",
- "👩🏻🏫",
- "👩🏻🏫",
- "👩🏼🏫",
- "👩🏼🏫",
- "👩🏽🏫",
- "👩🏽🏫",
- "👩🏾🏫",
- "👩🏾🏫",
- "👩🏿🏫",
- "👩🏿🏫",
- "👨🏫",
- "👨🏻🏫",
- "👨🏻🏫",
- "👨🏼🏫",
- "👨🏼🏫",
- "👨🏽🏫",
- "👨🏽🏫",
- "👨🏾🏫",
- "👨🏾🏫",
- "👨🏿🏫",
- "👨🏿🏫",
- "🧑🏭",
- "🧑🏻🏭",
- "🧑🏻🏭",
- "🧑🏼🏭",
- "🧑🏼🏭",
- "🧑🏽🏭",
- "🧑🏽🏭",
- "🧑🏾🏭",
- "🧑🏾🏭",
- "🧑🏿🏭",
- "🧑🏿🏭",
- "👩🏭",
- "👩🏻🏭",
- "👩🏻🏭",
- "👩🏼🏭",
- "👩🏼🏭",
- "👩🏽🏭",
- "👩🏽🏭",
- "👩🏾🏭",
- "👩🏾🏭",
- "👩🏿🏭",
- "👩🏿🏭",
- "👨🏭",
- "👨🏻🏭",
- "👨🏻🏭",
- "👨🏼🏭",
- "👨🏼🏭",
- "👨🏽🏭",
- "👨🏽🏭",
- "👨🏾🏭",
- "👨🏾🏭",
- "👨🏿🏭",
- "👨🏿🏭",
- "🧑💻",
- "🧑🏻💻",
- "🧑🏻💻",
- "🧑🏼💻",
- "🧑🏼💻",
- "🧑🏽💻",
- "🧑🏽💻",
- "🧑🏾💻",
- "🧑🏾💻",
- "🧑🏿💻",
- "🧑🏿💻",
- "👩💻",
- "👩🏻💻",
- "👩🏻💻",
- "👩🏼💻",
- "👩🏼💻",
- "👩🏽💻",
- "👩🏽💻",
- "👩🏾💻",
- "👩🏾💻",
- "👩🏿💻",
- "👩🏿💻",
- "👨💻",
- "👨🏻💻",
- "👨🏻💻",
- "👨🏼💻",
- "👨🏼💻",
- "👨🏽💻",
- "👨🏽💻",
- "👨🏾💻",
- "👨🏾💻",
- "👨🏿💻",
- "👨🏿💻",
- "🧑💼",
- "🧑🏻💼",
- "🧑🏻💼",
- "🧑🏼💼",
- "🧑🏼💼",
- "🧑🏽💼",
- "🧑🏽💼",
- "🧑🏾💼",
- "🧑🏾💼",
- "🧑🏿💼",
- "🧑🏿💼",
- "👩💼",
- "👩🏻💼",
- "👩🏻💼",
- "👩🏼💼",
- "👩🏼💼",
- "👩🏽💼",
- "👩🏽💼",
- "👩🏾💼",
- "👩🏾💼",
- "👩🏿💼",
- "👩🏿💼",
- "👨💼",
- "👨🏻💼",
- "👨🏻💼",
- "👨🏼💼",
- "👨🏼💼",
- "👨🏽💼",
- "👨🏽💼",
- "👨🏾💼",
- "👨🏾💼",
- "👨🏿💼",
- "👨🏿💼",
- "🧑🔧",
- "🧑🏻🔧",
- "🧑🏻🔧",
- "🧑🏼🔧",
- "🧑🏼🔧",
- "🧑🏽🔧",
- "🧑🏽🔧",
- "🧑🏾🔧",
- "🧑🏾🔧",
- "🧑🏿🔧",
- "🧑🏿🔧",
- "👩🔧",
- "👩🏻🔧",
- "👩🏻🔧",
- "👩🏼🔧",
- "👩🏼🔧",
- "👩🏽🔧",
- "👩🏽🔧",
- "👩🏾🔧",
- "👩🏾🔧",
- "👩🏿🔧",
- "👩🏿🔧",
- "👨🔧",
- "👨🏻🔧",
- "👨🏻🔧",
- "👨🏼🔧",
- "👨🏼🔧",
- "👨🏽🔧",
- "👨🏽🔧",
- "👨🏾🔧",
- "👨🏾🔧",
- "👨🏿🔧",
- "👨🏿🔧",
- "🧑🔬",
- "🧑🏻🔬",
- "🧑🏻🔬",
- "🧑🏼🔬",
- "🧑🏼🔬",
- "🧑🏽🔬",
- "🧑🏽🔬",
- "🧑🏾🔬",
- "🧑🏾🔬",
- "🧑🏿🔬",
- "🧑🏿🔬",
- "👩🔬",
- "👩🏻🔬",
- "👩🏻🔬",
- "👩🏼🔬",
- "👩🏼🔬",
- "👩🏽🔬",
- "👩🏽🔬",
- "👩🏾🔬",
- "👩🏾🔬",
- "👩🏿🔬",
- "👩🏿🔬",
- "👨🔬",
- "👨🏻🔬",
- "👨🏻🔬",
- "👨🏼🔬",
- "👨🏼🔬",
- "👨🏽🔬",
- "👨🏽🔬",
- "👨🏾🔬",
- "👨🏾🔬",
- "👨🏿🔬",
- "👨🏿🔬",
- "🧑🎨",
- "🧑🏻🎨",
- "🧑🏻🎨",
- "🧑🏼🎨",
- "🧑🏼🎨",
- "🧑🏽🎨",
- "🧑🏽🎨",
- "🧑🏾🎨",
- "🧑🏾🎨",
- "🧑🏿🎨",
- "🧑🏿🎨",
- "👩🎨",
- "👩🏻🎨",
- "👩🏻🎨",
- "👩🏼🎨",
- "👩🏼🎨",
- "👩🏽🎨",
- "👩🏽🎨",
- "👩🏾🎨",
- "👩🏾🎨",
- "👩🏿🎨",
- "👩🏿🎨",
- "👨🎨",
- "👨🏻🎨",
- "👨🏻🎨",
- "👨🏼🎨",
- "👨🏼🎨",
- "👨🏽🎨",
- "👨🏽🎨",
- "👨🏾🎨",
- "👨🏾🎨",
- "👨🏿🎨",
- "👨🏿🎨",
- "🧑🚒",
- "🧑🏻🚒",
- "🧑🏻🚒",
- "🧑🏼🚒",
- "🧑🏼🚒",
- "🧑🏽🚒",
- "🧑🏽🚒",
- "🧑🏾🚒",
- "🧑🏾🚒",
- "🧑🏿🚒",
- "🧑🏿🚒",
- "👩🚒",
- "👩🏻🚒",
- "👩🏻🚒",
- "👩🏼🚒",
- "👩🏼🚒",
- "👩🏽🚒",
- "👩🏽🚒",
- "👩🏾🚒",
- "👩🏾🚒",
- "👩🏿🚒",
- "👩🏿🚒",
- "👨🚒",
- "👨🏻🚒",
- "👨🏻🚒",
- "👨🏼🚒",
- "👨🏼🚒",
- "👨🏽🚒",
- "👨🏽🚒",
- "👨🏾🚒",
- "👨🏾🚒",
- "👨🏿🚒",
- "👨🏿🚒",
- "🧑✈️",
- "🧑🏻✈️",
- "🧑🏻✈️",
- "🧑🏼✈️",
- "🧑🏼✈️",
- "🧑🏽✈️",
- "🧑🏽✈️",
- "🧑🏾✈️",
- "🧑🏾✈️",
- "🧑🏿✈️",
- "🧑🏿✈️",
- "👩✈️",
- "👩🏻✈️",
- "👩🏻✈️",
- "👩🏼✈️",
- "👩🏼✈️",
- "👩🏽✈️",
- "👩🏽✈️",
- "👩🏾✈️",
- "👩🏾✈️",
- "👩🏿✈️",
- "👩🏿✈️",
- "👨✈️",
- "👨🏻✈️",
- "👨🏻✈️",
- "👨🏼✈️",
- "👨🏼✈️",
- "👨🏽✈️",
- "👨🏽✈️",
- "👨🏾✈️",
- "👨🏾✈️",
- "👨🏿✈️",
- "👨🏿✈️",
- "🧑🚀",
- "🧑🏻🚀",
- "🧑🏻🚀",
- "🧑🏼🚀",
- "🧑🏼🚀",
- "🧑🏽🚀",
- "🧑🏽🚀",
- "🧑🏾🚀",
- "🧑🏾🚀",
- "🧑🏿🚀",
- "🧑🏿🚀",
- "👩🚀",
- "👩🏻🚀",
- "👩🏻🚀",
- "👩🏼🚀",
- "👩🏼🚀",
- "👩🏽🚀",
- "👩🏽🚀",
- "👩🏾🚀",
- "👩🏾🚀",
- "👩🏿🚀",
- "👩🏿🚀",
- "👨🚀",
- "👨🏻🚀",
- "👨🏻🚀",
- "👨🏼🚀",
- "👨🏼🚀",
- "👨🏽🚀",
- "👨🏽🚀",
- "👨🏾🚀",
- "👨🏾🚀",
- "👨🏿🚀",
- "👨🏿🚀",
- "🧑⚖️",
- "🧑🏻⚖️",
- "🧑🏻⚖️",
- "🧑🏼⚖️",
- "🧑🏼⚖️",
- "🧑🏽⚖️",
- "🧑🏽⚖️",
- "🧑🏾⚖️",
- "🧑🏾⚖️",
- "🧑🏿⚖️",
- "🧑🏿⚖️",
- "👩⚖️",
- "👩🏻⚖️",
- "👩🏻⚖️",
- "👩🏼⚖️",
- "👩🏼⚖️",
- "👩🏽⚖️",
- "👩🏽⚖️",
- "👩🏾⚖️",
- "👩🏾⚖️",
- "👩🏿⚖️",
- "👩🏿⚖️",
- "👨⚖️",
- "👨🏻⚖️",
- "👨🏻⚖️",
- "👨🏼⚖️",
- "👨🏼⚖️",
- "👨🏽⚖️",
- "👨🏽⚖️",
- "👨🏾⚖️",
- "👨🏾⚖️",
- "👨🏿⚖️",
- "👨🏿⚖️",
- "👰",
- "👰🏻",
- "👰🏼",
- "👰🏽",
- "👰🏾",
- "👰🏿",
- "👰♀️",
- "👰♀️",
- "👰🏻♀️",
- "👰🏻♀️",
- "👰🏼♀️",
- "👰🏼♀️",
- "👰🏽♀️",
- "👰🏽♀️",
- "👰🏾♀️",
- "👰🏾♀️",
- "👰🏿♀️",
- "👰🏿♀️",
- "👰♂️",
- "👰🏻♂️",
- "👰🏻♂️",
- "👰🏼♂️",
- "👰🏼♂️",
- "👰🏽♂️",
- "👰🏽♂️",
- "👰🏾♂️",
- "👰🏾♂️",
- "👰🏿♂️",
- "👰🏿♂️",
- "🤵",
- "🤵🏻",
- "🤵🏻",
- "🤵🏼",
- "🤵🏼",
- "🤵🏽",
- "🤵🏽",
- "🤵🏾",
- "🤵🏾",
- "🤵🏿",
- "🤵🏿",
- "🤵♀️",
- "🤵🏻♀️",
- "🤵🏻♀️",
- "🤵🏼♀️",
- "🤵🏼♀️",
- "🤵🏽♀️",
- "🤵🏽♀️",
- "🤵🏾♀️",
- "🤵🏾♀️",
- "🤵🏿♀️",
- "🤵🏿♀️",
- "🤵♂️",
- "🤵🏻♂️",
- "🤵🏻♂️",
- "🤵🏼♂️",
- "🤵🏼♂️",
- "🤵🏽♂️",
- "🤵🏽♂️",
- "🤵🏾♂️",
- "🤵🏾♂️",
- "🤵🏿♂️",
- "🤵🏿♂️",
- "🫅",
- "🫅🏻",
- "🫅🏻",
- "🫅🏼",
- "🫅🏼",
- "🫅🏽",
- "🫅🏽",
- "🫅🏾",
- "🫅🏾",
- "🫅🏿",
- "🫅🏿",
- "👸",
- "👸🏻",
- "👸🏼",
- "👸🏽",
- "👸🏾",
- "👸🏿",
- "🤴",
- "🤴🏻",
- "🤴🏼",
- "🤴🏽",
- "🤴🏾",
- "🤴🏿",
- "🦸",
- "🦸🏻",
- "🦸🏻",
- "🦸🏼",
- "🦸🏼",
- "🦸🏽",
- "🦸🏽",
- "🦸🏾",
- "🦸🏾",
- "🦸🏿",
- "🦸🏿",
- "🦸♀️",
- "🦸🏻♀️",
- "🦸🏻♀️",
- "🦸🏼♀️",
- "🦸🏼♀️",
- "🦸🏽♀️",
- "🦸🏽♀️",
- "🦸🏾♀️",
- "🦸🏾♀️",
- "🦸🏿♀️",
- "🦸🏿♀️",
- "🦸♂️",
- "🦸🏻♂️",
- "🦸🏻♂️",
- "🦸🏼♂️",
- "🦸🏼♂️",
- "🦸🏽♂️",
- "🦸🏽♂️",
- "🦸🏾♂️",
- "🦸🏾♂️",
- "🦸🏿♂️",
- "🦸🏿♂️",
- "🦹",
- "🦹🏻",
- "🦹🏻",
- "🦹🏼",
- "🦹🏼",
- "🦹🏽",
- "🦹🏽",
- "🦹🏾",
- "🦹🏾",
- "🦹🏿",
- "🦹🏿",
- "🦹♀️",
- "🦹🏻♀️",
- "🦹🏻♀️",
- "🦹🏼♀️",
- "🦹🏼♀️",
- "🦹🏽♀️",
- "🦹🏽♀️",
- "🦹🏾♀️",
- "🦹🏾♀️",
- "🦹🏿♀️",
- "🦹🏿♀️",
- "🦹♂️",
- "🦹🏻♂️",
- "🦹🏻♂️",
- "🦹🏼♂️",
- "🦹🏼♂️",
- "🦹🏽♂️",
- "🦹🏽♂️",
- "🦹🏾♂️",
- "🦹🏾♂️",
- "🦹🏿♂️",
- "🦹🏿♂️",
- "🥷",
- "🥷🏻",
- "🥷🏻",
- "🥷🏼",
- "🥷🏼",
- "🥷🏽",
- "🥷🏽",
- "🥷🏾",
- "🥷🏾",
- "🥷🏿",
- "🥷🏿",
- "🧑🎄",
- "🧑🏻🎄",
- "🧑🏻🎄",
- "🧑🏼🎄",
- "🧑🏼🎄",
- "🧑🏽🎄",
- "🧑🏽🎄",
- "🧑🏾🎄",
- "🧑🏾🎄",
- "🧑🏿🎄",
- "🧑🏿🎄",
- "🤶",
- "🤶",
- "🤶🏻",
- "🤶🏻",
- "🤶🏼",
- "🤶🏼",
- "🤶🏽",
- "🤶🏽",
- "🤶🏾",
- "🤶🏾",
- "🤶🏿",
- "🤶🏿",
- "🎅",
- "🎅",
- "🎅🏻",
- "🎅🏼",
- "🎅🏽",
- "🎅🏾",
- "🎅🏿",
- "🧙",
- "🧙🏻",
- "🧙🏻",
- "🧙🏼",
- "🧙🏼",
- "🧙🏽",
- "🧙🏽",
- "🧙🏾",
- "🧙🏾",
- "🧙🏿",
- "🧙🏿",
- "🧙♀️",
- "🧙🏻♀️",
- "🧙🏻♀️",
- "🧙🏼♀️",
- "🧙🏼♀️",
- "🧙🏽♀️",
- "🧙🏽♀️",
- "🧙🏾♀️",
- "🧙🏾♀️",
- "🧙🏿♀️",
- "🧙🏿♀️",
- "🧙♂️",
- "🧙🏻♂️",
- "🧙🏻♂️",
- "🧙🏼♂️",
- "🧙🏼♂️",
- "🧙🏽♂️",
- "🧙🏽♂️",
- "🧙🏾♂️",
- "🧙🏾♂️",
- "🧙🏿♂️",
- "🧙🏿♂️",
- "🧝",
- "🧝🏻",
- "🧝🏻",
- "🧝🏼",
- "🧝🏼",
- "🧝🏽",
- "🧝🏽",
- "🧝🏾",
- "🧝🏾",
- "🧝🏿",
- "🧝🏿",
- "🧝♀️",
- "🧝🏻♀️",
- "🧝🏻♀️",
- "🧝🏼♀️",
- "🧝🏼♀️",
- "🧝🏽♀️",
- "🧝🏽♀️",
- "🧝🏾♀️",
- "🧝🏾♀️",
- "🧝🏿♀️",
- "🧝🏿♀️",
- "🧝♂️",
- "🧝🏻♂️",
- "🧝🏻♂️",
- "🧝🏼♂️",
- "🧝🏼♂️",
- "🧝🏽♂️",
- "🧝🏽♂️",
- "🧝🏾♂️",
- "🧝🏾♂️",
- "🧝🏿♂️",
- "🧝🏿♂️",
- "🧌",
- "🧛",
- "🧛🏻",
- "🧛🏻",
- "🧛🏼",
- "🧛🏼",
- "🧛🏽",
- "🧛🏽",
- "🧛🏾",
- "🧛🏾",
- "🧛🏿",
- "🧛🏿",
- "🧛♀️",
- "🧛🏻♀️",
- "🧛🏻♀️",
- "🧛🏼♀️",
- "🧛🏼♀️",
- "🧛🏽♀️",
- "🧛🏽♀️",
- "🧛🏾♀️",
- "🧛🏾♀️",
- "🧛🏿♀️",
- "🧛🏿♀️",
- "🧛♂️",
- "🧛🏻♂️",
- "🧛🏻♂️",
- "🧛🏼♂️",
- "🧛🏼♂️",
- "🧛🏽♂️",
- "🧛🏽♂️",
- "🧛🏾♂️",
- "🧛🏾♂️",
- "🧛🏿♂️",
- "🧛🏿♂️",
- "🧟",
- "🧟♀️",
- "🧟♂️",
- "🧞",
- "🧞♀️",
- "🧞♂️",
- "🧜",
- "🧜🏻",
- "🧜🏻",
- "🧜🏼",
- "🧜🏼",
- "🧜🏽",
- "🧜🏽",
- "🧜🏾",
- "🧜🏾",
- "🧜🏿",
- "🧜🏿",
- "🧜♀️",
- "🧜🏻♀️",
- "🧜🏻♀️",
- "🧜🏼♀️",
- "🧜🏼♀️",
- "🧜🏽♀️",
- "🧜🏽♀️",
- "🧜🏾♀️",
- "🧜🏾♀️",
- "🧜🏿♀️",
- "🧜🏿♀️",
- "🧜♂️",
- "🧜🏻♂️",
- "🧜🏻♂️",
- "🧜🏼♂️",
- "🧜🏼♂️",
- "🧜🏽♂️",
- "🧜🏽♂️",
- "🧜🏾♂️",
- "🧜🏾♂️",
- "🧜🏿♂️",
- "🧜🏿♂️",
- "🧚",
- "🧚🏻",
- "🧚🏻",
- "🧚🏼",
- "🧚🏼",
- "🧚🏽",
- "🧚🏽",
- "🧚🏾",
- "🧚🏾",
- "🧚🏿",
- "🧚🏿",
- "🧚♀️",
- "🧚🏻♀️",
- "🧚🏻♀️",
- "🧚🏼♀️",
- "🧚🏼♀️",
- "🧚🏽♀️",
- "🧚🏽♀️",
- "🧚🏾♀️",
- "🧚🏾♀️",
- "🧚🏿♀️",
- "🧚🏿♀️",
- "🧚♂️",
- "🧚🏻♂️",
- "🧚🏻♂️",
- "🧚🏼♂️",
- "🧚🏼♂️",
- "🧚🏽♂️",
- "🧚🏽♂️",
- "🧚🏾♂️",
- "🧚🏾♂️",
- "🧚🏿♂️",
- "🧚🏿♂️",
- "👼",
- "👼",
- "👼🏻",
- "👼🏼",
- "👼🏽",
- "👼🏾",
- "👼🏿",
- "🫄",
- "🫄🏻",
- "🫄🏻",
- "🫄🏼",
- "🫄🏼",
- "🫄🏽",
- "🫄🏽",
- "🫄🏾",
- "🫄🏾",
- "🫄🏿",
- "🫄🏿",
- "🤰",
- "🤰",
- "🤰🏻",
- "🤰🏻",
- "🤰🏼",
- "🤰🏼",
- "🤰🏽",
- "🤰🏽",
- "🤰🏾",
- "🤰🏾",
- "🤰🏿",
- "🤰🏿",
- "🫃",
- "🫃🏻",
- "🫃🏻",
- "🫃🏼",
- "🫃🏼",
- "🫃🏽",
- "🫃🏽",
- "🫃🏾",
- "🫃🏾",
- "🫃🏿",
- "🫃🏿",
- "🤱",
- "🤱🏻",
- "🤱🏻",
- "🤱🏼",
- "🤱🏼",
- "🤱🏽",
- "🤱🏽",
- "🤱🏾",
- "🤱🏾",
- "🤱🏿",
- "🤱🏿",
- "🧑🍼",
- "🧑🏻🍼",
- "🧑🏻🍼",
- "🧑🏼🍼",
- "🧑🏼🍼",
- "🧑🏽🍼",
- "🧑🏽🍼",
- "🧑🏾🍼",
- "🧑🏾🍼",
- "🧑🏿🍼",
- "🧑🏿🍼",
- "👩🍼",
- "👩🏻🍼",
- "👩🏻🍼",
- "👩🏼🍼",
- "👩🏼🍼",
- "👩🏽🍼",
- "👩🏽🍼",
- "👩🏾🍼",
- "👩🏾🍼",
- "👩🏿🍼",
- "👩🏿🍼",
- "👨🍼",
- "👨🏻🍼",
- "👨🏻🍼",
- "👨🏼🍼",
- "👨🏼🍼",
- "👨🏽🍼",
- "👨🏽🍼",
- "👨🏾🍼",
- "👨🏾🍼",
- "👨🏿🍼",
- "👨🏿🍼",
- "🙇",
- "🙇",
- "🙇🏻",
- "🙇🏻",
- "🙇🏼",
- "🙇🏼",
- "🙇🏽",
- "🙇🏽",
- "🙇🏾",
- "🙇🏾",
- "🙇🏿",
- "🙇🏿",
- "🙇♀️",
- "🙇🏻♀️",
- "🙇🏻♀️",
- "🙇🏼♀️",
- "🙇🏼♀️",
- "🙇🏽♀️",
- "🙇🏽♀️",
- "🙇🏾♀️",
- "🙇🏾♀️",
- "🙇🏿♀️",
- "🙇🏿♀️",
- "🙇♂️",
- "🙇🏻♂️",
- "🙇🏻♂️",
- "🙇🏼♂️",
- "🙇🏼♂️",
- "🙇🏽♂️",
- "🙇🏽♂️",
- "🙇🏾♂️",
- "🙇🏾♂️",
- "🙇🏿♂️",
- "🙇🏿♂️",
- "💁",
- "💁",
- "💁🏻",
- "💁🏻",
- "💁🏼",
- "💁🏼",
- "💁🏽",
- "💁🏽",
- "💁🏾",
- "💁🏾",
- "💁🏿",
- "💁🏿",
- "💁♀️",
- "💁🏻♀️",
- "💁🏻♀️",
- "💁🏼♀️",
- "💁🏼♀️",
- "💁🏽♀️",
- "💁🏽♀️",
- "💁🏾♀️",
- "💁🏾♀️",
- "💁🏿♀️",
- "💁🏿♀️",
- "💁♂️",
- "💁🏻♂️",
- "💁🏻♂️",
- "💁🏼♂️",
- "💁🏼♂️",
- "💁🏽♂️",
- "💁🏽♂️",
- "💁🏾♂️",
- "💁🏾♂️",
- "💁🏿♂️",
- "💁🏿♂️",
- "🙅",
- "🙅",
- "🙅🏻",
- "🙅🏻",
- "🙅🏼",
- "🙅🏼",
- "🙅🏽",
- "🙅🏽",
- "🙅🏾",
- "🙅🏾",
- "🙅🏿",
- "🙅🏿",
- "🙅♀️",
- "🙅🏻♀️",
- "🙅🏻♀️",
- "🙅🏼♀️",
- "🙅🏼♀️",
- "🙅🏽♀️",
- "🙅🏽♀️",
- "🙅🏾♀️",
- "🙅🏾♀️",
- "🙅🏿♀️",
- "🙅🏿♀️",
- "🙅♂️",
- "🙅🏻♂️",
- "🙅🏻♂️",
- "🙅🏼♂️",
- "🙅🏼♂️",
- "🙅🏽♂️",
- "🙅🏽♂️",
- "🙅🏾♂️",
- "🙅🏾♂️",
- "🙅🏿♂️",
- "🙅🏿♂️",
- "🙆",
- "🙆🏻",
- "🙆🏼",
- "🙆🏽",
- "🙆🏾",
- "🙆🏿",
- "🙆♀️",
- "🙆🏻♀️",
- "🙆🏻♀️",
- "🙆🏼♀️",
- "🙆🏼♀️",
- "🙆🏽♀️",
- "🙆🏽♀️",
- "🙆🏾♀️",
- "🙆🏾♀️",
- "🙆🏿♀️",
- "🙆🏿♀️",
- "🙆♂️",
- "🙆🏻♂️",
- "🙆🏻♂️",
- "🙆🏼♂️",
- "🙆🏼♂️",
- "🙆🏽♂️",
- "🙆🏽♂️",
- "🙆🏾♂️",
- "🙆🏾♂️",
- "🙆🏿♂️",
- "🙆🏿♂️",
- "🙋",
- "🙋",
- "🙋🏻",
- "🙋🏻",
- "🙋🏼",
- "🙋🏼",
- "🙋🏽",
- "🙋🏽",
- "🙋🏾",
- "🙋🏾",
- "🙋🏿",
- "🙋🏿",
- "🙋♀️",
- "🙋🏻♀️",
- "🙋🏻♀️",
- "🙋🏼♀️",
- "🙋🏼♀️",
- "🙋🏽♀️",
- "🙋🏽♀️",
- "🙋🏾♀️",
- "🙋🏾♀️",
- "🙋🏿♀️",
- "🙋🏿♀️",
- "🙋♂️",
- "🙋🏻♂️",
- "🙋🏻♂️",
- "🙋🏼♂️",
- "🙋🏼♂️",
- "🙋🏽♂️",
- "🙋🏽♂️",
- "🙋🏾♂️",
- "🙋🏾♂️",
- "🙋🏿♂️",
- "🙋🏿♂️",
- "🧏",
- "🧏🏻",
- "🧏🏻",
- "🧏🏼",
- "🧏🏼",
- "🧏🏽",
- "🧏🏽",
- "🧏🏾",
- "🧏🏾",
- "🧏🏿",
- "🧏🏿",
- "🧏♀️",
- "🧏🏻♀️",
- "🧏🏻♀️",
- "🧏🏼♀️",
- "🧏🏼♀️",
- "🧏🏽♀️",
- "🧏🏽♀️",
- "🧏🏾♀️",
- "🧏🏾♀️",
- "🧏🏿♀️",
- "🧏🏿♀️",
- "🧏♂️",
- "🧏🏻♂️",
- "🧏🏻♂️",
- "🧏🏼♂️",
- "🧏🏼♂️",
- "🧏🏽♂️",
- "🧏🏽♂️",
- "🧏🏾♂️",
- "🧏🏾♂️",
- "🧏🏿♂️",
- "🧏🏿♂️",
- "🤦",
- "🤦",
- "🤦",
- "🤦🏻",
- "🤦🏻",
- "🤦🏻",
- "🤦🏼",
- "🤦🏼",
- "🤦🏼",
- "🤦🏽",
- "🤦🏽",
- "🤦🏽",
- "🤦🏾",
- "🤦🏾",
- "🤦🏾",
- "🤦🏿",
- "🤦🏿",
- "🤦🏿",
- "🤦♀️",
- "🤦🏻♀️",
- "🤦🏻♀️",
- "🤦🏼♀️",
- "🤦🏼♀️",
- "🤦🏽♀️",
- "🤦🏽♀️",
- "🤦🏾♀️",
- "🤦🏾♀️",
- "🤦🏿♀️",
- "🤦🏿♀️",
- "🤦♂️",
- "🤦🏻♂️",
- "🤦🏻♂️",
- "🤦🏼♂️",
- "🤦🏼♂️",
- "🤦🏽♂️",
- "🤦🏽♂️",
- "🤦🏾♂️",
- "🤦🏾♂️",
- "🤦🏿♂️",
- "🤦🏿♂️",
- "🤷",
- "🤷",
- "🤷🏻",
- "🤷🏻",
- "🤷🏼",
- "🤷🏼",
- "🤷🏽",
- "🤷🏽",
- "🤷🏾",
- "🤷🏾",
- "🤷🏿",
- "🤷🏿",
- "🤷♀️",
- "🤷🏻♀️",
- "🤷🏻♀️",
- "🤷🏼♀️",
- "🤷🏼♀️",
- "🤷🏽♀️",
- "🤷🏽♀️",
- "🤷🏾♀️",
- "🤷🏾♀️",
- "🤷🏿♀️",
- "🤷🏿♀️",
- "🤷♂️",
- "🤷🏻♂️",
- "🤷🏻♂️",
- "🤷🏼♂️",
- "🤷🏼♂️",
- "🤷🏽♂️",
- "🤷🏽♂️",
- "🤷🏾♂️",
- "🤷🏾♂️",
- "🤷🏿♂️",
- "🤷🏿♂️",
- "🙎",
- "🙎",
- "🙎🏻",
- "🙎🏻",
- "🙎🏼",
- "🙎🏼",
- "🙎🏽",
- "🙎🏽",
- "🙎🏾",
- "🙎🏾",
- "🙎🏿",
- "🙎🏿",
- "🙎♀️",
- "🙎🏻♀️",
- "🙎🏻♀️",
- "🙎🏼♀️",
- "🙎🏼♀️",
- "🙎🏽♀️",
- "🙎🏽♀️",
- "🙎🏾♀️",
- "🙎🏾♀️",
- "🙎🏿♀️",
- "🙎🏿♀️",
- "🙎♂️",
- "🙎🏻♂️",
- "🙎🏻♂️",
- "🙎🏼♂️",
- "🙎🏼♂️",
- "🙎🏽♂️",
- "🙎🏽♂️",
- "🙎🏾♂️",
- "🙎🏾♂️",
- "🙎🏿♂️",
- "🙎🏿♂️",
- "🙍",
- "🙍🏻",
- "🙍🏼",
- "🙍🏽",
- "🙍🏾",
- "🙍🏿",
- "🙍♀️",
- "🙍🏻♀️",
- "🙍🏻♀️",
- "🙍🏼♀️",
- "🙍🏼♀️",
- "🙍🏽♀️",
- "🙍🏽♀️",
- "🙍🏾♀️",
- "🙍🏾♀️",
- "🙍🏿♀️",
- "🙍🏿♀️",
- "🙍♂️",
- "🙍🏻♂️",
- "🙍🏻♂️",
- "🙍🏼♂️",
- "🙍🏼♂️",
- "🙍🏽♂️",
- "🙍🏽♂️",
- "🙍🏾♂️",
- "🙍🏾♂️",
- "🙍🏿♂️",
- "🙍🏿♂️",
- "💇",
- "💇",
- "💇🏻",
- "💇🏻",
- "💇🏼",
- "💇🏼",
- "💇🏽",
- "💇🏽",
- "💇🏾",
- "💇🏾",
- "💇🏿",
- "💇🏿",
- "💇♀️",
- "💇🏻♀️",
- "💇🏻♀️",
- "💇🏼♀️",
- "💇🏼♀️",
- "💇🏽♀️",
- "💇🏽♀️",
- "💇🏾♀️",
- "💇🏾♀️",
- "💇🏿♀️",
- "💇🏿♀️",
- "💇♂️",
- "💇🏻♂️",
- "💇🏻♂️",
- "💇🏼♂️",
- "💇🏼♂️",
- "💇🏽♂️",
- "💇🏽♂️",
- "💇🏾♂️",
- "💇🏾♂️",
- "💇🏿♂️",
- "💇🏿♂️",
- "💆",
- "💆",
- "💆🏻",
- "💆🏻",
- "💆🏼",
- "💆🏼",
- "💆🏽",
- "💆🏽",
- "💆🏾",
- "💆🏾",
- "💆🏿",
- "💆🏿",
- "💆♀️",
- "💆🏻♀️",
- "💆🏻♀️",
- "💆🏼♀️",
- "💆🏼♀️",
- "💆🏽♀️",
- "💆🏽♀️",
- "💆🏾♀️",
- "💆🏾♀️",
- "💆🏿♀️",
- "💆🏿♀️",
- "💆♂️",
- "💆🏻♂️",
- "💆🏻♂️",
- "💆🏼♂️",
- "💆🏼♂️",
- "💆🏽♂️",
- "💆🏽♂️",
- "💆🏾♂️",
- "💆🏾♂️",
- "💆🏿♂️",
- "💆🏿♂️",
- "🧖",
- "🧖🏻",
- "🧖🏻",
- "🧖🏼",
- "🧖🏼",
- "🧖🏽",
- "🧖🏽",
- "🧖🏾",
- "🧖🏾",
- "🧖🏿",
- "🧖🏿",
- "🧖♀️",
- "🧖🏻♀️",
- "🧖🏻♀️",
- "🧖🏼♀️",
- "🧖🏼♀️",
- "🧖🏽♀️",
- "🧖🏽♀️",
- "🧖🏾♀️",
- "🧖🏾♀️",
- "🧖🏿♀️",
- "🧖🏿♀️",
- "🧖♂️",
- "🧖🏻♂️",
- "🧖🏻♂️",
- "🧖🏼♂️",
- "🧖🏼♂️",
- "🧖🏽♂️",
- "🧖🏽♂️",
- "🧖🏾♂️",
- "🧖🏾♂️",
- "🧖🏿♂️",
- "🧖🏿♂️",
- "💅",
- "💅",
- "💅🏻",
- "💅🏼",
- "💅🏽",
- "💅🏾",
- "💅🏿",
- "🤳",
- "🤳🏻",
- "🤳🏼",
- "🤳🏽",
- "🤳🏾",
- "🤳🏿",
- "💃",
- "💃",
- "💃🏻",
- "💃🏼",
- "💃🏽",
- "💃🏾",
- "💃🏿",
- "🕺",
- "🕺",
- "🕺🏻",
- "🕺🏻",
- "🕺🏼",
- "🕺🏼",
- "🕺🏽",
- "🕺🏽",
- "🕺🏿",
- "🕺🏿",
- "🕺🏾",
- "🕺🏾",
- "👯",
- "👯",
- "👯♀️",
- "👯♂️",
- "🕴️",
- "🕴️",
- "🕴🏻",
- "🕴🏻",
- "🕴🏻",
- "🕴🏼",
- "🕴🏼",
- "🕴🏼",
- "🕴🏽",
- "🕴🏽",
- "🕴🏽",
- "🕴🏾",
- "🕴🏾",
- "🕴🏾",
- "🕴🏿",
- "🕴🏿",
- "🕴🏿",
- "🧑🦽",
- "🧑🏻🦽",
- "🧑🏻🦽",
- "🧑🏼🦽",
- "🧑🏼🦽",
- "🧑🏽🦽",
- "🧑🏽🦽",
- "🧑🏾🦽",
- "🧑🏾🦽",
- "🧑🏿🦽",
- "🧑🏿🦽",
- "👩🦽",
- "👩🏻🦽",
- "👩🏻🦽",
- "👩🏼🦽",
- "👩🏼🦽",
- "👩🏽🦽",
- "👩🏽🦽",
- "👩🏾🦽",
- "👩🏾🦽",
- "👩🏿🦽",
- "👩🏿🦽",
- "👨🦽",
- "👨🏻🦽",
- "👨🏻🦽",
- "👨🏼🦽",
- "👨🏼🦽",
- "👨🏽🦽",
- "👨🏽🦽",
- "👨🏾🦽",
- "👨🏾🦽",
- "👨🏿🦽",
- "👨🏿🦽",
- "🧑🦼",
- "🧑🏻🦼",
- "🧑🏻🦼",
- "🧑🏼🦼",
- "🧑🏼🦼",
- "🧑🏽🦼",
- "🧑🏽🦼",
- "🧑🏾🦼",
- "🧑🏾🦼",
- "🧑🏿🦼",
- "🧑🏿🦼",
- "👩🦼",
- "👩🏻🦼",
- "👩🏻🦼",
- "👩🏼🦼",
- "👩🏼🦼",
- "👩🏽🦼",
- "👩🏽🦼",
- "👩🏾🦼",
- "👩🏾🦼",
- "👩🏿🦼",
- "👩🏿🦼",
- "👨🦼",
- "👨🏻🦼",
- "👨🏻🦼",
- "👨🏼🦼",
- "👨🏼🦼",
- "👨🏽🦼",
- "👨🏽🦼",
- "👨🏾🦼",
- "👨🏾🦼",
- "👨🏿🦼",
- "👨🏿🦼",
- "🚶",
- "🚶",
- "🚶🏻",
- "🚶🏻",
- "🚶🏼",
- "🚶🏼",
- "🚶🏽",
- "🚶🏽",
- "🚶🏾",
- "🚶🏾",
- "🚶🏿",
- "🚶🏿",
- "🚶♀️",
- "🚶🏻♀️",
- "🚶🏻♀️",
- "🚶🏼♀️",
- "🚶🏼♀️",
- "🚶🏽♀️",
- "🚶🏽♀️",
- "🚶🏾♀️",
- "🚶🏾♀️",
- "🚶🏿♀️",
- "🚶🏿♀️",
- "🚶♂️",
- "🚶🏻♂️",
- "🚶🏻♂️",
- "🚶🏼♂️",
- "🚶🏼♂️",
- "🚶🏽♂️",
- "🚶🏽♂️",
- "🚶🏾♂️",
- "🚶🏾♂️",
- "🚶🏿♂️",
- "🚶🏿♂️",
- "🧑🦯",
- "🧑🏻🦯",
- "🧑🏻🦯",
- "🧑🏼🦯",
- "🧑🏼🦯",
- "🧑🏽🦯",
- "🧑🏽🦯",
- "🧑🏾🦯",
- "🧑🏾🦯",
- "🧑🏿🦯",
- "🧑🏿🦯",
- "👩🦯",
- "👩🏻🦯",
- "👩🏻🦯",
- "👩🏼🦯",
- "👩🏼🦯",
- "👩🏽🦯",
- "👩🏽🦯",
- "👩🏾🦯",
- "👩🏾🦯",
- "👩🏿🦯",
- "👩🏿🦯",
- "👨🦯",
- "👨🏻🦯",
- "👨🏻🦯",
- "👨🏼🦯",
- "👨🏼🦯",
- "👨🏽🦯",
- "👨🏽🦯",
- "👨🏾🦯",
- "👨🏾🦯",
- "👨🏿🦯",
- "👨🏿🦯",
- "🧎",
- "🧎🏻",
- "🧎🏻",
- "🧎🏼",
- "🧎🏼",
- "🧎🏽",
- "🧎🏽",
- "🧎🏾",
- "🧎🏾",
- "🧎🏿",
- "🧎🏿",
- "🧎♀️",
- "🧎🏻♀️",
- "🧎🏻♀️",
- "🧎🏼♀️",
- "🧎🏼♀️",
- "🧎🏽♀️",
- "🧎🏽♀️",
- "🧎🏾♀️",
- "🧎🏾♀️",
- "🧎🏿♀️",
- "🧎🏿♀️",
- "🧎♂️",
- "🧎🏻♂️",
- "🧎🏻♂️",
- "🧎🏼♂️",
- "🧎🏼♂️",
- "🧎🏽♂️",
- "🧎🏽♂️",
- "🧎🏾♂️",
- "🧎🏾♂️",
- "🧎🏿♂️",
- "🧎🏿♂️",
- "🏃",
- "🏃",
- "🏃🏻",
- "🏃🏻",
- "🏃🏼",
- "🏃🏼",
- "🏃🏽",
- "🏃🏽",
- "🏃🏾",
- "🏃🏾",
- "🏃🏿",
- "🏃🏿",
- "🏃♀️",
- "🏃🏻♀️",
- "🏃🏻♀️",
- "🏃🏼♀️",
- "🏃🏼♀️",
- "🏃🏽♀️",
- "🏃🏽♀️",
- "🏃🏾♀️",
- "🏃🏾♀️",
- "🏃🏿♀️",
- "🏃🏿♀️",
- "🏃♂️",
- "🏃🏻♂️",
- "🏃🏻♂️",
- "🏃🏼♂️",
- "🏃🏼♂️",
- "🏃🏽♂️",
- "🏃🏽♂️",
- "🏃🏾♂️",
- "🏃🏾♂️",
- "🏃🏿♂️",
- "🏃🏿♂️",
- "🧍",
- "🧍🏻",
- "🧍🏻",
- "🧍🏼",
- "🧍🏼",
- "🧍🏽",
- "🧍🏽",
- "🧍🏾",
- "🧍🏾",
- "🧍🏿",
- "🧍🏿",
- "🧍♀️",
- "🧍🏻♀️",
- "🧍🏻♀️",
- "🧍🏼♀️",
- "🧍🏼♀️",
- "🧍🏽♀️",
- "🧍🏽♀️",
- "🧍🏾♀️",
- "🧍🏾♀️",
- "🧍🏿♀️",
- "🧍🏿♀️",
- "🧍♂️",
- "🧍🏻♂️",
- "🧍🏻♂️",
- "🧍🏼♂️",
- "🧍🏼♂️",
- "🧍🏽♂️",
- "🧍🏽♂️",
- "🧍🏾♂️",
- "🧍🏾♂️",
- "🧍🏿♂️",
- "🧍🏿♂️",
- "🧑🤝🧑",
- "🧑🏻🤝🧑🏻",
- "🧑🏻🤝🧑🏻",
- "🧑🏻🤝🧑🏼",
- "🧑🏻🤝🧑🏼",
- "🧑🏻🤝🧑🏽",
- "🧑🏻🤝🧑🏽",
- "🧑🏻🤝🧑🏾",
- "🧑🏻🤝🧑🏾",
- "🧑🏻🤝🧑🏿",
- "🧑🏻🤝🧑🏿",
- "🧑🏼🤝🧑🏻",
- "🧑🏼🤝🧑🏻",
- "🧑🏼🤝🧑🏼",
- "🧑🏼🤝🧑🏼",
- "🧑🏼🤝🧑🏽",
- "🧑🏼🤝🧑🏽",
- "🧑🏼🤝🧑🏾",
- "🧑🏼🤝🧑🏾",
- "🧑🏼🤝🧑🏿",
- "🧑🏼🤝🧑🏿",
- "🧑🏽🤝🧑🏻",
- "🧑🏽🤝🧑🏻",
- "🧑🏽🤝🧑🏼",
- "🧑🏽🤝🧑🏼",
- "🧑🏽🤝🧑🏽",
- "🧑🏽🤝🧑🏽",
- "🧑🏽🤝🧑🏾",
- "🧑🏽🤝🧑🏾",
- "🧑🏽🤝🧑🏿",
- "🧑🏽🤝🧑🏿",
- "🧑🏾🤝🧑🏻",
- "🧑🏾🤝🧑🏻",
- "🧑🏾🤝🧑🏼",
- "🧑🏾🤝🧑🏼",
- "🧑🏾🤝🧑🏽",
- "🧑🏾🤝🧑🏽",
- "🧑🏾🤝🧑🏾",
- "🧑🏾🤝🧑🏾",
- "🧑🏾🤝🧑🏿",
- "🧑🏾🤝🧑🏿",
- "🧑🏿🤝🧑🏻",
- "🧑🏿🤝🧑🏻",
- "🧑🏿🤝🧑🏼",
- "🧑🏿🤝🧑🏼",
- "🧑🏿🤝🧑🏽",
- "🧑🏿🤝🧑🏽",
- "🧑🏿🤝🧑🏾",
- "🧑🏿🤝🧑🏾",
- "🧑🏿🤝🧑🏿",
- "🧑🏿🤝🧑🏿",
- "👫",
- "👫🏻",
- "👫🏻",
- "👩🏻🤝👨🏼",
- "👩🏻🤝👨🏼",
- "👩🏻🤝👨🏽",
- "👩🏻🤝👨🏽",
- "👩🏻🤝👨🏾",
- "👩🏻🤝👨🏾",
- "👩🏻🤝👨🏿",
- "👩🏻🤝👨🏿",
- "👩🏼🤝👨🏻",
- "👩🏼🤝👨🏻",
- "👫🏼",
- "👫🏼",
- "👩🏼🤝👨🏽",
- "👩🏼🤝👨🏽",
- "👩🏼🤝👨🏾",
- "👩🏼🤝👨🏾",
- "👩🏼🤝👨🏿",
- "👩🏼🤝👨🏿",
- "👩🏽🤝👨🏻",
- "👩🏽🤝👨🏻",
- "👩🏽🤝👨🏼",
- "👩🏽🤝👨🏼",
- "👫🏽",
- "👫🏽",
- "👩🏽🤝👨🏾",
- "👩🏽🤝👨🏾",
- "👩🏽🤝👨🏿",
- "👩🏽🤝👨🏿",
- "👩🏾🤝👨🏻",
- "👩🏾🤝👨🏻",
- "👩🏾🤝👨🏼",
- "👩🏾🤝👨🏼",
- "👩🏾🤝👨🏽",
- "👩🏾🤝👨🏽",
- "👫🏾",
- "👫🏾",
- "👩🏾🤝👨🏿",
- "👩🏾🤝👨🏿",
- "👩🏿🤝👨🏻",
- "👩🏿🤝👨🏻",
- "👩🏿🤝👨🏼",
- "👩🏿🤝👨🏼",
- "👩🏿🤝👨🏽",
- "👩🏿🤝👨🏽",
- "👩🏿🤝👨🏾",
- "👩🏿🤝👨🏾",
- "👫🏿",
- "👫🏿",
- "👭",
- "👭🏻",
- "👭🏻",
- "👩🏻🤝👩🏼",
- "👩🏻🤝👩🏼",
- "👩🏻🤝👩🏽",
- "👩🏻🤝👩🏽",
- "👩🏻🤝👩🏾",
- "👩🏻🤝👩🏾",
- "👩🏻🤝👩🏿",
- "👩🏻🤝👩🏿",
- "👩🏼🤝👩🏻",
- "👩🏼🤝👩🏻",
- "👭🏼",
- "👭🏼",
- "👩🏼🤝👩🏽",
- "👩🏼🤝👩🏽",
- "👩🏼🤝👩🏾",
- "👩🏼🤝👩🏾",
- "👩🏼🤝👩🏿",
- "👩🏼🤝👩🏿",
- "👩🏽🤝👩🏻",
- "👩🏽🤝👩🏻",
- "👩🏽🤝👩🏼",
- "👩🏽🤝👩🏼",
- "👭🏽",
- "👭🏽",
- "👩🏽🤝👩🏾",
- "👩🏽🤝👩🏾",
- "👩🏽🤝👩🏿",
- "👩🏽🤝👩🏿",
- "👩🏾🤝👩🏻",
- "👩🏾🤝👩🏻",
- "👩🏾🤝👩🏼",
- "👩🏾🤝👩🏼",
- "👩🏾🤝👩🏽",
- "👩🏾🤝👩🏽",
- "👭🏾",
- "👭🏾",
- "👩🏾🤝👩🏿",
- "👩🏾🤝👩🏿",
- "👩🏿🤝👩🏻",
- "👩🏿🤝👩🏻",
- "👩🏿🤝👩🏼",
- "👩🏿🤝👩🏼",
- "👩🏿🤝👩🏽",
- "👩🏿🤝👩🏽",
- "👩🏿🤝👩🏾",
- "👩🏿🤝👩🏾",
- "👭🏿",
- "👭🏿",
- "👬",
- "👬🏻",
- "👬🏻",
- "👨🏻🤝👨🏼",
- "👨🏻🤝👨🏼",
- "👨🏻🤝👨🏽",
- "👨🏻🤝👨🏽",
- "👨🏻🤝👨🏾",
- "👨🏻🤝👨🏾",
- "👨🏻🤝👨🏿",
- "👨🏻🤝👨🏿",
- "👨🏼🤝👨🏻",
- "👨🏼🤝👨🏻",
- "👬🏼",
- "👬🏼",
- "👨🏼🤝👨🏽",
- "👨🏼🤝👨🏽",
- "👨🏼🤝👨🏾",
- "👨🏼🤝👨🏾",
- "👨🏼🤝👨🏿",
- "👨🏼🤝👨🏿",
- "👨🏽🤝👨🏻",
- "👨🏽🤝👨🏻",
- "👨🏽🤝👨🏼",
- "👨🏽🤝👨🏼",
- "👬🏽",
- "👬🏽",
- "👨🏽🤝👨🏾",
- "👨🏽🤝👨🏾",
- "👨🏽🤝👨🏿",
- "👨🏽🤝👨🏿",
- "👨🏾🤝👨🏻",
- "👨🏾🤝👨🏻",
- "👨🏾🤝👨🏼",
- "👨🏾🤝👨🏼",
- "👨🏾🤝👨🏽",
- "👨🏾🤝👨🏽",
- "👬🏾",
- "👬🏾",
- "👨🏾🤝👨🏿",
- "👨🏾🤝👨🏿",
- "👨🏿🤝👨🏻",
- "👨🏿🤝👨🏻",
- "👨🏿🤝👨🏼",
- "👨🏿🤝👨🏼",
- "👨🏿🤝👨🏽",
- "👨🏿🤝👨🏽",
- "👨🏿🤝👨🏾",
- "👨🏿🤝👨🏾",
- "👬🏿",
- "👬🏿",
- "💑",
- "💑🏻",
- "💑🏻",
- "🧑🏻❤️🧑🏼",
- "🧑🏻❤️🧑🏼",
- "🧑🏻❤️🧑🏽",
- "🧑🏻❤️🧑🏽",
- "🧑🏻❤️🧑🏾",
- "🧑🏻❤️🧑🏾",
- "🧑🏻❤️🧑🏿",
- "🧑🏻❤️🧑🏿",
- "🧑🏼❤️🧑🏻",
- "🧑🏼❤️🧑🏻",
- "💑🏼",
- "💑🏼",
- "🧑🏼❤️🧑🏽",
- "🧑🏼❤️🧑🏽",
- "🧑🏼❤️🧑🏾",
- "🧑🏼❤️🧑🏾",
- "🧑🏼❤️🧑🏿",
- "🧑🏼❤️🧑🏿",
- "🧑🏽❤️🧑🏻",
- "🧑🏽❤️🧑🏻",
- "🧑🏽❤️🧑🏼",
- "🧑🏽❤️🧑🏼",
- "💑🏽",
- "💑🏽",
- "🧑🏽❤️🧑🏾",
- "🧑🏽❤️🧑🏾",
- "🧑🏽❤️🧑🏿",
- "🧑🏽❤️🧑🏿",
- "🧑🏾❤️🧑🏻",
- "🧑🏾❤️🧑🏻",
- "🧑🏾❤️🧑🏼",
- "🧑🏾❤️🧑🏼",
- "🧑🏾❤️🧑🏽",
- "🧑🏾❤️🧑🏽",
- "💑🏾",
- "💑🏾",
- "🧑🏾❤️🧑🏿",
- "🧑🏾❤️🧑🏿",
- "🧑🏿❤️🧑🏻",
- "🧑🏿❤️🧑🏻",
- "🧑🏿❤️🧑🏼",
- "🧑🏿❤️🧑🏼",
- "🧑🏿❤️🧑🏽",
- "🧑🏿❤️🧑🏽",
- "🧑🏿❤️🧑🏾",
- "🧑🏿❤️🧑🏾",
- "💑🏿",
- "💑🏿",
- "👩❤️👨",
- "👩🏻❤️👨🏻",
- "👩🏻❤️👨🏻",
- "👩🏻❤️👨🏼",
- "👩🏻❤️👨🏼",
- "👩🏻❤️👨🏽",
- "👩🏻❤️👨🏽",
- "👩🏻❤️👨🏾",
- "👩🏻❤️👨🏾",
- "👩🏻❤️👨🏿",
- "👩🏻❤️👨🏿",
- "👩🏼❤️👨🏻",
- "👩🏼❤️👨🏻",
- "👩🏼❤️👨🏼",
- "👩🏼❤️👨🏼",
- "👩🏼❤️👨🏽",
- "👩🏼❤️👨🏽",
- "👩🏼❤️👨🏾",
- "👩🏼❤️👨🏾",
- "👩🏼❤️👨🏿",
- "👩🏼❤️👨🏿",
- "👩🏽❤️👨🏻",
- "👩🏽❤️👨🏻",
- "👩🏽❤️👨🏼",
- "👩🏽❤️👨🏼",
- "👩🏽❤️👨🏽",
- "👩🏽❤️👨🏽",
- "👩🏽❤️👨🏾",
- "👩🏽❤️👨🏾",
- "👩🏽❤️👨🏿",
- "👩🏽❤️👨🏿",
- "👩🏾❤️👨🏻",
- "👩🏾❤️👨🏻",
- "👩🏾❤️👨🏼",
- "👩🏾❤️👨🏼",
- "👩🏾❤️👨🏽",
- "👩🏾❤️👨🏽",
- "👩🏾❤️👨🏾",
- "👩🏾❤️👨🏾",
- "👩🏾❤️👨🏿",
- "👩🏾❤️👨🏿",
- "👩🏿❤️👨🏻",
- "👩🏿❤️👨🏻",
- "👩🏿❤️👨🏼",
- "👩🏿❤️👨🏼",
- "👩🏿❤️👨🏽",
- "👩🏿❤️👨🏽",
- "👩🏿❤️👨🏾",
- "👩🏿❤️👨🏾",
- "👩🏿❤️👨🏿",
- "👩🏿❤️👨🏿",
- "👩❤️👩",
- "👩❤️👩",
- "👩🏻❤️👩🏻",
- "👩🏻❤️👩🏻",
- "👩🏻❤️👩🏼",
- "👩🏻❤️👩🏼",
- "👩🏻❤️👩🏽",
- "👩🏻❤️👩🏽",
- "👩🏻❤️👩🏾",
- "👩🏻❤️👩🏾",
- "👩🏻❤️👩🏿",
- "👩🏻❤️👩🏿",
- "👩🏼❤️👩🏻",
- "👩🏼❤️👩🏻",
- "👩🏼❤️👩🏼",
- "👩🏼❤️👩🏼",
- "👩🏼❤️👩🏽",
- "👩🏼❤️👩🏽",
- "👩🏼❤️👩🏾",
- "👩🏼❤️👩🏾",
- "👩🏼❤️👩🏿",
- "👩🏼❤️👩🏿",
- "👩🏽❤️👩🏻",
- "👩🏽❤️👩🏻",
- "👩🏽❤️👩🏼",
- "👩🏽❤️👩🏼",
- "👩🏽❤️👩🏽",
- "👩🏽❤️👩🏽",
- "👩🏽❤️👩🏾",
- "👩🏽❤️👩🏾",
- "👩🏽❤️👩🏿",
- "👩🏽❤️👩🏿",
- "👩🏾❤️👩🏻",
- "👩🏾❤️👩🏻",
- "👩🏾❤️👩🏼",
- "👩🏾❤️👩🏼",
- "👩🏾❤️👩🏽",
- "👩🏾❤️👩🏽",
- "👩🏾❤️👩🏾",
- "👩🏾❤️👩🏾",
- "👩🏾❤️👩🏿",
- "👩🏾❤️👩🏿",
- "👩🏿❤️👩🏻",
- "👩🏿❤️👩🏻",
- "👩🏿❤️👩🏼",
- "👩🏿❤️👩🏼",
- "👩🏿❤️👩🏽",
- "👩🏿❤️👩🏽",
- "👩🏿❤️👩🏾",
- "👩🏿❤️👩🏾",
- "👩🏿❤️👩🏿",
- "👩🏿❤️👩🏿",
- "👨❤️👨",
- "👨❤️👨",
- "👨🏻❤️👨🏻",
- "👨🏻❤️👨🏻",
- "👨🏻❤️👨🏼",
- "👨🏻❤️👨🏼",
- "👨🏻❤️👨🏽",
- "👨🏻❤️👨🏽",
- "👨🏻❤️👨🏾",
- "👨🏻❤️👨🏾",
- "👨🏻❤️👨🏿",
- "👨🏻❤️👨🏿",
- "👨🏼❤️👨🏻",
- "👨🏼❤️👨🏻",
- "👨🏼❤️👨🏼",
- "👨🏼❤️👨🏼",
- "👨🏼❤️👨🏽",
- "👨🏼❤️👨🏽",
- "👨🏼❤️👨🏾",
- "👨🏼❤️👨🏾",
- "👨🏼❤️👨🏿",
- "👨🏼❤️👨🏿",
- "👨🏽❤️👨🏻",
- "👨🏽❤️👨🏻",
- "👨🏽❤️👨🏼",
- "👨🏽❤️👨🏼",
- "👨🏽❤️👨🏽",
- "👨🏽❤️👨🏽",
- "👨🏽❤️👨🏾",
- "👨🏽❤️👨🏾",
- "👨🏽❤️👨🏿",
- "👨🏽❤️👨🏿",
- "👨🏾❤️👨🏻",
- "👨🏾❤️👨🏻",
- "👨🏾❤️👨🏼",
- "👨🏾❤️👨🏼",
- "👨🏾❤️👨🏽",
- "👨🏾❤️👨🏽",
- "👨🏾❤️👨🏾",
- "👨🏾❤️👨🏾",
- "👨🏾❤️👨🏿",
- "👨🏾❤️👨🏿",
- "👨🏿❤️👨🏻",
- "👨🏿❤️👨🏻",
- "👨🏿❤️👨🏼",
- "👨🏿❤️👨🏼",
- "👨🏿❤️👨🏽",
- "👨🏿❤️👨🏽",
- "👨🏿❤️👨🏾",
- "👨🏿❤️👨🏾",
- "👨🏿❤️👨🏿",
- "👨🏿❤️👨🏿",
- "💏",
- "💏🏻",
- "💏🏻",
- "🧑🏻❤️💋🧑🏼",
- "🧑🏻❤️💋🧑🏼",
- "🧑🏻❤️💋🧑🏽",
- "🧑🏻❤️💋🧑🏽",
- "🧑🏻❤️💋🧑🏾",
- "🧑🏻❤️💋🧑🏾",
- "🧑🏻❤️💋🧑🏿",
- "🧑🏻❤️💋🧑🏿",
- "🧑🏼❤️💋🧑🏻",
- "🧑🏼❤️💋🧑🏻",
- "💏🏼",
- "💏🏼",
- "🧑🏼❤️💋🧑🏽",
- "🧑🏼❤️💋🧑🏽",
- "🧑🏼❤️💋🧑🏾",
- "🧑🏼❤️💋🧑🏾",
- "🧑🏼❤️💋🧑🏿",
- "🧑🏼❤️💋🧑🏿",
- "🧑🏽❤️💋🧑🏻",
- "🧑🏽❤️💋🧑🏻",
- "🧑🏽❤️💋🧑🏼",
- "🧑🏽❤️💋🧑🏼",
- "💏🏽",
- "💏🏽",
- "🧑🏽❤️💋🧑🏾",
- "🧑🏽❤️💋🧑🏾",
- "🧑🏽❤️💋🧑🏿",
- "🧑🏽❤️💋🧑🏿",
- "🧑🏾❤️💋🧑🏻",
- "🧑🏾❤️💋🧑🏻",
- "🧑🏾❤️💋🧑🏼",
- "🧑🏾❤️💋🧑🏼",
- "🧑🏾❤️💋🧑🏽",
- "🧑🏾❤️💋🧑🏽",
- "💏🏾",
- "💏🏾",
- "🧑🏾❤️💋🧑🏿",
- "🧑🏾❤️💋🧑🏿",
- "🧑🏿❤️💋🧑🏻",
- "🧑🏿❤️💋🧑🏻",
- "🧑🏿❤️💋🧑🏼",
- "🧑🏿❤️💋🧑🏼",
- "🧑🏿❤️💋🧑🏽",
- "🧑🏿❤️💋🧑🏽",
- "🧑🏿❤️💋🧑🏾",
- "🧑🏿❤️💋🧑🏾",
- "💏🏿",
- "💏🏿",
- "👩❤️💋👨",
- "👩🏻❤️💋👨🏻",
- "👩🏻❤️💋👨🏻",
- "👩🏻❤️💋👨🏼",
- "👩🏻❤️💋👨🏼",
- "👩🏻❤️💋👨🏽",
- "👩🏻❤️💋👨🏽",
- "👩🏻❤️💋👨🏾",
- "👩🏻❤️💋👨🏾",
- "👩🏻❤️💋👨🏿",
- "👩🏻❤️💋👨🏿",
- "👩🏼❤️💋👨🏻",
- "👩🏼❤️💋👨🏻",
- "👩🏼❤️💋👨🏼",
- "👩🏼❤️💋👨🏼",
- "👩🏼❤️💋👨🏽",
- "👩🏼❤️💋👨🏽",
- "👩🏼❤️💋👨🏾",
- "👩🏼❤️💋👨🏾",
- "👩🏼❤️💋👨🏿",
- "👩🏼❤️💋👨🏿",
- "👩🏽❤️💋👨🏻",
- "👩🏽❤️💋👨🏻",
- "👩🏽❤️💋👨🏼",
- "👩🏽❤️💋👨🏼",
- "👩🏽❤️💋👨🏽",
- "👩🏽❤️💋👨🏽",
- "👩🏽❤️💋👨🏾",
- "👩🏽❤️💋👨🏾",
- "👩🏽❤️💋👨🏿",
- "👩🏽❤️💋👨🏿",
- "👩🏾❤️💋👨🏻",
- "👩🏾❤️💋👨🏻",
- "👩🏾❤️💋👨🏼",
- "👩🏾❤️💋👨🏼",
- "👩🏾❤️💋👨🏽",
- "👩🏾❤️💋👨🏽",
- "👩🏾❤️💋👨🏾",
- "👩🏾❤️💋👨🏾",
- "👩🏾❤️💋👨🏿",
- "👩🏾❤️💋👨🏿",
- "👩🏿❤️💋👨🏻",
- "👩🏿❤️💋👨🏻",
- "👩🏿❤️💋👨🏼",
- "👩🏿❤️💋👨🏼",
- "👩🏿❤️💋👨🏽",
- "👩🏿❤️💋👨🏽",
- "👩🏿❤️💋👨🏾",
- "👩🏿❤️💋👨🏾",
- "👩🏿❤️💋👨🏿",
- "👩🏿❤️💋👨🏿",
- "👩❤️💋👩",
- "👩❤️💋👩",
- "👩🏻❤️💋👩🏻",
- "👩🏻❤️💋👩🏻",
- "👩🏻❤️💋👩🏼",
- "👩🏻❤️💋👩🏼",
- "👩🏻❤️💋👩🏽",
- "👩🏻❤️💋👩🏽",
- "👩🏻❤️💋👩🏾",
- "👩🏻❤️💋👩🏾",
- "👩🏻❤️💋👩🏿",
- "👩🏻❤️💋👩🏿",
- "👩🏼❤️💋👩🏻",
- "👩🏼❤️💋👩🏻",
- "👩🏼❤️💋👩🏼",
- "👩🏼❤️💋👩🏼",
- "👩🏼❤️💋👩🏽",
- "👩🏼❤️💋👩🏽",
- "👩🏼❤️💋👩🏾",
- "👩🏼❤️💋👩🏾",
- "👩🏼❤️💋👩🏿",
- "👩🏼❤️💋👩🏿",
- "👩🏽❤️💋👩🏻",
- "👩🏽❤️💋👩🏻",
- "👩🏽❤️💋👩🏼",
- "👩🏽❤️💋👩🏼",
- "👩🏽❤️💋👩🏽",
- "👩🏽❤️💋👩🏽",
- "👩🏽❤️💋👩🏾",
- "👩🏽❤️💋👩🏾",
- "👩🏽❤️💋👩🏿",
- "👩🏽❤️💋👩🏿",
- "👩🏾❤️💋👩🏻",
- "👩🏾❤️💋👩🏻",
- "👩🏾❤️💋👩🏼",
- "👩🏾❤️💋👩🏼",
- "👩🏾❤️💋👩🏽",
- "👩🏾❤️💋👩🏽",
- "👩🏾❤️💋👩🏾",
- "👩🏾❤️💋👩🏾",
- "👩🏾❤️💋👩🏿",
- "👩🏾❤️💋👩🏿",
- "👩🏿❤️💋👩🏻",
- "👩🏿❤️💋👩🏻",
- "👩🏿❤️💋👩🏼",
- "👩🏿❤️💋👩🏼",
- "👩🏿❤️💋👩🏽",
- "👩🏿❤️💋👩🏽",
- "👩🏿❤️💋👩🏾",
- "👩🏿❤️💋👩🏾",
- "👩🏿❤️💋👩🏿",
- "👩🏿❤️💋👩🏿",
- "👨❤️💋👨",
- "👨❤️💋👨",
- "👨❤️💋👨",
- "👨🏻❤️💋👨🏻",
- "👨🏻❤️💋👨🏻",
- "👨🏻❤️💋👨🏼",
- "👨🏻❤️💋👨🏼",
- "👨🏻❤️💋👨🏽",
- "👨🏻❤️💋👨🏽",
- "👨🏻❤️💋👨🏾",
- "👨🏻❤️💋👨🏾",
- "👨🏻❤️💋👨🏿",
- "👨🏻❤️💋👨🏿",
- "👨🏼❤️💋👨🏻",
- "👨🏼❤️💋👨🏻",
- "👨🏼❤️💋👨🏼",
- "👨🏼❤️💋👨🏼",
- "👨🏼❤️💋👨🏽",
- "👨🏼❤️💋👨🏽",
- "👨🏼❤️💋👨🏾",
- "👨🏼❤️💋👨🏾",
- "👨🏼❤️💋👨🏿",
- "👨🏼❤️💋👨🏿",
- "👨🏽❤️💋👨🏻",
- "👨🏽❤️💋👨🏻",
- "👨🏽❤️💋👨🏼",
- "👨🏽❤️💋👨🏼",
- "👨🏽❤️💋👨🏽",
- "👨🏽❤️💋👨🏽",
- "👨🏽❤️💋👨🏾",
- "👨🏽❤️💋👨🏾",
- "👨🏽❤️💋👨🏿",
- "👨🏽❤️💋👨🏿",
- "👨🏾❤️💋👨🏻",
- "👨🏾❤️💋👨🏻",
- "👨🏾❤️💋👨🏼",
- "👨🏾❤️💋👨🏼",
- "👨🏾❤️💋👨🏽",
- "👨🏾❤️💋👨🏽",
- "👨🏾❤️💋👨🏾",
- "👨🏾❤️💋👨🏾",
- "👨🏾❤️💋👨🏿",
- "👨🏾❤️💋👨🏿",
- "👨🏿❤️💋👨🏻",
- "👨🏿❤️💋👨🏻",
- "👨🏿❤️💋👨🏼",
- "👨🏿❤️💋👨🏼",
- "👨🏿❤️💋👨🏽",
- "👨🏿❤️💋👨🏽",
- "👨🏿❤️💋👨🏾",
- "👨🏿❤️💋👨🏾",
- "👨🏿❤️💋👨🏿",
- "👨🏿❤️💋👨🏿",
- "👪",
- "👨👩👦",
- "👨👩👧",
- "👨👩👧👦",
- "👨👩👦👦",
- "👨👩👧👧",
- "👩👩👦",
- "👩👩👧",
- "👩👩👧👦",
- "👩👩👦👦",
- "👩👩👧👧",
- "👨👨👦",
- "👨👨👧",
- "👨👨👧👦",
- "👨👨👦👦",
- "👨👨👧👧",
- "👩👦",
- "👩👧",
- "👩👧👦",
- "👩👦👦",
- "👩👧👧",
- "👨👦",
- "👨👧",
- "👨👧👦",
- "👨👦👦",
- "👨👧👧",
- "🪢",
- "🧶",
- "🧵",
- "🪡",
- "🧥",
- "🥼",
- "🦺",
- "👚",
- "👕",
- "👕",
- "👖",
- "🩲",
- "🩳",
- "👔",
- "👗",
- "👙",
- "🩱",
- "👘",
- "🥻",
- "🩴",
- "🥿",
- "🥿",
- "👠",
- "👡",
- "👡",
- "👢",
- "👢",
- "👞",
- "👟",
- "👟",
- "🥾",
- "🧦",
- "🧤",
- "🧣",
- "🎩",
- "🎩",
- "🧢",
- "👒",
- "🎓",
- "⛑️",
- "⛑️",
- "🪖",
- "👑",
- "💍",
- "👝",
- "👝",
- "👛",
- "👜",
- "💼",
- "🎒",
- "🎒",
- "🧳",
- "👓",
- "👓",
- "🕶️",
- "🥽",
- "🌂",
- "🩷",
- "❤️",
- "❤️",
- "🧡",
- "💛",
- "💚",
- "🩵",
- "💙",
- "💜",
- "🖤",
- "🩶",
- "🤍",
- "🤎",
- "💔",
- "❣️",
- "❣️",
- "💕",
- "💞",
- "💓",
- "💓",
- "💗",
- "💗",
- "💖",
- "💘",
- "💝",
- "❤️🩹",
- "❤️🔥",
- "💟",
- "☮️",
- "☮️",
- "✝️",
- "✝️",
- "☪️",
- "🕉️",
- "☸️",
- "🪯",
- "✡️",
- "🔯",
- "🕎",
- "☯️",
- "☦️",
- "🛐",
- "🛐",
- "⛎",
- "♈",
- "♉",
- "♊",
- "♋",
- "♌",
- "♍",
- "♎",
- "♏",
- "♏",
- "♐",
- "♑",
- "♒",
- "♓",
- "🆔",
- "⚛️",
- "⚛️",
- "🉑",
- "☢️",
- "☢️",
- "☣️",
- "☣️",
- "📴",
- "📳",
- "🈶",
- "🈚",
- "🈸",
- "🈺",
- "🈷️",
- "✴️",
- "🆚",
- "💮",
- "🉐",
- "㊙️",
- "㊗️",
- "🈴",
- "🈵",
- "🈹",
- "🈲",
- "🅰️",
- "🅱️",
- "🆎",
- "🆑",
- "🅾️",
- "🆘",
- "❌",
- "❌",
- "⭕",
- "🛑",
- "🛑",
- "⛔",
- "📛",
- "🚫",
- "🚫",
- "💢",
- "♨️",
- "♨️",
- "🚷",
- "🚯",
- "🚯",
- "🚳",
- "🚱",
- "🔞",
- "📵",
- "🚭",
- "❗",
- "❕",
- "❓",
- "❓",
- "❔",
- "‼️",
- "⁉️",
- "🔅",
- "🔆",
- "〽️",
- "⚠️",
- "🚸",
- "🔱",
- "⚜️",
- "🔰",
- "♻️",
- "✅",
- "🈯",
- "💹",
- "❇️",
- "✳️",
- "❎",
- "🌐",
- "💠",
- "Ⓜ️",
- "Ⓜ️",
- "🌀",
- "💤",
- "🏧",
- "🚾",
- "🚾",
- "♿",
- "🅿️",
- "🛗",
- "🈳",
- "🈂️",
- "🛂",
- "🛃",
- "🛄",
- "🛅",
- "🛜",
- "🚹",
- "🚹",
- "🚺",
- "🚺",
- "🚼",
- "🚻",
- "🚮",
- "🎦",
- "📶",
- "📶",
- "🈁",
- "🔣",
- "🔣",
- "ℹ️",
- "ℹ️",
- "🔤",
- "🔡",
- "🔠",
- "🆖",
- "🆗",
- "🆙",
- "🆒",
- "🆕",
- "🆓",
- "0️⃣",
- "1️⃣",
- "2️⃣",
- "3️⃣",
- "4️⃣",
- "5️⃣",
- "6️⃣",
- "7️⃣",
- "8️⃣",
- "9️⃣",
- "🔟",
- "🔢",
- "#️⃣",
- "*️⃣",
- "*️⃣",
- "⏏️",
- "⏏️",
- "▶️",
- "⏸️",
- "⏸️",
- "⏯️",
- "⏹️",
- "⏺️",
- "⏭️",
- "⏭️",
- "⏮️",
- "⏮️",
- "⏩",
- "⏪",
- "⏫",
- "⏬",
- "◀️",
- "🔼",
- "🔽",
- "➡️",
- "➡️",
- "⬅️",
- "⬅️",
- "⬆️",
- "⬆️",
- "⬇️",
- "⬇️",
- "↗️",
- "↘️",
- "↙️",
- "↖️",
- "↖️",
- "↕️",
- "↕️",
- "↔️",
- "↪️",
- "↩️",
- "⤴️",
- "⤵️",
- "🔀",
- "🔁",
- "🔂",
- "🔄",
- "🔃",
- "🎵",
- "🎶",
- "🎶",
- "➕",
- "➖",
- "➗",
- "✖️",
- "🟰",
- "♾️",
- "💲",
- "💱",
- "™️",
- "™️",
- "©️",
- "®️",
- "〰️",
- "➰",
- "➿",
- "🔚",
- "🔚",
- "🔙",
- "🔙",
- "🔛",
- "🔛",
- "🔝",
- "🔝",
- "🔜",
- "🔜",
- "✔️",
- "✔️",
- "☑️",
- "🔘",
- "⚪",
- "⚫",
- "🔴",
- "🔵",
- "🟤",
- "🟣",
- "🟢",
- "🟡",
- "🟠",
- "🔺",
- "🔻",
- "🔸",
- "🔹",
- "🔶",
- "🔷",
- "🔳",
- "🔲",
- "▪️",
- "▫️",
- "◾",
- "◽",
- "◼️",
- "◻️",
- "⬛",
- "⬜",
- "🟧",
- "🟦",
- "🟥",
- "🟫",
- "🟪",
- "🟩",
- "🟨",
- "🔈",
- "🔇",
- "🔇",
- "🔉",
- "🔊",
- "🔔",
- "🔕",
- "📣",
- "📣",
- "📢",
- "🗨️",
- "🗨️",
- "👁🗨",
- "💬",
- "💭",
- "🗯️",
- "🗯️",
- "♠️",
- "♠️",
- "♣️",
- "♣️",
- "♥️",
- "♥️",
- "♦️",
- "♦️",
- "🃏",
- "🃏",
- "🎴",
- "🀄",
- "🕐",
- "🕐",
- "🕑",
- "🕑",
- "🕒",
- "🕒",
- "🕓",
- "🕓",
- "🕔",
- "🕔",
- "🕕",
- "🕕",
- "🕖",
- "🕖",
- "🕗",
- "🕗",
- "🕘",
- "🕘",
- "🕙",
- "🕙",
- "🕚",
- "🕚",
- "🕛",
- "🕛",
- "🕜",
- "🕜",
- "🕝",
- "🕝",
- "🕞",
- "🕞",
- "🕟",
- "🕟",
- "🕠",
- "🕠",
- "🕡",
- "🕡",
- "🕢",
- "🕢",
- "🕣",
- "🕣",
- "🕤",
- "🕤",
- "🕥",
- "🕥",
- "🕦",
- "🕦",
- "🕧",
- "🕧",
- "♀️",
- "♂️",
- "⚧",
- "⚕️",
- "🇿",
- "🇾",
- "🇽",
- "🇼",
- "🇻",
- "🇺",
- "🇹",
- "🇸",
- "🇷",
- "🇶",
- "🇵",
- "🇴",
- "🇳",
- "🇲",
- "🇱",
- "🇰",
- "🇯",
- "🇮",
- "🇭",
- "🇬",
- "🇫",
- "🇪",
- "🇩",
- "🇨",
- "🇧",
- "🇦",
- "🚗",
- "🚗",
- "🚕",
- "🚙",
- "🛻",
- "🚐",
- "🚌",
- "🚎",
- "🏎️",
- "🏎️",
- "🚓",
- "🚑",
- "🚒",
- "🚚",
- "🚛",
- "🚜",
- "🦯",
- "🦽",
- "🦼",
- "🩼",
- "🛴",
- "🛴",
- "🚲",
- "🚲",
- "🛵",
- "🛵",
- "🏍️",
- "🏍️",
- "🛺",
- "🛞",
- "🚨",
- "🚔",
- "🚍",
- "🚘",
- "🚖",
- "🚡",
- "🚠",
- "🚟",
- "🚃",
- "🚋",
- "🚋",
- "🚞",
- "🚝",
- "🚄",
- "🚅",
- "🚅",
- "🚈",
- "🚂",
- "🚂",
- "🚆",
- "🚇",
- "🚊",
- "🚉",
- "✈️",
- "🛫",
- "🛬",
- "🛩️",
- "🛩️",
- "💺",
- "🛰️",
- "🚀",
- "🛸",
- "🚁",
- "🛶",
- "🛶",
- "⛵",
- "🚤",
- "🛥️",
- "🛥️",
- "🛳️",
- "🛳️",
- "⛴️",
- "🚢",
- "🛟",
- "⚓",
- "🪝",
- "⛽",
- "⛽",
- "🚧",
- "🚦",
- "🚥",
- "🚏",
- "🚏",
- "🗺️",
- "🗺️",
- "🗿",
- "🗿",
- "🗽",
- "🗼",
- "🏰",
- "🏰",
- "🏯",
- "🏟️",
- "🎡",
- "🎢",
- "🎠",
- "⛲",
- "⛱️",
- "⛱️",
- "🏖️",
- "🏖️",
- "🏝️",
- "🏝️",
- "🏜️",
- "🌋",
- "⛰️",
- "🏔️",
- "🏔️",
- "🗻",
- "🏕️",
- "⛺",
- "🏠",
- "🏡",
- "🏘️",
- "🏘️",
- "🏘️",
- "🏚️",
- "🏚️",
- "🛖",
- "🏗️",
- "🏗️",
- "🏭",
- "🏢",
- "🏬",
- "🏣",
- "🏤",
- "🏥",
- "🏦",
- "🏨",
- "🏪",
- "🏫",
- "🏩",
- "💒",
- "🏛️",
- "⛪",
- "🕌",
- "🕍",
- "🛕",
- "🕋",
- "⛩️",
- "🛤️",
- "🛤️",
- "🛣️",
- "🗾",
- "🗾",
- "🎑",
- "🏞️",
- "🏞️",
- "🌅",
- "🌄",
- "🌠",
- "🌠",
- "🎇",
- "🎆",
- "🌇",
- "🌇",
- "🌇",
- "🌆",
- "🏙️",
- "🌃",
- "🌌",
- "🌉",
- "🌁"
-];
diff --git a/font.gs b/font.gs
deleted file mode 100644
index c04a1da..0000000
--- a/font.gs
+++ /dev/null
@@ -1,127 +0,0 @@
-# Usage:
-# copy font.txt to your project directory
-# include the font data in the font_data list
-# list font_data = file ```font.txt```;
-# generate your own font using font.py
-# in inkscape, use these options:
-# Input/Output > SVG output > Path data > Path string format = Absolute
-# Input/Output > SVG output > Path data > Force repeat commands = Checked
-
-var font_offset = 0;
-var font_x = 0;
-var font_y = 0;
-var font_scale = 1;
-var font_x1 = 0;
-var font_x2 = 240;
-var font_char_spacing = 0;
-var font_line_spacing = 0;
-var font_linelen = 0;
-
-%define FONT_NAME font_data[font_offset+1]
-%define FONT_CREATOR font_data[font_offset+2]
-%define FONT_RIGHTS font_data[font_offset+3]
-%define FONT_WIDTH font_data[font_offset+4]
-%define FONT_HEIGHT font_data[font_offset+5]
-
-%define FONT_CALCULATE_WIDTH_FROM_LENGTH(LENGTH) \
- (LENGTH*(FONT_WIDTH+2+font_char_spacing)-(2+font_char_spacing))*font_scale
-%define FONT_CALCULATE_WIDTH(TEXT) FONT_CALCULATE_WIDTH_FROM_LENGTH(length(TEXT))
-
-proc font_render_char char {
- switch_costume $char;
- local x = "";
- local y = "";
- local i = font_offset+font_data[5+font_offset+costume_number()];
- forever {
- if font_data[i] == "M" {
- pen_up;
- goto font_x+font_scale*font_data[i+1], font_y-font_scale*font_data[i+2];
- i += 3;
- if x == "" {
- x = x_position();
- y = y_position();
- }
- } elif font_data[i] == "L" {
- pen_down;
- goto font_x+font_scale*font_data[i+1], font_y-font_scale*font_data[i+2];
- i += 3;
- } elif font_data[i] == "H" {
- pen_down;
- set_x font_x+font_scale*font_data[i+1];
- i += 2;
- } elif font_data[i] == "V" {
- pen_down;
- set_y font_y-font_scale*font_data[i+1];
- i += 2;
- } elif font_data[i] == "Z" {
- pen_down;
- goto x, y;
- i += 1;
- } else {
- pen_up;
- stop_this_script;
- }
- }
-}
-
-proc font_render_begin {
- font_x = font_x1;
- font_linelen = 0;
-}
-
-proc font_render_text text {
- local i = 1;
- repeat length($text) {
- font_render_char $text[i];
- font_x += (FONT_WIDTH+2+font_char_spacing)*font_scale;
- i++;
- }
-}
-
-proc font_render_text_softwrap text {
- local maxlen = (font_x2 - font_x1) // ((FONT_WIDTH+2+font_char_spacing)*font_scale);
- local i = 1;
- local font_linelen = 0;
- local word = "";
- until i > length($text) {
- until $text[i] == " " or i > length($text) {
- word &= $text[i];
- i++;
- }
- if font_linelen + length(word) > maxlen {
- font_y -= (FONT_HEIGHT+4+font_line_spacing)*font_scale;
- font_x = font_x1;
- font_linelen = 0;
- }
- local j = 1;
- repeat length(word) {
- font_render_char word[j];
- font_x += (FONT_WIDTH+2+font_char_spacing)*font_scale;
- font_linelen += 1;
- if font_x > font_x2 {
- font_y -= (FONT_HEIGHT+4+font_line_spacing)*font_scale;
- font_x = font_x1;
- font_linelen = 0;
- }
- j++;
- }
- word = "";
- until $text[i] != " " or i > length($text) {
- word &= $text[i];
- i++;
- }
- local j = 1;
- repeat length(word) {
- font_render_char word[j];
- font_x += (FONT_WIDTH+2+font_char_spacing)*font_scale;
- font_linelen += 1;
- if font_x > font_x2 {
- font_y -= (FONT_HEIGHT+4+font_line_spacing)*font_scale;
- font_x = font_x1;
- font_linelen = 0;
- }
- j++;
- }
- word = "";
- }
-}
diff --git a/font.py b/font.py
deleted file mode 100644
index 1447f0e..0000000
--- a/font.py
+++ /dev/null
@@ -1,90 +0,0 @@
-# pyright: reportAny=false
-# pyright: reportUnusedCallResult=false
-
-import argparse
-import re
-import xml.etree.ElementTree
-from dataclasses import dataclass
-from pathlib import Path
-from typing import cast
-
-ns = {
- "svg": "http://www.w3.org/2000/svg",
- "inkscape": "http://www.inkscape.org/namespaces/inkscape",
- "dc": "http://purl.org/dc/elements/1.1/",
- "cc": "http://creativecommons.org/ns#",
- "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
-}
-
-CHARSET = "".join(map(chr, range(ord(" "), ord("~") + 1)))
-
-argparser = argparse.ArgumentParser()
-argparser.add_argument("font", type=Path, help="Font .svg file to convert")
-argparser.add_argument("output", type=Path, help="Output .txt file")
-
-
-@dataclass
-class Args:
- font: Path
- output: Path
-
-
-args = Args(**argparser.parse_args().__dict__)
-name = args.font.stem
-root = xml.etree.ElementTree.parse(args.font).getroot()
-width = int(cast(str, root.get("width")))
-height = int(cast(str, root.get("height")))
-creator = root.find(".//dc:creator/dc:Agent/dc:title", ns) or ""
-rights = root.find(".//dc:rights/dc:Agent/dc:title", ns) or ""
-chars: dict[str, list[str]] = {}
-
-
-def modulate(d: list[str]) -> list[str]:
- cmd: str = ""
- i = 0
- while i < len(d):
- if d[i].isalpha():
- cmd = d[i]
- i += 1
- if cmd.upper() in "ML":
- if cmd.isupper():
- d[i] = str(int(float(d[i])) % (width * 2))
- i += 2
- elif cmd.upper() == "H":
- if cmd.isupper():
- d[i] = str(int(float(d[i])) % (width * 2))
- i += 1
- elif cmd.upper() == "V":
- i += 1
- return d
-
-
-for path in root.findall(".//svg:path", ns):
- sd = cast(str, path.get("d"))
- label = cast(str, path.get("{%s}label" % ns["inkscape"]))
- if len(label) == 1:
- chars[label] = modulate(re.split(r"[,\s]+", sd))
-
-with args.output.open("w") as f:
-
- def print(*objs: object, sep: str = " ", end: str = "\n") -> None:
- f.write(sep.join(map(str, objs)) + end)
-
- print(name)
- print(creator)
- print(rights)
- print(width)
- print(height)
-
- i = 0
- for ch in CHARSET:
- d = chars.get(ch, [])
- d.append("#")
- print(6 + len(CHARSET) + i)
- i += len(d)
- for ch in CHARSET:
- d: list[str] = chars.get(ch, ["#"])
- for x in d:
- if str(x).islower() and x not in "Zz":
- x = "d" + x
- print(x)
diff --git a/font.svg b/font.svg
deleted file mode 100644
index 9487322..0000000
--- a/font.svg
+++ /dev/null
@@ -1,448 +0,0 @@
-
-
-
-
diff --git a/font.txt b/font.txt
deleted file mode 100644
index 11aaec1..0000000
--- a/font.txt
+++ /dev/null
@@ -1,1755 +0,0 @@
-font
-
-
-4
-8
-101
-102
-113
-124
-145
-177
-194
-230
-236
-252
-268
-286
-297
-304
-310
-316
-323
-352
-370
-393
-419
-435
-458
-487
-500
-543
-572
-583
-595
-605
-616
-626
-645
-679
-698
-728
-750
-767
-782
-795
-821
-837
-853
-869
-889
-897
-911
-922
-945
-963
-992
-1016
-1048
-1059
-1075
-1089
-1103
-1116
-1135
-1146
-1156
-1163
-1173
-1183
-1189
-1196
-1222
-1240
-1262
-1280
-1306
-1322
-1345
-1361
-1379
-1397
-1417
-1430
-1448
-1461
-1483
-1501
-1519
-1532
-1564
-1580
-1596
-1610
-1624
-1637
-1662
-1677
-1705
-1711
-1739
-#
-M
-2
-8
-V
-8
-M
-2
-0
-V
-5
-#
-M
-3
-0
-V
-2
-M
-1
-0
-V
-2
-#
-M
-4
-6
-H
-0
-M
-4
-2
-H
-0
-M
-3
-8
-V
-0
-M
-1
-8
-V
-0
-#
-M
-2
--1
-V
-9
-M
-4
-1
-L
-3
-0
-H
-1
-L
-0
-1
-V
-2
-L
-4
-5
-V
-7
-L
-3
-8
-H
-1
-L
-0
-7
-#
-M
-4
-6
-V
-7
-M
-0
-1
-V
-2
-M
-4
-0
-L
-0
-8
-#
-M
-4
-5
-L
-2
-8
-H
-1
-L
-0
-7
-V
-4
-L
-1
-3
-M
-4
-1
-L
-3
-0
-H
-1
-L
-0
-1
-V
-2
-L
-2
-4
-L
-4
-8
-#
-M
-2
-0
-V
-2
-#
-M
-4
--1
-H
-3
-L
-1
-1
-V
-7
-L
-3
-9
-H
-4
-#
-M
-0
--1
-H
-1
-L
-3
-1
-V
-7
-L
-1
-9
-H
-0
-#
-M
-0
-3
-L
-4
-7
-M
-4
-3
-L
-0
-7
-M
-2
-1
-V
-5
-#
-M
-4
-4
-H
-0
-M
-2
-2
-V
-6
-#
-M
-2
-7
-L
-1
-10
-#
-M
-0
-4
-H
-4
-#
-M
-2
-7
-V
-8
-#
-M
-0
-9
-L
-4
--1
-#
-M
-2
-4
-V
-4
-M
-1
-0
-H
-3
-L
-4
-1
-V
-7
-L
-3
-8
-H
-1
-L
-0
-7
-V
-1
-L
-1
-0
-#
-M
-0
-8
-H
-2
-M
-0
-1
-H
-1
-L
-2
-0
-V
-8
-H
-4
-#
-M
-0
-2
-V
-1
-L
-1
-0
-H
-3
-L
-4
-1
-V
-3
-L
-0
-7
-V
-8
-H
-4
-#
-M
-0
-0
-H
-4
-L
-1
-3
-H
-3
-L
-4
-4
-V
-7
-L
-3
-8
-H
-1
-L
-0
-7
-V
-6
-#
-M
-4
-4
-V
-8
-M
-4
-0
-L
-0
-4
-V
-6
-H
-4
-#
-M
-4
-0
-H
-0
-V
-3
-H
-3
-L
-4
-4
-V
-7
-L
-3
-8
-H
-1
-L
-0
-7
-#
-M
-4
-1
-L
-3
-0
-H
-1
-L
-0
-1
-V
-7
-L
-1
-8
-H
-3
-L
-4
-7
-V
-4
-L
-3
-3
-H
-0
-#
-M
-0
-1
-V
-0
-H
-4
-V
-1
-L
-1
-8
-#
-M
-0
-1
-L
-1
-0
-H
-3
-L
-4
-1
-V
-3
-L
-3
-4
-H
-1
-L
-0
-5
-V
-7
-L
-1
-8
-H
-3
-L
-4
-7
-V
-5
-L
-3
-4
-H
-1
-L
-0
-3
-Z
-#
-M
-0
-7
-L
-1
-8
-H
-3
-L
-4
-7
-V
-1
-L
-3
-0
-H
-1
-L
-0
-1
-V
-4
-L
-1
-5
-H
-4
-#
-M
-2
-7
-V
-8
-M
-2
-2
-V
-3
-#
-M
-2
-7
-L
-1
-10
-M
-2
-2
-V
-3
-#
-M
-4
-0
-L
-0
-4
-L
-4
-8
-#
-M
-0
-6
-H
-4
-M
-0
-3
-H
-4
-#
-M
-0
-0
-L
-4
-4
-L
-0
-8
-#
-M
-2
-8
-V
-8
-M
-1
-0
-H
-3
-L
-4
-1
-V
-3
-L
-2
-5
-#
-M
-4
-3
-H
-3
-L
-2
-4
-V
-6
-L
-3
-7
-L
-4
-6
-V
-1
-L
-3
-0
-H
-1
-L
-0
-1
-V
-9
-L
-1
-10
-H
-3
-#
-M
-0
-6
-H
-4
-M
-0
-8
-V
-6
-L
-2
-0
-L
-4
-6
-V
-8
-#
-M
-3
-4
-H
-0
-M
-0
-0
-H
-3
-L
-4
-1
-V
-3
-L
-3
-4
-L
-4
-5
-V
-7
-L
-3
-8
-H
-0
-Z
-#
-M
-4
-1
-L
-3
-0
-H
-1
-L
-0
-1
-V
-7
-L
-1
-8
-H
-3
-L
-4
-7
-#
-M
-0
-0
-H
-3
-L
-4
-1
-V
-7
-L
-3
-8
-H
-0
-Z
-#
-M
-4
-4
-H
-0
-M
-4
-0
-H
-0
-V
-8
-H
-4
-#
-M
-4
-4
-H
-0
-M
-4
-0
-H
-0
-V
-8
-#
-M
-4
-1
-L
-3
-0
-H
-1
-L
-0
-1
-V
-7
-L
-1
-8
-H
-3
-L
-4
-7
-V
-4
-H
-2
-#
-M
-4
-4
-H
-0
-M
-4
-0
-V
-8
-M
-0
-0
-V
-8
-#
-M
-2
-0
-V
-8
-M
-0
-8
-H
-4
-M
-0
-0
-H
-4
-#
-M
-1
-0
-H
-4
-V
-7
-L
-3
-8
-H
-1
-L
-0
-7
-#
-M
-2
-4
-H
-0
-M
-4
-8
-L
-2
-4
-L
-4
-0
-M
-0
-0
-V
-8
-#
-M
-0
-0
-V
-8
-H
-4
-#
-M
-0
-8
-V
-0
-L
-2
-3
-L
-4
-0
-V
-8
-#
-M
-0
-8
-V
-0
-L
-4
-8
-V
-0
-#
-M
-0
-1
-L
-1
-0
-H
-3
-L
-4
-1
-V
-7
-L
-3
-8
-H
-1
-L
-0
-7
-Z
-#
-M
-0
-8
-V
-0
-H
-3
-L
-4
-1
-V
-3
-L
-3
-4
-H
-0
-#
-M
-4
-10
-L
-3
-8
-M
-0
-1
-L
-1
-0
-H
-3
-L
-4
-1
-V
-7
-L
-3
-8
-H
-1
-L
-0
-7
-Z
-#
-M
-4
-8
-L
-2
-4
-M
-0
-8
-V
-0
-H
-3
-L
-4
-1
-V
-3
-L
-3
-4
-H
-0
-#
-M
-4
-1
-L
-3
-0
-H
-1
-L
-0
-1
-V
-2
-L
-2
-4
-H
-3
-L
-4
-5
-V
-7
-L
-3
-8
-H
-1
-L
-0
-7
-#
-M
-2
-0
-V
-8
-M
-0
-0
-H
-4
-#
-M
-0
-0
-V
-7
-L
-1
-8
-H
-3
-L
-4
-7
-V
-0
-#
-M
-0
-0
-V
-4
-L
-2
-8
-L
-4
-4
-V
-0
-#
-M
-0
-0
-V
-8
-L
-2
-5
-L
-4
-8
-V
-0
-#
-M
-4
-0
-L
-0
-8
-M
-0
-0
-L
-4
-8
-#
-M
-4
-0
-V
-2
-L
-2
-5
-M
-0
-0
-V
-2
-L
-2
-5
-V
-8
-#
-M
-0
-0
-H
-4
-L
-0
-8
-H
-4
-#
-M
-3
--1
-H
-1
-V
-10
-H
-3
-#
-M
-0
--1
-L
-4
-9
-#
-M
-1
--1
-H
-3
-V
-10
-H
-1
-#
-M
-0
-4
-L
-2
-0
-L
-4
-4
-#
-M
-0
-9
-H
-4
-#
-M
-1
--1
-L
-3
-1
-#
-M
-0
-3
-L
-1
-2
-H
-3
-L
-4
-3
-V
-8
-H
-1
-L
-0
-7
-V
-6
-L
-1
-5
-H
-4
-#
-M
-0
-0
-V
-8
-H
-3
-L
-4
-7
-V
-3
-L
-3
-2
-H
-0
-#
-M
-4
-3
-L
-3
-2
-H
-1
-L
-0
-3
-V
-7
-L
-1
-8
-H
-3
-L
-4
-7
-#
-M
-4
-0
-V
-8
-H
-1
-L
-0
-7
-V
-3
-L
-1
-2
-H
-4
-#
-M
-0
-5
-H
-4
-V
-3
-L
-3
-2
-H
-1
-L
-0
-3
-V
-7
-L
-1
-8
-H
-3
-L
-4
-7
-#
-M
-4
-3
-H
-0
-M
-4
-0
-H
-3
-L
-2
-1
-V
-8
-#
-M
-1
-10
-H
-3
-L
-4
-9
-V
-2
-H
-1
-L
-0
-3
-V
-7
-L
-1
-8
-H
-4
-#
-M
-0
-2
-H
-3
-L
-4
-3
-V
-8
-M
-0
-0
-V
-8
-#
-M
-2
-0
-V
-0
-M
-4
-8
-H
-0
-M
-0
-2
-H
-2
-V
-8
-#
-M
-3
-0
-V
-0
-M
-0
-2
-H
-3
-V
-9
-L
-2
-10
-H
-0
-#
-M
-2
-5
-H
-0
-M
-4
-2
-L
-2
-5
-L
-4
-8
-M
-0
-0
-V
-8
-#
-M
-0
-0
-H
-2
-V
-7
-L
-3
-8
-H
-4
-#
-M
-2
-2
-V
-8
-M
-0
-8
-V
-2
-H
-3
-L
-4
-3
-V
-8
-#
-M
-0
-8
-V
-2
-H
-3
-L
-4
-3
-V
-8
-#
-M
-0
-3
-V
-7
-L
-1
-8
-H
-3
-L
-4
-7
-V
-3
-L
-3
-2
-H
-1
-Z
-#
-M
-0
-10
-V
-2
-H
-3
-L
-4
-3
-V
-7
-L
-3
-8
-H
-0
-#
-M
-4
-10
-V
-2
-H
-1
-L
-0
-3
-V
-7
-L
-1
-8
-H
-4
-#
-M
-0
-8
-V
-2
-H
-3
-L
-4
-3
-V
-4
-#
-M
-4
-3
-L
-3
-2
-H
-1
-L
-0
-3
-V
-4
-L
-1
-5
-H
-3
-L
-4
-6
-V
-7
-L
-3
-8
-H
-1
-L
-0
-7
-#
-M
-4
-2
-H
-0
-M
-2
-0
-V
-7
-L
-3
-8
-H
-4
-#
-M
-0
-2
-V
-7
-L
-1
-8
-H
-3
-L
-4
-7
-V
-2
-#
-M
-0
-2
-V
-4
-L
-2
-8
-L
-4
-4
-V
-2
-#
-M
-0
-2
-V
-8
-L
-2
-5
-L
-4
-8
-V
-2
-#
-M
-4
-2
-L
-0
-8
-M
-0
-2
-L
-4
-8
-#
-M
-0
-2
-L
-1
-6
-L
-2
-8
-M
-4
-2
-L
-3
-6
-L
-2
-8
-L
-1
-9
-L
-0
-10
-#
-M
-0
-2
-H
-4
-V
-3
-L
-0
-7
-V
-8
-H
-4
-#
-M
-4
--1
-H
-3
-L
-2
-0
-V
-3
-L
-1
-4
-H
-0
-H
-1
-L
-2
-5
-V
-9
-L
-3
-10
-H
-4
-#
-M
-2
--1
-V
-10
-#
-M
-0
--1
-H
-1
-L
-2
-0
-V
-3
-L
-3
-4
-H
-4
-H
-3
-L
-2
-5
-V
-9
-L
-1
-10
-H
-0
-#
-M
-0
-5
-V
-4
-L
-1
-3
-L
-3
-5
-L
-4
-4
-V
-3
-#
diff --git a/getopt.gs b/getopt.gs
new file mode 100644
index 0000000..1042385
--- /dev/null
+++ b/getopt.gs
@@ -0,0 +1,166 @@
+#
+# ── INPUT ────────────────────────────────────────────────────────────────────
+# Reads from the global list `shlex_args` (populated by shlex_split).
+#
+# ── USAGE ────────────────────────────────────────────────────────────────────
+# 1. Call shlex_split on your command string.
+# 2. Call getopt_init to reset state.
+# 3. Call getopt in a loop, passing your optstring (e.g. "ab:c").
+# A letter followed by ':' means that option requires an argument.
+# 4. After the loop, optind points at the first non-option argument.
+#
+# onflag {
+# shlex_split "-v -o file.txt -- foo bar";
+# getopt_init;
+# getopt_result = "";
+# until getopt_result == -1 {
+# getopt "vo:";
+# if getopt_result == "v" { say "verbose"; }
+# if getopt_result == "o" { say "output: " & optarg; }
+# if getopt_result == "?" { say "unknown: " & optopt; }
+# }
+# # shlex_args[optind] .. shlex_args[length shlex_args] are non-option args
+# }
+#
+# ── OUTPUTS (globals) ────────────────────────────────────────────────────────
+# getopt_result — option char found, "?" for unknown, -1 when done
+# optarg — argument value for options that take one (letter + ':')
+# optopt — the raw option character just examined
+# optind — index of next unprocessed item in shlex_args
+
+var getopt_result = "";
+var optarg = "";
+var optopt = "";
+var optind = 1;
+
+# ── private state ─────────────────────────────────────────────────────────────
+# _go_subpos: position within the current cluster arg being parsed.
+# 0 → need to fetch the next arg from shlex_args
+# 2+ → mid-cluster (e.g. after '-' in "-xyz", 'x' is at pos 2)
+var _go_subpos = 0;
+
+# ── getopt_init ───────────────────────────────────────────────────────────────
+# Reset all getopt state. Call before starting a new parse.
+proc getopt_init {
+ optind = 1;
+ optarg = "";
+ optopt = "";
+ getopt_result = "";
+ _go_subpos = 0;
+}
+
+# ── getopt ────────────────────────────────────────────────────────────────────
+# proc getopt optstring
+#
+# optstring e.g. "ab:cd:"
+# A plain letter is a flag. Letter + ':' requires an argument.
+#
+# Behaviours mirroring POSIX getopt:
+# -a -b -c individual flags
+# -abc cluster; equivalent to -a -b -c
+# -o value option with argument (separate token)
+# -ovalue option with argument (joined)
+# -- ends option parsing; optind advances past it
+# non-option arg ends option parsing (optind points at it)
+proc getopt optstring {
+ local arg = "";
+ local c = "";
+ local ci = 0;
+ local found = 0;
+ local takes_arg = 0;
+ local vi = 0;
+
+ # ── Phase 1: fetch next arg when not mid-cluster ──────────────────────────
+ if _go_subpos == 0 {
+ if optind > length shlex_args {
+ getopt_result = -1;
+ } else {
+ arg = shlex_args[optind];
+ if arg == "--" {
+ # explicit end-of-options marker
+ optind += 1;
+ getopt_result = -1;
+ } elif length arg < 2 or arg[1] != "-" {
+ # non-option argument: stop here, leave optind pointing at it
+ getopt_result = -1;
+ } else {
+ # valid option cluster, first char at position 2
+ _go_subpos = 2;
+ }
+ }
+ }
+
+ # ── Phase 2: consume one option character from the current cluster ────────
+ if _go_subpos > 0 {
+ arg = shlex_args[optind];
+ c = arg[_go_subpos];
+ optopt = c;
+ optarg = "";
+
+ # Search optstring for c; check if the next char is ':'
+ found = 0;
+ takes_arg = 0;
+ ci = 1;
+ until ci > length $optstring or found == 1 {
+ if $optstring[ci] == c {
+ found = 1;
+ if ci + 1 <= length $optstring {
+ if $optstring[ci + 1] == ":" {
+ takes_arg = 1;
+ }
+ }
+ }
+ ci += 1;
+ }
+
+ if found == 0 {
+ # ── unknown option ────────────────────────────────────────────────
+ getopt_result = "?";
+ if _go_subpos >= length arg {
+ optind += 1;
+ _go_subpos = 0;
+ } else {
+ _go_subpos += 1;
+ }
+
+ } elif takes_arg == 1 {
+ # ── option with argument ──────────────────────────────────────────
+ if _go_subpos < length arg {
+ # rest of the cluster is the value e.g. -ofoo → optarg="foo"
+ vi = _go_subpos + 1;
+ until vi > length arg {
+ optarg &= arg[vi];
+ vi += 1;
+ }
+ optind += 1;
+ _go_subpos = 0;
+ getopt_result = c;
+ } else {
+ # value is the next item e.g. -o foo → optarg="foo"
+ optind += 1;
+ if optind > length shlex_args {
+ # missing required argument
+ getopt_result = "?";
+ _go_subpos = 0;
+ } else {
+ optarg = shlex_args[optind];
+ optind += 1;
+ _go_subpos = 0;
+ getopt_result = c;
+ }
+ }
+
+ } else {
+ # ── flag option (no argument) ─────────────────────────────────────
+ getopt_result = c;
+ if _go_subpos >= length arg {
+ # end of this cluster, move to next arg
+ optind += 1;
+ _go_subpos = 0;
+ } else {
+ # more letters remain in the cluster
+ _go_subpos += 1;
+ }
+ }
+ }
+}
diff --git a/list.gs b/list.gs
index 343077a..4ee2a6f 100644
--- a/list.gs
+++ b/list.gs
@@ -1,179 +1,305 @@
-# Sort `LIST` in ascending order using the insertion sorting algorithm.
-%define INSERTION_SORT(LIST) \
- local i = 2; \
- until i > length(LIST) { \
- local isx = LIST[i]; \
- local j = i; \
- until j <= 1 or LIST[j - 1] <= isx { \
- LIST[j] = LIST[j - 1]; \
+%define LIST_SORT(LIST) \
+ local start = $start; \
+ local end = $end; \
+ if start < 0 { \
+ start = length(LIST) + start + 1; \
+ } \
+ if end < 0 { \
+ end = length(LIST) + end + 1; \
+ } \
+ local i = start + 1; \
+ until i > end { \
+ local key = LIST[i]; \
+ local j = i - 1; \
+ until j < start or LIST[j] <= key { \
+ LIST[j + 1] = LIST[j]; \
j--; \
} \
- LIST[j] = isx; \
+ LIST[j + 1] = key; \
i++; \
}
-# Sort `LIST` of type `TYPE` in ascending order of the value of `FIELD` using the
-# insertion sorting algorithm.
-%define INSERTION_SORT_BY_FIELD(TYPE,LIST,FIELD) \
- local i = 2; \
- until i > length(LIST) { \
- local TYPE isfx = LIST[i]; \
- local j = i; \
- until j <= 1 or LIST[j - 1]FIELD <= isfx FIELD { \
- LIST[j] = LIST[j - 1]; \
+%define LIST_SORT(LIST, TYPE, KEY) \
+ local start = $start; \
+ local end = $end; \
+ if start < 0 { \
+ start = length(LIST) + start + 1; \
+ } \
+ if end < 0 { \
+ end = length(LIST) + end + 1; \
+ } \
+ local i = start + 1; \
+ until i > end { \
+ local TYPE key = LIST[i]; \
+ local j = i - 1; \
+ until j < start or LIST[j].KEY <= key.KEY { \
+ LIST[j + 1] = LIST[j]; \
j--; \
} \
- LIST[j] = isfx; \
+ LIST[j + 1] = key; \
i++; \
}
-# Count the number of elements in `LIST` that satisfy `CMP`, and store the result in
-# `STORE`. local `i` is the index of the current element.
-%define COUNT(LIST,CMP,STORE) \
- local STORE = 0; \
- local i = 1; \
- repeat length(LIST) { \
- if CMP { \
- STORE += 1; \
+%define LIST_JOIN(LIST) \
+ local start = $start; \
+ local end = $end; \
+ if start < 0 { \
+ start = length(LIST) + start + 1; \
+ } \
+ if end < 0 { \
+ end = length(LIST) + end + 1; \
+ } \
+ local out = ""; \
+ local i = start; \
+ repeat end - start + 1 { \
+ if i != start { \
+ out &= $sep; \
} \
+ out &= LIST[i]; \
i++; \
- }
+ } \
+ return out;
-# Sum the elements in `LIST` that satisfy `CMP`, and store the result in `STORE`.
-# local `i` is the index of the current element.
-%define SUM(LIST,CMP,STORE) \
- local STORE = 0; \
- local i = 1; \
- repeat length(LIST) { \
- if CMP { \
- STORE += LIST[i]; \
+%define LIST_JOIN(LIST, KEY) \
+ local start = $start; \
+ local end = $end; \
+ if start < 0 { \
+ start = length(LIST) + start + 1; \
+ } \
+ if end < 0 { \
+ end = length(LIST) + end + 1; \
+ } \
+ local out = ""; \
+ local i = start; \
+ repeat end - start + 1 { \
+ if i != start { \
+ out &= $sep; \
} \
+ out &= LIST[i].KEY; \
i++; \
- }
+ } \
+ return out;
-# Find the largest element in `LIST` that satisfies `CMP`, and store the result in
-# `STORE`. local `i` is the index of the current element.
-%define FINDMAX(LIST,CMP,STORE) \
- local STORE = "-Infinity"; \
- local i = 1; \
- repeat length(LIST) { \
- if CMP { \
- if LIST[i] > STORE { \
- STORE = LIST[i]; \
- } \
+%define LIST_SUM(LIST) \
+ local start = $start; \
+ local end = $end; \
+ if start < 0 { \
+ start = length(LIST) + start + 1; \
+ } \
+ if end < 0 { \
+ end = length(LIST) + end + 1; \
+ } \
+ local out = 0; \
+ local i = start; \
+ repeat end - start + 1 { \
+ out += LIST[i]; \
+ i++; \
+ } \
+ return out;
+
+%define LIST_SUM(LIST, KEY) \
+ local start = $start; \
+ local end = $end; \
+ if start < 0 { \
+ start = length(LIST) + start + 1; \
+ } \
+ if end < 0 { \
+ end = length(LIST) + end + 1; \
+ } \
+ local out = 0; \
+ local i = start; \
+ repeat end - start + 1 { \
+ out += LIST[i].KEY; \
+ i++; \
+ } \
+ return out;
+
+%define LIST_MIN(LIST) \
+ local start = $start; \
+ local end = $end; \
+ if start < 0 { \
+ start = length(LIST) + start + 1; \
+ } \
+ if end < 0 { \
+ end = length(LIST) + end + 1; \
+ } \
+ local out = 1/0; \
+ local i = start; \
+ repeat end - start + 1 { \
+ if LIST[i] < out { \
+ out = LIST[i]; \
} \
i++; \
- }
+ } \
+ return out;
-# Find the smallest element in `LIST` that satisfies `CMP`, and store the result in
-# `STORE`. local `i` is the index of the current element.
-%define FINDMIN(LIST,CMP,STORE) \
- local STORE = "Infinity"; \
- local i = 1; \
- repeat length(LIST) { \
- if CMP { \
- if LIST[i] < STORE { \
- STORE = LIST[i]; \
- } \
+%define LIST_MIN(LIST, KEY) \
+ local start = $start; \
+ local end = $end; \
+ if start < 0 { \
+ start = length(LIST) + start + 1; \
+ } \
+ if end < 0 { \
+ end = length(LIST) + end + 1; \
+ } \
+ local out = 1/0; \
+ local i = start; \
+ repeat end - start + 1 { \
+ if LIST[i].KEY < out { \
+ out = LIST[i].KEY; \
} \
i++; \
- }
+ } \
+ return out;
-# Reverse `LIST` in place.
-%define REVERSE(LIST) \
- local i = 1; \
- local j = length(LIST); \
- repeat length(LIST) / 2 { \
- local x = LIST[i]; \
- LIST[i] = LIST[j]; \
- LIST[j] = x; \
+%define LIST_MAX(LIST) \
+ local start = $start; \
+ local end = $end; \
+ if start < 0 { \
+ start = length(LIST) + start + 1; \
+ } \
+ if end < 0 { \
+ end = length(LIST) + end + 1; \
+ } \
+ local out = -1/0; \
+ local i = start; \
+ repeat end - start + 1 { \
+ if LIST[i] > out { \
+ out = LIST[i]; \
+ } \
i++; \
- j--; \
- }
+ } \
+ return out;
-# Copy `SRC` to `DEST`.
-%define COPY(SRC,DEST) \
- delete DEST; \
- local i = 1; \
- repeat length(SRC) { \
- add SRC[i] to DEST; \
+%define LIST_MAX(LIST, KEY) \
+ local start = $start; \
+ local end = $end; \
+ if start < 0 { \
+ start = length(LIST) + start + 1; \
+ } \
+ if end < 0 { \
+ end = length(LIST) + end + 1; \
+ } \
+ local out = -1/0; \
+ local i = start; \
+ repeat end - start + 1 { \
+ if LIST[i].KEY > out { \
+ out = LIST[i].KEY; \
+ } \
i++; \
+ } \
+ return out;
+
+%define LIST_REVERSE(LIST) \
+ local lo = $start; \
+ local hi = $end; \
+ if lo < 0 { \
+ lo = length(LIST) + lo + 1; \
+ } \
+ if hi < 0 { \
+ hi = length(LIST) + hi + 1; \
+ } \
+ until lo >= hi { \
+ local tmp = LIST[lo]; \
+ LIST[lo] = LIST[hi]; \
+ LIST[hi] = tmp; \
+ lo++; \
+ hi--; \
}
-# Extend `DEST` with the elements of `SRC`.
-%define EXTEND(SRC,DEST) \
- local i = 1; \
- repeat length(SRC) { \
- add SRC[i] to DEST; \
- i++; \
+%define LIST_REVERSE(TYPE, LIST) \
+ local lo = $start; \
+ local hi = $end; \
+ if lo < 0 { \
+ lo = length(LIST) + lo + 1; \
+ } \
+ if hi < 0 { \
+ hi = length(LIST) + hi + 1; \
+ } \
+ until lo >= hi { \
+ local TYPE tmp = LIST[lo]; \
+ LIST[lo] = LIST[hi]; \
+ LIST[hi] = tmp; \
+ lo++; \
+ hi--; \
}
-# Remove duplicate elements from `LIST`.
-%define UNIQUE(LIST) \
- local i = 1; \
- until i > length(LIST) { \
- local j = i + 1; \
- until j > length(LIST) { \
- if LIST[i] == LIST[j] { \
- delete LIST[j]; \
- } else { \
- j++; \
- } \
- } \
+%define LIST_COPY(SRC, DST) \
+ local start = $start; \
+ local end = $end; \
+ if start < 0 { \
+ start = length(SRC) + start + 1; \
+ } \
+ if end < 0 { \
+ end = length(SRC) + end + 1; \
+ } \
+ local i = start; \
+ repeat end - start + 1 { \
+ add SRC[i] to DST; \
i++; \
}
-# Sum the field `FIELD` in `LIST` that satisfy `CMP`, and store the result in `STORE`.
-%define SUM_BY_FIELD(LIST,FIELD,CMP,STORE) \
- local STORE = 0; \
+%define LIST_EXTEND(SRC, DST) \
local i = 1; \
- repeat length(LIST) { \
- if CMP { \
- STORE += LIST[i]FIELD; \
- } \
+ repeat length SRC { \
+ add SRC[i] to DST; \
i++; \
}
-# TODO [BLOCKED BY]: https://github.com/aspizu/goboscript/issues/71
-# Find the largest `FIELD` value in `LIST` of type `TYPE` that satisfies `CMP` and store
-# the result in `STORE`.
-%define FINDMAX_BY_FIELD(TYPE,LIST,FIELD,CMP,STORE) \
- local TYPE STORE; \
- STORE FIELD = "-Infinity"; \
- local i = 1; \
- repeat length(LIST) { \
- if CMP { \
- if LIST[i]FIELD > STORE FIELD { \
- STORE = LIST[i]; \
- } \
- } \
+%define LIST_EXTEND(SRC, DST) \
+ local start = $start; \
+ local end = $end; \
+ if start < 0 { \
+ start = length(SRC) + start + 1; \
+ } \
+ if end < 0 { \
+ end = length(SRC) + end + 1; \
+ } \
+ local i = start; \
+ repeat end - start + 1 { \
+ add SRC[i] to DST; \
i++; \
}
-# TODO [BLOCKED BY]: https://github.com/aspizu/goboscript/issues/71
-# Find the smallest `FIELD` value in `LIST` of type `TYPE` that satisfies `CMP` and
-# store the result in `STORE`.
-%define FINDMIN_BY_FIELD(TYPE,LIST,FIELD,CMP,STORE) \
- local TYPE STORE; \
- STORE FIELD = "Infinity"; \
- local i = 1; \
- repeat length(LIST) { \
- if CMP { \
- if LIST[i]FIELD < STORE FIELD { \
- STORE = LIST[i]; \
+%define LIST_UNIQUE(LIST) \
+ local start = $start; \
+ local end_ = $end; \
+ if start < 0 { \
+ start = length(LIST) + start + 1; \
+ } \
+ if end_ < 0 { \
+ end_ = length(LIST) + end_ + 1; \
+ } \
+ local i = start; \
+ until i > end_ { \
+ local j = i + 1; \
+ until j > end_ { \
+ if LIST[i] == LIST[j] { \
+ delete LIST[j]; \
+ end_--; \
+ } else { \
+ j++; \
} \
} \
i++; \
}
-# Remove duplicate elements from `LIST` by field `FIELD`.
-%define UNIQUE_BY_FIELD(LIST,FIELD) \
- local i = 1; \
- until i > length(LIST) { \
+%define LIST_UNIQUE(LIST, TYPE, KEY) \
+ local start = $start; \
+ local end_ = $end; \
+ if start < 0 { \
+ start = length(LIST) + start + 1; \
+ } \
+ if end_ < 0 { \
+ end_ = length(LIST) + end_ + 1; \
+ } \
+ local i = start; \
+ until i > end_ { \
local j = i + 1; \
- until j > length(LIST) { \
- if LIST[i] FIELD == LIST[j] FIELD { \
+ until j > end_ { \
+ if LIST[i].KEY == LIST[j].KEY { \
delete LIST[j]; \
+ end_--; \
} else { \
j++; \
} \
diff --git a/math.gs b/math.gs
index e77d17e..c28dacc 100644
--- a/math.gs
+++ b/math.gs
@@ -1,71 +1,63 @@
%define PI 3.141592653589793
+
%define E 2.718281828459045
-%define SQRT2 1.4142135623730951
-# Return the minimum of `A` and `B`.
-%define MIN(A,B) ((A) - ((A) - (B)) * ((A) > (B)))
+%define MIN(A,B) ((A)+(((A)>(B))*((B)-(A))))
-# Return the maximum of `A` and `B`.
-%define MAX(A,B) ((A) + ((B) - (A)) * ((A) < (B)))
+%define MAX(A,B) ((A)+(((A)<(B))*((B)-(A))))
-# Combine RGB values into a single value for use with the `set_pen_color` block.
-%define RGB(R,G,B) (((R) * 65536) + ((G) * 256) + (B))
+%define RGB(R, G, B) (((R)*65536)+((G)*256)+(B))
-# Combine RGBA values into a single value for use with the `set_pen_color` block.
-%define RGBA(R,G,B,A) (((R) * 65536) + ((G) * 256) + (B) + ((A) * 16777216))
+%define RGBA(R, G, B, A) (((R)*65536)+((G)*256)+(B)+((A)*16777216))
-# Parse a hexadecimal value.
%define HEX(VALUE) (("0x"&(VALUE))+0)
-# Parse a binary value.
%define BIN(VALUE) (("0b"&(VALUE))+0)
-# Parse a octal value.
%define OCT(VALUE) (("0o"&(VALUE))+0)
+%define SIGN(VALUE) (((VALUE)>0)-((VALUE)<0))
+
%define ACOSH(X) ln((X)+sqrt((X)*(X)-1))
+
%define ASINH(X) ln((X)+sqrt((X)*(X)+1))
+
%define ATANH(X) ln((1+(X))/(1-(X)))/2
+
%define COSH(X) ((antiln(X)+antiln(-(X)))/2)
+
%define SINH(X) ((antiln(X)-antiln(-(X)))/2)
-%define TANH(X) ((antiln(X)-antiln(-(X)))/(antiln(X)+antiln(-(X))))
-# Return the distance between the points `(X1,Y1)` and `(X2,Y2)`.
-%define DIST(X1,Y1,X2,Y2) sqrt(((X2)-(X1))*((X2)-(X1))+((Y2)-(Y1))*((Y2)-(Y1)))
+%define TANH(X) ((antiln(X)-antiln(-(X)))/(antiln(X)+antiln(-(X))))
-# Return the magnitude of the vector `(X,Y)`.
%define MAG(X,Y) sqrt((X)*(X)+(Y)*(Y))
-# Return `BASE` raised to the power of `EXP`.
+%define DIST(X1, Y1, X2, Y2) MAG(X2-X1,Y2-Y1)
+
+%define RAD(DEG) ((DEG) * 0.017453292519943295)
+
+%define DEG(RAD) ((RAD) * 57.29577951308232)
+
%define POW(BASE,EXP) antiln(ln(BASE)*(EXP))
-# Gamma correct `VALUE` with power 2.2
-%define GAMMA(VALUE) antiln(ln(VALUE)/2.2)
+%define ROOT(BASE,N) antiln(ln(BASE)/(N))
-# Clamp `VALUE` above zero. (Returns 0 for `VALUE` < 0)
-%define POSITIVE_CLAMP(VALUE) (((VALUE)>0)*(VALUE))
+%define LOG(VAL,BASE) (ln(VAL)/ln(BASE))
-# Clamp `VALUE` below zero. (Returns 0 for `VALUE` > 0)
-%define NEGATIVE_CLAMP(VALUE) (((VALUE)<0)*(VALUE))
+%define LERP(T,OUT0,OUT1) ((OUT0)+(T)*((OUT1)-(OUT0)))
-# Clamp `VALUE` between `MIN` and `MAX`.
-# (Returns `MIN` for `VALUE` < `MIN`, `MAX` for `VALUE` > `MAX`)
-%define CLAMP(VALUE,MIN,MAX) (((VALUE)>(MIN))*((MAX)+((VALUE)-(MAX))*((VALUE)<(MAX))))
+%define INVLERP(VAL,IN0,IN1) (((VAL)-(IN0))/((IN1)-(IN0)))
-# Return the `N`th bit of `V`'s binary representation.
-%define BIT(N,V) (((V) // antiln((N) * ln 2) % 2))
+%define REMAP(T,IN0,IN1,OUT0,OUT1) (LERP(INVLERP(IN0,IN1,T),OUT0,OUT1))
-# Linearly interpolate between `A` and `B` by `T`.
-%define LERP(A,B,T) ((A)+((B)-(A))*(T))
+%define CLAMP(VAL,MIN,MAX) ((MAX)-(((MAX)-((((VAL)-(MIN))*((VAL)>(MIN)))+ (MIN)))*((VAL)<(MAX))))
-# Work out the ratio of `VAL` from `A` to `B`.
-%define INVLERP(VAL,A,B) ((VAL) - (A)) / ((B) - (A))
+%define POSITIVE_CLAMP(VAL) (((VAL)>0)*(VAL))
-# Re-maps a `V` from the range `A` to `B` to the range `C` to `D`.
-%define MAP(A,B,C,D,V) (((V)-(B))*((D)-(C))/((A)-(B))+(C))
+%define NEGATIVE_CLAMP(VALUE) (((VALUE)<0)*(VALUE))
-# Convert degrees to radians.
-%define RAD(DEG) ((DEG) * 0.017453292519943295)
+%define RANDOM() random("0.0", "1.0")
-# Convert radians to degrees.
-%define DEG(RAD) ((RAD) * 57.29577951308232)
+%define RANDOM_ANGLE() random("0.0", "360.0")
+
+%define APPROX(A,B,TOLERANCE) (abs((B)-(A)) < (TOLERANCE))
diff --git a/md5.gs b/md5.gs
new file mode 100644
index 0000000..3d7bfd4
--- /dev/null
+++ b/md5.gs
@@ -0,0 +1,246 @@
+#
+# DEPENDS ON: the bitwise library providing:
+# XOR32, AND32, OR32, NOT32, ADD32 (macros)
+# rol32(a, b) (function)
+# xor4, and4, or4 (lookup lists, must be pre-populated)
+#
+# USAGE:
+# 1. Populate md5_input with one byte per item.
+# 2. Call md5.
+# 3. Read 16 bytes from md5_output.
+#
+# INPUT LIST: md5_input — one byte (0‥255) per item
+# OUTPUT LIST: md5_output — 16 bytes, little-endian (H0 H1 H2 H3)
+
+list md5_input;
+list md5_output;
+
+proc md5_input_encode_ascii text {
+ BYTES_ENCODE_ASCII(md5_input)
+}
+
+func md5_output_decode_hex(start=1, end=-1) {
+ BYTES_DECODE_HEX(md5_output)
+}
+
+# ── private state ─────────────────────────────────────────────────────────────
+list _md5_M; # 16 x 32-bit words for the current 512-bit chunk
+list _md5_padded; # padded copy of md5_input
+
+var _md5_H0 = 0; # hash state words
+var _md5_H1 = 0;
+var _md5_H2 = 0;
+var _md5_H3 = 0;
+
+var _md5_a = 0; # working variables
+var _md5_b = 0;
+var _md5_c = 0;
+var _md5_d = 0;
+var _md5_F = 0; # round function output / accumulator
+var _md5_g = 0; # message word index for current round
+var _md5_i = 0; # round counter
+var _md5_temp = 0;
+var _md5_chunk = 0;
+var _md5_nchunks = 0;
+
+# ── _md5_init_tables ──────────────────────────────────────────────────────────
+list _md5_K = [ # 64 round constants floor(2^32 * |sin(i+1)|)
+ 0xd76aa478, 0xe8c7b756,
+ 0x242070db, 0xc1bdceee,
+ 0xf57c0faf, 0x4787c62a,
+ 0xa8304613, 0xfd469501,
+ 0x698098d8, 0x8b44f7af,
+ 0xffff5bb1, 0x895cd7be,
+ 0x6b901122, 0xfd987193,
+ 0xa679438e, 0x49b40821,
+ # Round 2 (i = 16..31)
+ 0xf61e2562, 0xc040b340,
+ 0x265e5a51, 0xe9b6c7aa,
+ 0xd62f105d, 0x02441453,
+ 0xd8a1e681, 0xe7d3fbc8,
+ 0x21e1cde6, 0xc33707d6,
+ 0xf4d50d87, 0x455a14ed,
+ 0xa9e3e905, 0xfcefa3f8,
+ 0x676f02d9, 0x8d2a4c8a,
+ # Round 3 (i = 32..47)
+ 0xfffa3942, 0x8771f681,
+ 0x6d9d6122, 0xfde5380c,
+ 0xa4beea44, 0x4bdecfa9,
+ 0xf6bb4b60, 0xbebfbc70,
+ 0x289b7ec6, 0xeaa127fa,
+ 0xd4ef3085, 0x04881d05,
+ 0xd9d4d039, 0xe6db99e5,
+ 0x1fa27cf8, 0xc4ac5665,
+ # Round 4 (i = 48..63)
+ 0xf4292244, 0x432aff97,
+ 0xab9423a7, 0xfc93a039,
+ 0x655b59c3, 0x8f0ccc92,
+ 0xffeff47d, 0x85845dd1,
+ 0x6fa87e4f, 0xfe2ce6e0,
+ 0xa3014314, 0x4e0811a1,
+ 0xf7537e82, 0xbd3af235,
+ 0x2ad7d2bb, 0xeb86d391
+];
+
+list _md5_s = [ # 64 per-round left-rotate amounts
+ # Round 1
+ 7, 12, 17, 22,
+ 7, 12, 17, 22,
+ 7, 12, 17, 22,
+ 7, 12, 17, 22,
+ # Round 2
+ 5, 9, 14, 20,
+ 5, 9, 14, 20,
+ 5, 9, 14, 20,
+ 5, 9, 14, 20,
+ # Round 3
+ 4, 11, 16, 23,
+ 4, 11, 16, 23,
+ 4, 11, 16, 23,
+ 4, 11, 16, 23,
+ # Round 4
+ 6, 10, 15, 21,
+ 6, 10, 15, 21,
+ 6, 10, 15, 21,
+ 6, 10, 15, 21
+];
+
+# ── _md5_pad_msg ──────────────────────────────────────────────────────────────
+# Copies md5_input into _md5_padded then applies RFC 1321 Section 3.1-3.2 padding:
+# 1. Append 0x80.
+# 2. Append 0x00 bytes until length ≡ 56 (mod 64).
+# 3. Append the original bit-length as a 64-bit little-endian integer.
+#
+# The bit-length is split into two 32-bit halves to stay within JS double
+# precision: lo = (msglen % 2^29) * 8, hi = msglen // 2^29
+proc _md5_pad_msg {
+ local msglen = length md5_input;
+ local bitlen_lo = (msglen % 0x20000000) * 8;
+ local bitlen_hi = msglen // 0x20000000;
+ local i = 1;
+
+ delete _md5_padded;
+
+ repeat msglen {
+ add md5_input[i] to _md5_padded;
+ i += 1;
+ }
+
+ add 0x80 to _md5_padded;
+
+ until length _md5_padded % 64 == 56 {
+ add 0 to _md5_padded;
+ }
+
+ # low 32 bits of bit-length
+ add bitlen_lo % 0x100 to _md5_padded;
+ add (bitlen_lo // 0x100) % 0x100 to _md5_padded;
+ add (bitlen_lo // 0x10000) % 0x100 to _md5_padded;
+ add (bitlen_lo // 0x1000000) % 0x100 to _md5_padded;
+ # high 32 bits of bit-length
+ add bitlen_hi % 0x100 to _md5_padded;
+ add (bitlen_hi // 0x100) % 0x100 to _md5_padded;
+ add (bitlen_hi // 0x10000) % 0x100 to _md5_padded;
+ add (bitlen_hi // 0x1000000) % 0x100 to _md5_padded;
+}
+
+# ── _md5_process_chunk ────────────────────────────────────────────────────────
+# Processes one 512-bit (64-byte) chunk.
+# base: 1-based start index into _md5_padded.
+proc _md5_process_chunk base {
+ local wi = 0;
+ local bi = 0;
+
+ # Unpack 64 bytes -> 16 little-endian 32-bit words in _md5_M
+ delete _md5_M;
+ wi = 0;
+ repeat 16 {
+ bi = $base + wi * 4;
+ add _md5_padded[bi]
+ + _md5_padded[bi + 1] * 0x100
+ + _md5_padded[bi + 2] * 0x10000
+ + _md5_padded[bi + 3] * 0x1000000
+ to _md5_M;
+ wi += 1;
+ }
+
+ # Initialise working variables from current hash state
+ _md5_a = _md5_H0;
+ _md5_b = _md5_H1;
+ _md5_c = _md5_H2;
+ _md5_d = _md5_H3;
+
+ # 64 rounds
+ _md5_i = 0;
+ repeat 64 {
+ if _md5_i < 16 {
+ # Round 1 — F(b,c,d) = (b AND c) OR (NOT b AND d)
+ _md5_F = or32(and32(_md5_b, _md5_c), and32(not32(_md5_b), _md5_d));
+ _md5_g = _md5_i;
+ } elif _md5_i < 32 {
+ # Round 2 — G(b,c,d) = (d AND b) OR (NOT d AND c)
+ _md5_F = or32(and32(_md5_d, _md5_b), and32(not32(_md5_d), _md5_c));
+ _md5_g = (5 * _md5_i + 1) % 16;
+ } elif _md5_i < 48 {
+ # Round 3 — H(b,c,d) = b XOR c XOR d
+ _md5_F = xor32(xor32(_md5_b, _md5_c), _md5_d);
+ _md5_g = (3 * _md5_i + 5) % 16;
+ } else {
+ # Round 4 — I(b,c,d) = c XOR (b OR NOT d)
+ _md5_F = xor32(_md5_c, or32(_md5_b, not32(_md5_d)));
+ _md5_g = (7 * _md5_i) % 16;
+ }
+
+ # temp = b + ROL32(a + F + K[i] + M[g], s[i])
+ _md5_F = add32(
+ add32(add32(_md5_a, _md5_F), _md5_K[_md5_i + 1]),
+ _md5_M[_md5_g + 1]);
+ _md5_temp = _md5_d;
+ _md5_d = _md5_c;
+ _md5_c = _md5_b;
+ _md5_b = add32(_md5_b, rol32(_md5_F, _md5_s[_md5_i + 1]));
+ _md5_a = _md5_temp;
+
+ _md5_i += 1;
+ }
+
+ # Add working variables back into hash state
+ _md5_H0 = add32(_md5_H0, _md5_a);
+ _md5_H1 = add32(_md5_H1, _md5_b);
+ _md5_H2 = add32(_md5_H2, _md5_c);
+ _md5_H3 = add32(_md5_H3, _md5_d);
+}
+
+# ── _md5_emit_word ────────────────────────────────────────────────────────────
+# Appends a 32-bit word to md5_output as 4 little-endian bytes.
+proc _md5_emit_word w {
+ add $w % 0x100 to md5_output;
+ add ($w // 0x100) % 0x100 to md5_output;
+ add ($w // 0x10000) % 0x100 to md5_output;
+ add ($w // 0x1000000) % 0x100 to md5_output;
+}
+
+# ── md5 ───────────────────────────────────────────────────────────────────────
+# Entry point. Reads md5_input, writes 16 bytes to md5_output.
+proc md5 {
+ _md5_pad_msg;
+
+ # RFC 1321 Section 3.3 — initial hash values
+ _md5_H0 = 0x67452301;
+ _md5_H1 = 0xefcdab89;
+ _md5_H2 = 0x98badcfe;
+ _md5_H3 = 0x10325476;
+
+ _md5_nchunks = length _md5_padded // 64;
+ _md5_chunk = 0;
+ repeat _md5_nchunks {
+ _md5_process_chunk _md5_chunk * 64 + 1;
+ _md5_chunk += 1;
+ }
+
+ delete md5_output;
+ _md5_emit_word _md5_H0;
+ _md5_emit_word _md5_H1;
+ _md5_emit_word _md5_H2;
+ _md5_emit_word _md5_H3;
+}
diff --git a/sha256.gs b/sha256.gs
new file mode 100644
index 0000000..0b0995c
--- /dev/null
+++ b/sha256.gs
@@ -0,0 +1,258 @@
+# sha256.gs — SHA-256 (FIPS 180-4) for goboscript
+#
+# DEPENDS ON: bitwise library providing:
+# XOR32, AND32, OR32, NOT32, ADD32 (macros)
+# rol32(a, b) (function)
+# xor4, and4, or4 (lookup lists, pre-populated)
+#
+# USAGE:
+# 1. Populate sha256_input with one byte (0-255) per item.
+# 2. Call sha256.
+# 3. Read 32 bytes from sha256_output (big-endian, standard byte order).
+#
+# INPUT LIST: sha256_input — one byte per item
+# OUTPUT LIST: sha256_output — 32 bytes, big-endian
+
+list sha256_input;
+list sha256_output;
+
+proc sha256_input_encode_ascii text {
+ BYTES_ENCODE_ASCII(sha256_input)
+}
+
+func sha256_output_decode_hex(start=1, end=-1) {
+ BYTES_DECODE_HEX(sha256_output)
+}
+
+# ── private state ─────────────────────────────────────────────────────────────
+list _sha_W; # 64-word message schedule
+list _sha_padded; # padded copy of sha256_input
+
+var _sha_H0 = 0;
+var _sha_H1 = 0;
+var _sha_H2 = 0;
+var _sha_H3 = 0;
+var _sha_H4 = 0;
+var _sha_H5 = 0;
+var _sha_H6 = 0;
+var _sha_H7 = 0;
+
+var _sha_a = 0;
+var _sha_b = 0;
+var _sha_c = 0;
+var _sha_d = 0;
+var _sha_e = 0;
+var _sha_f = 0;
+var _sha_g = 0;
+var _sha_h = 0;
+
+var _sha_i = 0;
+var _sha_T1 = 0;
+var _sha_T2 = 0;
+var _sha_S0 = 0;
+var _sha_S1 = 0;
+var _sha_ch = 0;
+var _sha_maj = 0;
+var _sha_chunk = 0;
+var _sha_nchunks = 0;
+
+# ── SHA-256 helpers (using ror32 via rol32) ───────────────────────────────────
+# ror32(x, n) = rol32(x, 32-n)
+# These are inlined as macros for speed.
+
+# BSIG0(x) = ROTR2(x) XOR ROTR13(x) XOR ROTR22(x)
+%define SHA_BSIG0(X) xor32(xor32(rol32((X),30),rol32((X),19)),rol32((X),10))
+# BSIG1(x) = ROTR6(x) XOR ROTR11(x) XOR ROTR25(x)
+%define SHA_BSIG1(X) xor32(xor32(rol32((X),26),rol32((X),21)),rol32((X),7))
+# SSIG0(x) = ROTR7(x) XOR ROTR18(x) XOR SHR3(x)
+%define SHA_SSIG0(X) xor32(xor32(rol32((X),25),rol32((X),14)),(X)//8)
+# SSIG1(x) = ROTR17(x) XOR ROTR19(x) XOR SHR10(x)
+%define SHA_SSIG1(X) xor32(xor32(rol32((X),15),rol32((X),13)),(X)//1024)
+# CH(e,f,g) = (e AND f) XOR (NOT e AND g)
+%define SHA_CH(E,F,G) xor32(and32((E),(F)),and32(not32(E),(G)))
+# MAJ(a,b,c) = (a AND b) XOR (a AND c) XOR (b AND c)
+%define SHA_MAJ(A,B,C) xor32(xor32(and32((A),(B)),and32((A),(C))),and32((B),(C)))
+
+# ── _sha_init_K ───────────────────────────────────────────────────────────────
+list _sha_K = [ # 64 round constants
+ 0x428a2f98, 0x71374491,
+ 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1,
+ 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01,
+ 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe,
+ 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786,
+ 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa,
+ 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d,
+ 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147,
+ 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138,
+ 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb,
+ 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b,
+ 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624,
+ 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08,
+ 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a,
+ 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f,
+ 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb,
+ 0xbef9a3f7, 0xc67178f2
+];
+
+# ── _sha_pad_msg ──────────────────────────────────────────────────────────────
+# SHA-256 padding: same structure as MD5 but big-endian length field.
+proc _sha_pad_msg {
+ local msglen = length sha256_input;
+ local bitlen_lo = (msglen % 0x20000000) * 8;
+ local bitlen_hi = msglen // 0x20000000;
+ local i = 1;
+
+ delete _sha_padded;
+
+ repeat msglen {
+ add sha256_input[i] to _sha_padded;
+ i += 1;
+ }
+
+ add 0x80 to _sha_padded;
+
+ until length _sha_padded % 64 == 56 {
+ add 0 to _sha_padded;
+ }
+
+ # 64-bit bit-length, big-endian (high word first)
+ add (bitlen_hi // 0x1000000) % 0x100 to _sha_padded;
+ add (bitlen_hi // 0x10000) % 0x100 to _sha_padded;
+ add (bitlen_hi // 0x100) % 0x100 to _sha_padded;
+ add bitlen_hi % 0x100 to _sha_padded;
+ add (bitlen_lo // 0x1000000) % 0x100 to _sha_padded;
+ add (bitlen_lo // 0x10000) % 0x100 to _sha_padded;
+ add (bitlen_lo // 0x100) % 0x100 to _sha_padded;
+ add bitlen_lo % 0x100 to _sha_padded;
+}
+
+# ── _sha_process_chunk ────────────────────────────────────────────────────────
+proc _sha_process_chunk base {
+ local wi = 0;
+ local bi = 0;
+
+ # Unpack 16 big-endian 32-bit words from the 64-byte chunk
+ delete _sha_W;
+ wi = 0;
+ repeat 16 {
+ bi = $base + wi * 4;
+ add _sha_padded[bi] * 0x1000000
+ + _sha_padded[bi + 1] * 0x10000
+ + _sha_padded[bi + 2] * 0x100
+ + _sha_padded[bi + 3]
+ to _sha_W;
+ wi += 1;
+ }
+
+ # Extend to 64 words
+ wi = 17;
+ repeat 48 {
+ add add32(add32(add32(
+ SHA_SSIG1(_sha_W[wi - 2]),
+ _sha_W[wi - 7]),
+ SHA_SSIG0(_sha_W[wi - 15])),
+ _sha_W[wi - 16])
+ to _sha_W;
+ wi += 1;
+ }
+
+ # Initialise working variables
+ _sha_a = _sha_H0;
+ _sha_b = _sha_H1;
+ _sha_c = _sha_H2;
+ _sha_d = _sha_H3;
+ _sha_e = _sha_H4;
+ _sha_f = _sha_H5;
+ _sha_g = _sha_H6;
+ _sha_h = _sha_H7;
+
+ # 64 rounds
+ _sha_i = 1;
+ repeat 64 {
+ _sha_T1 = add32(add32(add32(add32(
+ _sha_h,
+ SHA_BSIG1(_sha_e)),
+ SHA_CH(_sha_e, _sha_f, _sha_g)),
+ _sha_K[_sha_i]),
+ _sha_W[_sha_i]);
+ _sha_T2 = add32(SHA_BSIG0(_sha_a), SHA_MAJ(_sha_a, _sha_b, _sha_c));
+
+ _sha_h = _sha_g;
+ _sha_g = _sha_f;
+ _sha_f = _sha_e;
+ _sha_e = add32(_sha_d, _sha_T1);
+ _sha_d = _sha_c;
+ _sha_c = _sha_b;
+ _sha_b = _sha_a;
+ _sha_a = add32(_sha_T1, _sha_T2);
+
+ _sha_i += 1;
+ }
+
+ _sha_H0 = add32(_sha_H0, _sha_a);
+ _sha_H1 = add32(_sha_H1, _sha_b);
+ _sha_H2 = add32(_sha_H2, _sha_c);
+ _sha_H3 = add32(_sha_H3, _sha_d);
+ _sha_H4 = add32(_sha_H4, _sha_e);
+ _sha_H5 = add32(_sha_H5, _sha_f);
+ _sha_H6 = add32(_sha_H6, _sha_g);
+ _sha_H7 = add32(_sha_H7, _sha_h);
+}
+
+# ── _sha_emit_word ─────────────────────────────────────────────────────────────
+# Appends a 32-bit word to sha256_output as 4 big-endian bytes.
+proc _sha_emit_word w {
+ add ($w // 0x1000000) % 0x100 to sha256_output;
+ add ($w // 0x10000) % 0x100 to sha256_output;
+ add ($w // 0x100) % 0x100 to sha256_output;
+ add $w % 0x100 to sha256_output;
+}
+
+# ── sha256 ────────────────────────────────────────────────────────────────────
+# Entry point. Reads sha256_input, writes 32 bytes to sha256_output.
+proc sha256 {
+ _sha_pad_msg;
+
+ # FIPS 180-4 §5.3.3 — initial hash values (first 32 bits of fractional
+ # parts of square roots of the first 8 primes)
+ _sha_H0 = 0x6a09e667;
+ _sha_H1 = 0xbb67ae85;
+ _sha_H2 = 0x3c6ef372;
+ _sha_H3 = 0xa54ff53a;
+ _sha_H4 = 0x510e527f;
+ _sha_H5 = 0x9b05688c;
+ _sha_H6 = 0x1f83d9ab;
+ _sha_H7 = 0x5be0cd19;
+
+ _sha_nchunks = length _sha_padded // 64;
+ _sha_chunk = 0;
+ repeat _sha_nchunks {
+ _sha_process_chunk _sha_chunk * 64 + 1;
+ _sha_chunk += 1;
+ }
+
+ delete sha256_output;
+ _sha_emit_word _sha_H0;
+ _sha_emit_word _sha_H1;
+ _sha_emit_word _sha_H2;
+ _sha_emit_word _sha_H3;
+ _sha_emit_word _sha_H4;
+ _sha_emit_word _sha_H5;
+ _sha_emit_word _sha_H6;
+ _sha_emit_word _sha_H7;
+}
diff --git a/shlex.gs b/shlex.gs
new file mode 100644
index 0000000..0993a99
--- /dev/null
+++ b/shlex.gs
@@ -0,0 +1,104 @@
+#
+# USAGE
+# Include this file in your project and call:
+#
+# parse_args "git commit -m 'fix bug' --author=\"Jane\"";
+#
+# Parsed tokens are stored in the global list `args`:
+# args[1] => "git"
+# args[2] => "commit"
+# args[3] => "-m"
+# args[4] => "fix bug"
+# args[5] => "--author=Jane"
+#
+# SYNTAX SUPPORTED
+# Unquoted tokens — delimited by spaces
+# Single quotes — everything inside is literal, no escapes
+# Double quotes — spaces preserved; backslash escapes work inside
+# Backslash — outside quotes, escapes the next character (e.g. '\ ' => ' ')
+# Adjacent quoting — foo"bar"'baz' => foobarbaz (quotes can be concatenated)
+#
+# GLOBAL OUTPUTS
+# list args — holds one token per index after parse_args returns
+
+list shlex_args;
+
+
+# ── parse_args ────────────────────────────────────────────────────────────────
+# proc parse_args str
+# str — the raw input string to tokenise
+#
+# Clears `args` before filling it. Unclosed quotes consume until end-of-string
+# (same lenient behaviour as most interactive shells).
+
+proc shlex_split str {
+ delete shlex_args;
+
+ local _pa_i = 1;
+ local _pa_len = length $str;
+ local _pa_cur = "";
+ local _pa_in_sq = 0;
+ local _pa_in_dq = 0;
+
+ until _pa_i > _pa_len {
+ local _pa_c = $str[_pa_i];
+
+ # ── inside single quotes ──────────────────────────────────────────────
+ # Nothing is special except the closing quote.
+ if _pa_in_sq == 1 {
+ if _pa_c == "'" {
+ _pa_in_sq = 0;
+ } else {
+ _pa_cur &= _pa_c;
+ }
+
+ # ── inside double quotes ──────────────────────────────────────────────
+ # Backslash escapes the next character; everything else is literal.
+ } elif _pa_in_dq == 1 {
+ if _pa_c == "\"" {
+ _pa_in_dq = 0;
+ } elif _pa_c == "\\" {
+ _pa_i += 1;
+ if _pa_i <= _pa_len {
+ _pa_cur &= $str[_pa_i];
+ }
+ } else {
+ _pa_cur &= _pa_c;
+ }
+
+ # ── unquoted ──────────────────────────────────────────────────────────
+ } elif _pa_c == "'" {
+ # Enter single-quote mode (may continue current token).
+ _pa_in_sq = 1;
+
+ } elif _pa_c == "\"" {
+ # Enter double-quote mode (may continue current token).
+ _pa_in_dq = 1;
+
+ } elif _pa_c == "\\" {
+ # Backslash outside quotes: take the next character literally.
+ _pa_i += 1;
+ if _pa_i <= _pa_len {
+ _pa_cur &= $str[_pa_i];
+ }
+
+ } elif _pa_c == " " {
+ # Space: flush current token if non-empty.
+ if length _pa_cur > 0 {
+ add _pa_cur to shlex_args;
+ _pa_cur = "";
+ }
+
+ } else {
+ # Ordinary character.
+ _pa_cur &= _pa_c;
+ }
+
+ _pa_i += 1;
+ }
+
+ # Flush the final token (handles no-trailing-space and unclosed quotes).
+ if length _pa_cur > 0 {
+ add _pa_cur to shlex_args;
+ }
+}
diff --git a/string.gs b/string.gs
index d65c89f..779fef9 100644
--- a/string.gs
+++ b/string.gs
@@ -6,117 +6,102 @@
list strbuf;
-# Slice $text from $start to $end, $end is exclusive. $start and $end are 1-based.
-func slice(text, start, end) {
- delete strbuf;
- repeat $end - $start {
- add $text[$start + length(strbuf)] to strbuf;
+# Returns a substring of $text from $start to $end (inclusive).
+# Negative indices count from the end of the string (-1 = last character).
+# If $start or $end are out of bounds, they are clamped to the string length.
+# If the range is invalid, an empty string is returned.
+#
+# @param {string} text - The string to slice.
+# @param {number} start - The start index (default: 1).
+# @param {number} end - The end index, inclusive (default: -1).
+# @returns {string} The substring, or "" if the range is invalid.
+#
+# @example str_slice("hello", 2, 4) => "ell"
+# @example str_slice("hello", -3) => "llo"
+# @example str_slice("hello", 2) => "ello"
+# @example str_slice("hello") => "hello"
+func str_slice(text, start=1, end=-1) {
+ local start = $start;
+ local end = $end;
+ if start < 0 {
+ start = length($text) + start + 1;
+ }
+ if end < 0 {
+ end = length($text) + end + 1;
+ }
+ if start < 1 {
+ start = 1;
+ }
+ if end > length($text) {
+ end = length($text);
+ }
+ if end < 1 or start > length($text) or end < start {
+ return "";
}
- return strbuf;
-}
-
-# Conditional macro to check if $text starts with $prefix.
-%define ENDSWITH(TEXT,SUFFIX) \
- (slice((TEXT), 1 + (length(TEXT) - length(SUFFIX)), 1 + length(TEXT)) == (SUFFIX))
-
-# Conditional macro to check if $text starts with $prefix.
-%define STARTSWITH(TEXT,PREFIX) \
- (slice((TEXT), 1, 1 + length(PREFIX)) == (PREFIX))
-
-# Remove $prefix from the beginning of $text.
-%define REMOVEPREFIX(TEXT,PREFIX) (splice((TEXT), 1, length(PREFIX), ""))
-
-# Remove $suffix from the end of $text.
-%define REMOVESUFFIX(TEXT,SUFFIX) \
- (splice(TEXT, 1 + (length(TEXT) - length(SUFFIX)), length(SUFFIX), ""))
-
-# Replace all occurrences of $subtext with $repl in $text.
-func replace(text, subtext, repl) {
- local i = 1;
- local result = "";
delete strbuf;
- until i > length($text) {
- add $text[i] to strbuf;
- if contains(strbuf, $subtext) {
- repeat length($subtext) {
- delete strbuf["last"];
- }
- result &= strbuf & $repl;
- delete strbuf;
- }
- i++;
+ repeat end - start + 1 {
+ add $text[start + length(strbuf)] to strbuf;
}
- return result & strbuf;
+ return strbuf;
}
-# Replace first $n occurrences of $subtext with $repl in $text.
-func replacen(text, subtext, repl, n) {
- local i = 1;
- local n = 0;
- local result = "";
- delete strbuf;
- until i > length($text) {
- add $text[i] to strbuf;
- if contains(strbuf, $subtext) {
- if n < $n {
- repeat length($subtext) {
- delete strbuf["last"];
- }
- result &= strbuf & $repl;
- } else {
- result &= strbuf;
- }
- delete strbuf;
- n++;
- }
- i++;
- }
- return result & strbuf;
+# Returns true if $text ends with the given $suffix, false otherwise.
+# The check is NOT case-sensitive.
+#
+# @param {string} text - The string to check.
+# @param {string} suffix - The suffix to look for at the end of $text.
+# @returns {boolean} True if $text ends with $suffix, false otherwise.
+#
+# @example str_ends_with("hello", "lo") => true
+# @example str_ends_with("hello", "he") => false
+# @example str_ends_with("hello", "") => true
+func str_ends_with(text, suffix) {
+ if $suffix == "" { return true; }
+ return str_slice($text, -length($suffix)) == $suffix;
}
-# Replace the $n-th occurrence of $subtext with $repl in $text.
-func replacenth(text, subtext, repl, n) {
- local i = 1;
- local n = 1;
- local result = "";
- delete strbuf;
- until i > length($text) {
- add $text[i] to strbuf;
- if contains(strbuf, $subtext) {
- if n == $n {
- repeat length($subtext) {
- delete strbuf["last"];
- }
- result &= strbuf & $repl;
- } else {
- result &= strbuf;
- }
- delete strbuf;
- n++;
- }
- i++;
- }
- return result & strbuf;
+# Returns true if $text begins with the given $prefix, false otherwise.
+# The check is NOT case-sensitive.
+#
+# @param {string} text - The string to check.
+# @param {string} prefix - The prefix to look for at the start of $text.
+# @returns {boolean} True if $text starts with $prefix, false otherwise.
+#
+# @example str_starts_with("hello", "he") => true
+# @example str_starts_with("hello", "lo") => false
+# @example str_starts_with("hello", "") => true
+func str_starts_with(text, prefix) {
+ return str_slice($text, 1, length($prefix)) == $prefix;
}
-# Remove $len characters from $text starting at $start and insert $repl in its place.
-func splice(text, start, len, repl) {
- delete strbuf;
- repeat $start - 1 {
- add $text[1+length(strbuf)] to strbuf;
- }
- local result = strbuf & $repl;
+# Returns a copy of $text with its characters in reverse order.
+#
+# @param {string} text - The string to reverse.
+# @returns {string} The reversed string.
+#
+# @example str_reverse("hello") => "olleh"
+# @example str_reverse("abcd") => "dcba"
+# @example str_reverse("") => ""
+func str_reverse(text) {
delete strbuf;
- local i = $start + $len;
- repeat 1 + (length($text) - ($start + $len)) {
- add $text[i] to strbuf;
+ local i = 1;
+ repeat length($text) {
+ add $text[1+length($text)-i] to strbuf;
i++;
}
- return result & strbuf;
+ return strbuf;
}
-# Transform ASCII letters in $text to uppercase.
-func uppercase(text) {
+# Returns a copy of $text with all ASCII lowercase letters converted to uppercase.
+# Non-alphabetic characters are left unchanged.
+#
+# @param {string} text - The string to convert.
+# @returns {string} The uppercased string.
+#
+# @example str_upper("hello") => "HELLO"
+# @example str_upper("Hello!") => "HELLO!"
+# @example str_upper("123") => "123"
+func str_upper(text) {
delete strbuf;
repeat length($text) {
local i = 1;
@@ -132,8 +117,16 @@ func uppercase(text) {
return strbuf;
}
-# Transform ASCII letters in $text to lowercase.
-func lowercase(text) {
+# Returns a copy of $text with all ASCII uppercase letters converted to lowercase.
+# Non-alphabetic characters are left unchanged.
+#
+# @param {string} text - The string to convert.
+# @returns {string} The lowercased string.
+#
+# @example str_lower("HELLO") => "hello"
+# @example str_lower("Hello!") => "hello!"
+# @example str_lower("123") => "123"
+func str_lower(text) {
delete strbuf;
repeat length($text) {
local i = 1;
@@ -149,8 +142,16 @@ func lowercase(text) {
return strbuf;
}
-# Transform the first character in $text to uppercase, and the rest to lowercase
-func capitalize(text) {
+# Returns a copy of $text with the first character uppercased and all
+# remaining characters lowercased. Non-alphabetic characters are unchanged.
+#
+# @param {string} text - The string to capitalize.
+# @returns {string} The capitalized string.
+#
+# @example str_capitalize("hello") => "Hello"
+# @example str_capitalize("HELLO") => "Hello"
+# @example str_capitalize("hELLO wORLD") => "Hello world"
+func str_capitalize(text) {
delete strbuf;
local i = 1;
until $text[1] == ASCII_UPPERCASE[i] or i > 26 {
@@ -175,39 +176,85 @@ func capitalize(text) {
return strbuf;
}
-# Return the index of the first occurrence of $char in $text, or 0 if not found.
-func findchar(text, char) {
+# Returns a copy of $text in title case: the first letter of each word is
+# uppercased and subsequent letters are lowercased. A "word" is defined as
+# a sequence of ASCII alphabetic characters; non-alpha characters act as
+# word boundaries and are passed through unchanged.
+#
+# @param {string} text - The string to convert to title case.
+# @returns {string} The title-cased string.
+#
+# @example str_title("hello world") => "Hello World"
+# @example str_title("HELLO WORLD") => "Hello World"
+# @example str_title("it's a test") => "It'S A Test"
+func str_title(text) {
+ local result = "";
local i = 1;
+ local boundary = false;
repeat length($text) {
- if $text[i] == $char {
- return i;
+ local j = 1;
+ until $text[i] == ASCII_UPPERCASE[j] or j > 26 {
+ j++;
+ }
+ if j > 26 {
+ boundary = false;
+ result &= $text[i];
+ } else {
+ if boundary == false {
+ boundary = true;
+ result &= ASCII_UPPERCASE[j];
+ } else {
+ result &= ASCII_LOWERCASE[j];
+ }
}
i++;
}
- return 0;
+ return result;
}
-# Return the index of the last occurrence of $char in $text, or 0 if not found.
-func rfindchar(text, char) {
- local i = length($text);
- repeat length($text) {
- if $text[i] == $char {
- return i;
- }
- i--;
+# Returns a new string consisting of $text repeated $n times.
+# If $n is 0 or negative, an empty string is returned.
+#
+# @param {string} text - The string to repeat.
+# @param {number} n - The number of times to repeat $text.
+# @returns {string} The repeated string.
+#
+# @example str_repeat("ab", 3) => "ababab"
+# @example str_repeat("hi", 1) => "hi"
+# @example str_repeat("x", 0) => ""
+func str_repeat(text, n) {
+ local result = "";
+ repeat $n {
+ result &= $text;
}
- return 0;
+ return result;
}
-# Return true if all characters in $text are alphanumeric and there is at least one
-# character.
-func isalnum(text) {
- if length($text) == 0 {
+# Returns true if strings $a and $b are equal (same length and identical
+# characters), false otherwise. Uses costume-switching to perform an
+# ordinal character-by-character comparison: each character is mapped to
+# its corresponding ASCII costume index, allowing exact case-sensitive
+# matching for all printable ASCII characters.
+# Requires costumes to be defined with:
+# costumes "blank.svg" as "@ascii/";
+#
+# @param {string} a - The first string to compare.
+# @param {string} b - The second string to compare.
+# @returns {boolean} True if $a and $b are identical, false otherwise.
+#
+# @example str_eq("hello", "hello") => true
+# @example str_eq("hello", "Hello") => false
+# @example str_eq("abc", "ab") => false
+func str_eq(a, b) {
+ if length($a) != length($b) {
return false;
}
local i = 1;
- repeat length($text) {
- if $text[i] not in ASCII_UPPERCASE & ASCII_DIGITS {
+ repeat length($a) {
+ switch_costume $a;
+ local c = costume_number();
+ switch_costume $b;
+ if c != costume_number() {
return false;
}
i++;
@@ -215,27 +262,120 @@ func isalnum(text) {
return true;
}
-# Return true if all characters in $text are alphabetic and there is at least one
-# character.
-func isalpha(text) {
- if length($text) == 0 {
- return false;
+# Splits $text into a list of substrings separated by $sep and stores the
+# result in the list `str_split`. Consecutive separators produce
+# empty-string entries. If $sep does not appear, `str_split` contains
+# only $text as its single item.
+#
+# @param {string} text - The string to split.
+# @param {string} sep - The separator character (default: " ").
+# @returns {void} Results are stored in the list `str_split`.
+#
+# @example str_split "a,b,c", ","; => str_split = ["a", "b", "c"]
+# @example str_split "hello"; => str_split = ["hello"]
+# @example str_split "a,,b", ","; => str_split = ["a", "", "b"]
+list str_split;
+
+proc str_split text, sep=" " {
+ delete str_split;
+ delete strbuf;
+ local i = 1;
+ repeat length($text) {
+ if $text[i] == $sep {
+ add strbuf to str_split;
+ delete strbuf;
+ } else {
+ add $text[i] to strbuf;
+ }
+ i++;
}
+ add strbuf to str_split;
+}
+
+# Splits $text into individual lines using LF (\n) as line
+# endings and stores the result in the list `str_split_lines`.
+#
+# @param {string} text - The string to split into lines.
+# @returns {void} Results are stored in the list `str_split_lines`.
+#
+# @example str_split_lines "a\nb\nc"; => str_split_lines = ["a", "b", "c"]
+# @example str_split_lines "end\n"; => str_split_lines = ["end"]
+list str_split_lines;
+
+proc str_split_lines text {
+ delete str_split_lines;
+ delete strbuf;
local i = 1;
repeat length($text) {
- if $text[i] not in ASCII_UPPERCASE {
- return false;
+ if $text[i] in "\n" {
+ add strbuf to str_split_lines;
+ delete strbuf;
+ } else {
+ add $text[i] to strbuf;
}
i++;
}
- return true;
+ if strbuf == "" {} else {
+ add strbuf to str_split_lines;
+ }
+}
+
+# Returns $text truncated to at most $maxlength characters. If truncation
+# is necessary, the returned string ends with "..." and its total length
+# equals $maxlength (i.e. $maxlength - 3 characters of original text plus
+# the three-character ellipsis). If $text is already within the limit, it
+# is returned unchanged.
+#
+# @param {string} text - The string to truncate.
+# @param {number} maxlength - The maximum allowed length of the result.
+# @returns {string} The original string, or a truncated string ending in "...".
+#
+# @example str_truncate("hello world", 8) => "hello..."
+# @example str_truncate("hi", 10) => "hi"
+# @example str_truncate("abcdefg", 7) => "abcdefg"
+func str_truncate(text, maxlength) {
+ if length($text) > $maxlength {
+ return str_slice($text, 1, $maxlength - 3) & "...";
+ } else {
+ return $text;
+ }
}
-# Conditional macro to check if $text is a digit.
-%define ISDIGIT(TEXT) (round(TEXT) == (TEXT))
+# Counts how many characters in $text are also present in the $chars set.
+# Each character position in $text is checked independently; $chars acts
+# as an unordered set of allowed characters, not a substring pattern.
+#
+# @param {string} text - The string to scan.
+# @param {string} chars - A string of characters to count occurrences of.
+# @returns {number} The total count of characters in $text that appear in $chars.
+#
+# @example str_count_char("hello", "lo") => 3 (l, l, o)
+# @example str_count_char("aabbcc", "ac") => 4
+# @example str_count_char("abc", "xyz") => 0
+func str_count_char(text, chars) {
+ local i = 1;
+ local count = 0;
+ repeat length($text) {
+ if $text[i] in $chars {
+ count++;
+ }
+ i++;
+ }
+ return count;
+}
-# Remove leading characters in $text that are in $chars.
-func lstrip(text, chars) {
+# Returns a copy of $text with leading characters that appear in $chars
+# removed. Stripping stops as soon as a character not in $chars is found.
+# By default, strips ASCII whitespace (space, tab, newline, carriage return).
+#
+# @param {string} text - The string to strip.
+# @param {string} chars - Characters to remove from the left (default: " \t\n\r").
+# @returns {string} The left-stripped string.
+#
+# @example str_lstrip(" hello") => "hello"
+# @example str_lstrip("xxhello", "x") => "hello"
+# @example str_lstrip("hello ") => "hello "
+func str_lstrip(text, chars=" \t\n\r") {
local i = 1;
until $text[i] not in $chars or i > length($text) {
i++;
@@ -248,10 +388,20 @@ func lstrip(text, chars) {
return strbuf;
}
-# Remove trailing characters in $text that are in $chars.
-func rstrip(text, chars) {
+# Returns a copy of $text with trailing characters that appear in $chars
+# removed. Stripping stops as soon as a character not in $chars is found
+# scanning from the right. By default, strips ASCII whitespace.
+#
+# @param {string} text - The string to strip.
+# @param {string} chars - Characters to remove from the right (default: " \t\n\r").
+# @returns {string} The right-stripped string.
+#
+# @example str_rstrip("hello ") => "hello"
+# @example str_rstrip("helloxx", "x") => "hello"
+# @example str_rstrip(" hello") => " hello"
+func str_rstrip(text, chars=" \t\n\r") {
local i = length($text);
- until $text[i] not in $chars or i == 1 {
+ until $text[i] not in $chars or i == 0 {
i--;
}
delete strbuf;
@@ -261,10 +411,20 @@ func rstrip(text, chars) {
return strbuf;
}
-# Remove leading and trailing characters in $text that are in $chars.
-func strip(text, chars) {
+# Returns a copy of $text with both leading and trailing characters that
+# appear in $chars removed. Equivalent to applying str_lstrip then
+# str_rstrip. By default, strips ASCII whitespace.
+#
+# @param {string} text - The string to strip.
+# @param {string} chars - Characters to remove from both ends (default: " \t\n\r").
+# @returns {string} The stripped string.
+#
+# @example str_strip(" hello ") => "hello"
+# @example str_strip("xxhelloxx", "x") => "hello"
+# @example str_strip("hello") => "hello"
+func str_strip(text, chars=" \t\n\r") {
local i = 1;
- until $text[i] not in $chars or i > length($text) {
+ until i > length($text) or $text[i] not in $chars {
i++;
}
delete strbuf;
@@ -272,167 +432,425 @@ func strip(text, chars) {
add $text[i] to strbuf;
i++;
}
- until strbuf["last"] not in $chars {
+ until length(strbuf) == 0 or strbuf["last"] not in $chars {
delete strbuf["last"];
}
return strbuf;
}
-list split;
-# Split $text into list `split`, separated by character $sep.
-proc split text, sep {
- delete split;
- delete strbuf;
+# Returns true if $text is non-empty and every character is an ASCII
+# letter (A–Z, a–z) or ASCII digit (0–9). Returns false for empty strings
+# or strings containing any other character.
+#
+# @param {string} text - The string to test.
+# @returns {boolean} True if $text is non-empty and entirely alphanumeric.
+#
+# @example str_is_alnum("abc123") => true
+# @example str_is_alnum("abc!") => false
+# @example str_is_alnum("") => false
+func str_is_alnum(text) {
+ if length($text) == 0 {
+ return false;
+ }
local i = 1;
repeat length($text) {
- if $text[i] == $sep {
- add strbuf to split;
- delete strbuf;
- } else {
- add $text[i] to strbuf;
+ if $text[i] not in ASCII_UPPERCASE & ASCII_DIGITS {
+ return false;
}
i++;
}
- add strbuf to split;
+ return true;
}
-# Split $text into list `split`, separated by newlines.
-proc splitlines text {
- delete split;
- delete strbuf;
+# Returns true if $text is non-empty and every character is an ASCII
+# letter (A–Z or a–z). Returns false for empty strings or strings
+# containing digits, punctuation, or other non-alpha characters.
+#
+# @param {string} text - The string to test.
+# @returns {boolean} True if $text is non-empty and entirely alphabetic.
+#
+# @example str_is_alpha("hello") => true
+# @example str_is_alpha("hello1") => false
+# @example str_is_alpha("") => false
+func str_is_alpha(text) {
+ if length($text) == 0 {
+ return false;
+ }
local i = 1;
repeat length($text) {
- if $text[i] in "\r\n" {
- add strbuf to split;
- delete strbuf;
- } else {
- add $text[i] to strbuf;
+ if $text[i] not in ASCII_UPPERCASE {
+ return false;
}
i++;
}
- if strbuf == "" {} else {
- add strbuf to split;
- }
+ return true;
}
-# Reverse $text.
-func reverse(text) {
- delete strbuf;
+# Returns true if $text represents an integer or decimal number (i.e. it
+# round-trips through the round() function unchanged). Returns false for
+# strings containing non-numeric content.
+#
+# @param {string} text - The string to test.
+# @returns {boolean} True if $text is a valid numeric value.
+#
+# @example str_is_digit("42") => true
+# @example str_is_digit("3.14") => false
+# @example str_is_digit("hello") => false
+func str_is_digit(text) {
+ return round($text) == $text;
+}
+
+# Returns the 1-based index of the first occurrence of $char in $text,
+# scanning left to right. Returns 0 if $char is not found.
+# Only single-character values for $char are meaningful.
+#
+# @param {string} text - The string to search within.
+# @param {string} char - The character to search for.
+# @returns {number} The 1-based index of the first match, or 0 if not found.
+#
+# @example str_find_char("hello", "l") => 3
+# @example str_find_char("hello", "z") => 0
+# @example str_find_char("abca", "a") => 1
+func str_find_char(text, char) {
local i = 1;
repeat length($text) {
- add $text[1+length($text)-i] to strbuf;
+ if $text[i] == $char {
+ return i;
+ }
i++;
}
- return strbuf;
+ return 0;
}
-# Repeat $text $n times.
-func repeatstr(text, n) {
- local result = "";
- repeat $n {
- result &= $text;
+# Returns the 1-based index of the last occurrence of $char in $text,
+# scanning right to left. Returns 0 if $char is not found.
+# Only single-character values for $char are meaningful.
+#
+# @param {string} text - The string to search within.
+# @param {string} char - The character to search for.
+# @returns {number} The 1-based index of the last match, or 0 if not found.
+#
+# @example str_rfind_char("hello", "l") => 4
+# @example str_rfind_char("hello", "z") => 0
+# @example str_rfind_char("abca", "a") => 4
+func str_rfind_char(text, char) {
+ local i = length($text);
+ repeat length($text) {
+ if $text[i] == $char {
+ return i;
+ }
+ i--;
}
- return result;
+ return 0;
}
-# Return a titlecased version of $text: words start with uppercase characters,
-# all remaining cased characters are lowercase.
-func titlecase(text) {
- local result = "";
+# Returns a new string formed by removing $len characters from $text
+# starting at position $start (1-based) and optionally inserting $repl
+# in their place. If $len is Infinity (the default), all characters from
+# $start to the end of $text are removed. If $repl is "" (the default),
+# nothing is inserted (pure deletion).
+#
+# @param {string} text - The original string.
+# @param {number} start - The 1-based index at which to begin removal.
+# @param {number} len - Number of characters to remove (default: Infinity).
+# @param {string} repl - Replacement string to insert (default: "").
+# @returns {string} The modified string.
+#
+# @example str_splice("hello world", 6) => "hello"
+# @example str_splice("hello world", 6, 5) => "hello "
+# @example str_splice("hello world", 6, 5, "!") => "hello !"
+func str_splice(text, start, len="Infinity", repl="") {
+ return str_slice($text, 1, $start - 1) & $repl & str_slice($text, $start + $len);
+}
+
+# Returns a copy of $text with every non-overlapping occurrence of
+# $subtext replaced by $repl, scanning left to right. Overlapping
+# matches are not detected; after a match the scan resumes immediately
+# after the replaced region.
+#
+# @param {string} text - The original string.
+# @param {string} subtext - The substring to search for.
+# @param {string} repl - The replacement string.
+# @returns {string} The string with all occurrences replaced.
+#
+# @example str_replace("aabbaa", "aa", "X") => "XbbX"
+# @example str_replace("hello", "l", "r") => "herro"
+# @example str_replace("hello", "z", "r") => "hello"
+func str_replace(text, subtext, repl) {
local i = 1;
- local boundary = false;
- repeat length($text) {
- local j = 1;
- until $text[i] == ASCII_UPPERCASE[j] or j > 26 {
- j++;
- }
- if j > 26 {
- boundary = false;
- result &= $text[i];
- } else {
- if boundary == false {
- boundary = true;
- result &= ASCII_UPPERCASE[j];
- } else {
- result &= ASCII_LOWERCASE[j];
+ local result = "";
+ delete strbuf;
+ until i > length($text) {
+ add $text[i] to strbuf;
+ if contains(strbuf, $subtext) {
+ repeat length($subtext) {
+ delete strbuf["last"];
}
+ result &= strbuf & $repl;
+ delete strbuf;
}
i++;
}
- return result;
+ return result & strbuf;
}
-# Join `LIST` elements into a string, separated by `SEP` and store the result in a local
-# variable `STORE`.
-%define JOIN(LIST,SEP,STORE) \
- local STORE = ""; \
- local i = 1; \
- repeat length(LIST) { \
- STORE &= LIST[i]; \
- if i < length(LIST) { \
- STORE &= (SEP); \
- } \
- i++; \
- }
-
-# Join `LIST` by `FIELD` with `SEP` separator and store the result in a local variable
-# `STORE`.
-%define JOIN_BY_FIELD(LIST,FIELD,SEP,STORE) \
- local STORE = ""; \
- local i = 1; \
- repeat length(LIST) { \
- STORE &= LIST[i]FIELD; \
- if i < length(LIST) { \
- STORE &= (SEP); \
- } \
- i++; \
- }
-
-func truncate(text, maxlength) {
- if length($text) > $maxlength {
- return slice($text, 1, $maxlength-4) & "...";
- } else {
- return $text;
+# Returns a copy of $text with the first $n non-overlapping occurrences of
+# $subtext replaced by $repl, scanning left to right. Occurrences beyond
+# the $n-th are left unchanged. Passing $n = 0 returns $text unmodified.
+#
+# @param {string} text - The original string.
+# @param {string} subtext - The substring to search for.
+# @param {string} repl - The replacement string.
+# @param {number} n - Maximum number of replacements to perform.
+# @returns {string} The string with up to $n occurrences replaced.
+#
+# @example str_replacen("aabbaa", "aa", "X", 1) => "Xbbaa"
+# @example str_replacen("aabbaa", "aa", "X", 2) => "XbbX"
+# @example str_replacen("hello", "l", "r", 0) => "hello"
+func str_replacen(text, subtext, repl, n) {
+ local i = 1;
+ local n = 0;
+ local result = "";
+ delete strbuf;
+ until i > length($text) {
+ add $text[i] to strbuf;
+ if contains(strbuf, $subtext) {
+ if n < $n {
+ repeat length($subtext) {
+ delete strbuf["last"];
+ }
+ result &= strbuf & $repl;
+ } else {
+ result &= strbuf;
+ }
+ delete strbuf;
+ n++;
+ }
+ i++;
}
+ return result & strbuf;
}
-func casecmp(a, b) {
- if length($a) != length($b) {
- return false;
- }
+# Returns a copy of $text with only the $n-th occurrence (1-based) of
+# $subtext replaced by $repl, scanning left to right. All other
+# occurrences are left unchanged. If there are fewer than $n occurrences,
+# $text is returned unmodified.
+#
+# @param {string} text - The original string.
+# @param {string} subtext - The substring to search for.
+# @param {string} repl - The replacement string.
+# @param {number} n - The 1-based index of the occurrence to replace.
+# @returns {string} The string with the $n-th occurrence replaced.
+#
+# @example str_replacenth("aabbaa", "aa", "X", 1) => "Xbbaa"
+# @example str_replacenth("aabbaa", "aa", "X", 2) => "aabbX"
+# @example str_replacenth("hello", "l", "r", 2) => "helro"
+func str_replacenth(text, subtext, repl, n) {
local i = 1;
- repeat length($a) {
- switch_costume $a;
- local c = costume_number();
- switch_costume $b;
- if c != costume_number() {
- return false;
+ local n = 1;
+ local result = "";
+ delete strbuf;
+ until i > length($text) {
+ add $text[i] to strbuf;
+ if contains(strbuf, $subtext) {
+ if n == $n {
+ repeat length($subtext) {
+ delete strbuf["last"];
+ }
+ result &= strbuf & $repl;
+ } else {
+ result &= strbuf;
+ }
+ delete strbuf;
+ n++;
}
i++;
}
- return true;
+ return result & strbuf;
+}
+
+# Returns $text with the leading $prefix removed, if present.
+# If $text does not start with $prefix, it is returned unchanged.
+# The check is NOT case-sensitive.
+#
+# @param {string} text - The string to process.
+# @param {string} prefix - The prefix to remove.
+# @returns {string} $text without the leading $prefix, or $text unchanged.
+#
+# @example str_remove_prefix("hello world", "hello ") => "world"
+# @example str_remove_prefix("hello world", "world") => "hello world"
+# @example str_remove_prefix("hello", "") => "hello"
+func str_remove_prefix(text, prefix) {
+ if str_starts_with($text, $prefix) {
+ return str_slice($text, 1 + length($prefix));
+ }
+ return $text;
}
-func countchar(text, char) {
+# Returns $text with the trailing $suffix removed, if present.
+# If $text does not end with $suffix, it is returned unchanged.
+# The check is NOT case-sensitive.
+#
+# @param {string} text - The string to process.
+# @param {string} suffix - The suffix to remove.
+# @returns {string} $text without the trailing $suffix, or $text unchanged.
+#
+# @example str_remove_suffix("hello world", " world") => "hello"
+# @example str_remove_suffix("hello world", "hello") => "hello world"
+# @example str_remove_suffix("hello", "") => "hello"
+func str_remove_suffix(text, suffix) {
+ if str_ends_with($text, $suffix) {
+ return str_slice($text, 1, 0 - length($suffix));
+ }
+ return $text;
+}
+
+# Returns the 1-based index of the first occurrence of $subtext in $text,
+# scanning left to right using a naive O(n*m) search. Returns 0 if
+# $subtext is not found or if $subtext is longer than $text.
+#
+# @param {string} text - The string to search within.
+# @param {string} subtext - The substring to search for.
+# @returns {number} The 1-based starting index of the first match, or 0.
+#
+# @example str_find("hello world", "world") => 7
+# @example str_find("hello world", "xyz") => 0
+# @example str_find("aabaa", "aa") => 1
+func str_find(text, subtext) {
+ local n = length($text);
+ local m = length($subtext);
+ if m > n { return 0; }
+
local i = 1;
- local count = 0;
- repeat length($text) {
- if $text[i] == $char {
- count++;
+ until i > n - m + 1 {
+ if str_slice($text, i, i + m - 1) == $subtext {
+ return i;
}
i++;
}
- return count;
+ return 0;
}
-func countchars(text, chars) {
- local i = 1;
- local count = 0;
+# Returns a copy of $text centered in a string of length $width.
+# If $width is less than or equal to the length of $text, a copy of
+# $text is returned unchanged. The default fill character is a space.
+#
+# @param {string} text - The string to center.
+# @param {number} width - The total width of the resulting string.
+# @param {string} fillchar - The character to use for padding (default: " ").
+# @returns {string} The centered string.
+#
+# @example str_center("hello", 10) => " hello "
+# @example str_center("hello", 10, "-") => "--hello--"
+# @example str_center("hello", 5) => "hello"
+func str_center(text, width, fillchar=" ") {
+ if $width <= length($text) {
+ return $text;
+ }
+ local total_padding = $width - length($text);
+ local left_padding = total_padding // 2;
+ local right_padding = total_padding - left_padding;
+ delete strbuf;
+ repeat left_padding {
+ add $fillchar to strbuf;
+ }
repeat length($text) {
- if $text[i] in $chars {
+ add $text[1 + length(strbuf) - left_padding] to strbuf;
+ }
+ repeat right_padding {
+ add $fillchar to strbuf;
+ }
+ return strbuf;
+}
+
+# Returns a copy of $text left-justified in a string of length $width.
+# The string is padded on the right with $fillchar. If $width is less
+# than or equal to the length of $text, a copy of $text is returned unchanged.
+#
+# @param {string} text - The string to left-justify.
+# @param {number} width - The total width of the resulting string.
+# @param {string} fillchar - The character to use for padding (default: " ").
+# @returns {string} The left-justified string.
+#
+# @example str_ljust("hello", 10) => "hello "
+# @example str_ljust("hello", 10, "-") => "hello-----"
+# @example str_ljust("hello", 5) => "hello"
+func str_ljust(text, width, fillchar=" ") {
+ if $width <= length($text) {
+ return $text;
+ }
+ delete strbuf;
+ repeat length($text) {
+ add $text[1 + length(strbuf)] to strbuf;
+ }
+ repeat $width - length($text) {
+ add $fillchar to strbuf;
+ }
+ return strbuf;
+}
+
+# Returns a copy of $text right-justified in a string of length $width.
+# The string is padded on the left with $fillchar. If $width is less
+# than or equal to the length of $text, a copy of $text is returned unchanged.
+#
+# @param {string} text - The string to right-justify.
+# @param {number} width - The total width of the resulting string.
+# @param {string} fillchar - The character to use for padding (default: " ").
+# @returns {string} The right-justified string.
+#
+# @example str_rjust("hello", 10) => " hello"
+# @example str_rjust("hello", 10, "-") => "-----hello"
+# @example str_rjust("hello", 5) => "hello"
+func str_rjust(text, width, fillchar=" ") {
+ if $width <= length($text) {
+ return $text;
+ }
+ delete strbuf;
+ repeat $width - length($text) {
+ add $fillchar to strbuf;
+ }
+ repeat length($text) {
+ add $text[1 + length(strbuf) - ($width - length($text))] to strbuf;
+ }
+ return strbuf;
+}
+
+# Counts the number of non-overlapping occurrences of $sub in $text.
+# - returns 0 if $sub is not found
+# - returns length($text) + 1 for an empty $sub
+#
+# @param {string} text - The string to search within.
+# @param {string} sub - The substring to count.
+# @returns {number} The number of non-overlapping occurrences.
+#
+# @example str_count("this is it", "is") => 2
+# @example str_count("aaaa", "aa") => 2
+# @example str_count("banana", "an") => 2
+# @example str_count("hello", "xyz") => 0
+# @example str_count("abc", "") => 4
+func str_count(text, sub) {
+ local count = 0;
+ local i = 1;
+ local j = 0;
+ local candidate = "";
+
+ if length($sub) == 0 {
+ return length($text) + 1;
+ }
+
+ until i > length($text) - length($sub) + 1 {
+ candidate = "";
+ j = 0;
+ repeat length($sub) {
+ j++;
+ candidate &= $text[i + j - 1];
+ }
+ if candidate == $sub {
count++;
+ i += length($sub);
+ } else {
+ i++;
}
- i++;
}
return count;
}
diff --git a/test/base64.test.gs b/test/base64.test.gs
new file mode 100644
index 0000000..74a1d16
--- /dev/null
+++ b/test/base64.test.gs
@@ -0,0 +1,85 @@
+%include ../base64.gs
+
+proc test {
+ # ── Encode tests ────────────────────────────────────────────────
+
+ delete base64_buffer;
+ base64_buffer_append "";
+ expect "base64_encode('')", base64_encode(BASE64_CHARSET), to_be: "";
+
+ delete base64_buffer;
+ base64_buffer_append "f";
+ expect "base64_encode('f')", base64_encode(BASE64_CHARSET), to_be: "Zg==";
+
+ delete base64_buffer;
+ base64_buffer_append "fo";
+ expect "base64_encode('fo')", base64_encode(BASE64_CHARSET), to_be: "Zm8=";
+
+ delete base64_buffer;
+ base64_buffer_append "foo";
+ expect "base64_encode('foo')", base64_encode(BASE64_CHARSET), to_be: "Zm9v";
+
+ delete base64_buffer;
+ base64_buffer_append "foob";
+ expect "base64_encode('foob')", base64_encode(BASE64_CHARSET), to_be: "Zm9vYg==";
+
+ delete base64_buffer;
+ base64_buffer_append "fooba";
+ expect "base64_encode('fooba')", base64_encode(BASE64_CHARSET), to_be: "Zm9vYmE=";
+
+ delete base64_buffer;
+ base64_buffer_append "foobar";
+ expect "base64_encode('foobar')", base64_encode(BASE64_CHARSET), to_be: "Zm9vYmFy";
+
+ delete base64_buffer;
+ base64_buffer_append "Many hands make light work.";
+ expect "base64_encode('Many hands make light work.')", base64_encode(BASE64_CHARSET), to_be: "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu";
+
+ # ── Decode tests ────────────────────────────────────────────────
+
+ base64_build_lut BASE64_CHARSET;
+
+ delete base64_buffer;
+ base64_decode "Zg==";
+ expect "base64_decode('Zg==')", base64_buffer_to_str(), to_be: "f";
+
+ delete base64_buffer;
+ base64_decode "Zm8=";
+ expect "base64_decode('Zm8=')", base64_buffer_to_str(), to_be: "fo";
+
+ delete base64_buffer;
+ base64_decode "Zm9v";
+ expect "base64_decode('Zm9v')", base64_buffer_to_str(), to_be: "foo";
+
+ delete base64_buffer;
+ base64_decode "Zm9vYg==";
+ expect "base64_decode('Zm9vYg==')", base64_buffer_to_str(), to_be: "foob";
+
+ delete base64_buffer;
+ base64_decode "Zm9vYmE=";
+ expect "base64_decode('Zm9vYmE=')", base64_buffer_to_str(), to_be: "fooba";
+
+ delete base64_buffer;
+ base64_decode "Zm9vYmFy";
+ expect "base64_decode('Zm9vYmFy')", base64_buffer_to_str(), to_be: "foobar";
+
+ delete base64_buffer;
+ base64_decode "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu";
+ expect "base64_decode('TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu')", base64_buffer_to_str(), to_be: "Many hands make light work.";
+
+ # ── Round-trip tests ─────────────────────────────────────────────
+
+ delete base64_buffer;
+ base64_buffer_append "Hello, World!";
+ local encoded = base64_encode(BASE64_CHARSET);
+ delete base64_buffer;
+ base64_decode encoded;
+ expect "round-trip 'Hello, World!'", base64_buffer_to_str(), to_be: "Hello, World!";
+
+ delete base64_buffer;
+ base64_buffer_append "abc";
+ encoded = base64_encode(BASE64_CHARSET);
+ delete base64_buffer;
+ base64_decode encoded;
+ expect "round-trip 'abc'", base64_buffer_to_str(), to_be: "abc";
+}
diff --git a/test/bitwise.test.gs b/test/bitwise.test.gs
new file mode 100644
index 0000000..c8c66b7
--- /dev/null
+++ b/test/bitwise.test.gs
@@ -0,0 +1,86 @@
+%include ../bitwise.gs
+
+proc test {
+ # xor8 (func) — chosen so result is 0xFF (255), a good boundary check
+ expect "xor8(0xA3, 0x5C)", xor8(_(0xA3), _(0x5C)), to_be: "255";
+
+ # xor16 (func)
+ expect "xor16(0xBEEF, 0xDEAD)", xor16(_(0xBEEF), _(0xDEAD)), to_be: "24642";
+
+ # xor32 (func)
+ expect "xor32(0x12345678, 0x9ABCDEF0)", xor32(_(0x12345678), _(0x9ABCDEF0)), to_be: "2290649224";
+
+ # and8 (func)
+ expect "and8(0xE7, 0x3C)", and8(_(0xE7), _(0x3C)), to_be: "36";
+
+ # and16 (func)
+ expect "and16(0xFACE, 0xBEEF)", and16(_(0xFACE), _(0xBEEF)), to_be: "47822";
+
+ # and32 (func)
+ expect "and32(0xCAFEBABE, 0xDEADBEEF)", and32(_(0xCAFEBABE), _(0xDEADBEEF)), to_be: "3400317614";
+
+ # or8 (func)
+ expect "or8(0x81, 0x42)", or8(_(0x81), _(0x42)), to_be: "195";
+
+ # or16 (func)
+ expect "or16(0x1337, 0xC0DE)", or16(_(0x1337), _(0xC0DE)), to_be: "54271";
+
+ # or32 (func)
+ expect "or32(0xC0DE0000, 0x0000CAFE)", or32(_(0xC0DE0000), _(0x0000CAFE)), to_be: "3235826430";
+
+ # NOT4 (macro)
+ expect "NOT4(0x0)", NOT4(0x0), to_be: "15";
+ expect "NOT4(0xF)", NOT4(0xF), to_be: "0";
+ expect "NOT4(0xA)", NOT4(0xA), to_be: "5";
+ expect "NOT4(0x5)", NOT4(0x5), to_be: "10";
+
+ # not8 (func)
+ expect "not8(0x00)", not8(_(0x00)), to_be: "255";
+ expect "not8(0xFF)", not8(_(0xFF)), to_be: "0";
+ expect "not8(0xA5)", not8(_(0xA5)), to_be: "90"; # 0x5A
+ expect "not8(0xF0)", not8(_(0xF0)), to_be: "15"; # 0x0F
+
+ # not16 (func)
+ expect "not16(0x0000)", not16(_(0x0000)), to_be: "65535";
+ expect "not16(0xFFFF)", not16(_(0xFFFF)), to_be: "0";
+ expect "not16(0xA5A5)", not16(_(0xA5A5)), to_be: "23130"; # 0x5A5A
+ expect "not16(0xDEAD)", not16(_(0xDEAD)), to_be: "8530"; # 0x2152
+
+ # not32 (func)
+ expect "not32(0x00000000)", not32(_(0x00000000)), to_be: "4294967295";
+ expect "not32(0xFFFFFFFF)", not32(_(0xFFFFFFFF)), to_be: "0";
+ expect "not32(0xDEADBEEF)", not32(_(0xDEADBEEF)), to_be: "559038736"; # 0x21524110
+ expect "not32(0xA5A5A5A5)", not32(_(0xA5A5A5A5)), to_be: "1515870810"; # 0x5A5A5A5A
+
+ # ADD32 (macro)
+ expect "ADD32(1, 1)", ADD32(1, 1), to_be: "2";
+ expect "ADD32(0xFFFFFFFF, 1) wraps", ADD32(0xFFFFFFFF, 1), to_be: "0";
+ expect "ADD32(0x80000000, 0x80000000) wraps", ADD32(0x80000000, 0x80000000), to_be: "0";
+ expect "ADD32(0xDEADBEEF, 0x12345678)", ADD32(0xDEADBEEF, 0x12345678), to_be: "4041348455"; # 0xF0E21567
+
+ # add32 (func)
+ expect "add32(0, 0)", add32(_(0), _(0)), to_be: "0";
+ expect "add32(1, 1)", add32(_(1), _(1)), to_be: "2";
+ expect "add32(0xFFFFFFFF, 1) wraps", add32(_(0xFFFFFFFF), _(1)), to_be: "0";
+ expect "add32(0x80000000, 0x80000000) wraps", add32(_(0x80000000), _(0x80000000)), to_be: "0";
+ expect "add32(0xDEADBEEF, 0x12345678)", add32(_(0xDEADBEEF), _(0x12345678)), to_be: "4041348455";
+ expect "add32(0xCAFEBABE, 0xDEADBEEF)", add32(_(0xCAFEBABE), _(0xDEADBEEF)), to_be: "2846652845"; # 0xA9AC79AD
+
+ # ROL32 (macro, single step)
+ # NOTE: ROL32 has a bug — (A) > 0xFFFFFFFF is always 0, so the MSB carry
+ # is never captured. The two tests below expose it.
+ expect "ROL32(1)", ROL32(1), to_be: "2";
+ expect "ROL32(0x40000000)", ROL32(0x40000000), to_be: "2147483648"; # MSB 0 → safe
+ expect "ROL32(0x80000000) carry bug", ROL32(0x80000000), to_be: "1"; # FAILS: gives 0
+ expect "ROL32(0xDEADBEEF) carry bug", ROL32(0xDEADBEEF), to_be: "2932443615"; # 0xBD5B7DDF — FAILS: gives 0xBD5B7DDE
+
+ # rol32 (func)
+ expect "rol32(1, 0) identity", rol32(_(1), _(0)), to_be: "1";
+ expect "rol32(1, 1)", rol32(_(1), _(1)), to_be: "2";
+ expect "rol32(1, 31)", rol32(_(1), _(31)), to_be: "2147483648"; # 0x80000000
+ expect "rol32(0x12345678, 8)", rol32(_(0x12345678), _(8)), to_be: "878082066"; # 0x34567812
+ expect "rol32(1, 32) mod wraps to identity", rol32(_(1), _(32)), to_be: "1";
+ expect "rol32(0x80000000, 1) carry bug", rol32(_(0x80000000), _(1)), to_be: "1"; # FAILS: gives 0
+ expect "rol32(0xDEADBEEF, 4) carry bug", rol32(_(0xDEADBEEF), _(4)), to_be: "3940282109"; # 0xEADBEEFD — FAILS
+
+}
diff --git a/test/blank.svg b/test/blank.svg
deleted file mode 100644
index 9f67e78..0000000
--- a/test/blank.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-
diff --git a/test/getopt.test.gs b/test/getopt.test.gs
new file mode 100644
index 0000000..1fec23c
--- /dev/null
+++ b/test/getopt.test.gs
@@ -0,0 +1,125 @@
+%include ../shlex.gs
+%include ../getopt.gs
+
+proc test {
+ # ── 1. single flag ────────────────────────────────────────────────────────
+ shlex_split "-v";
+ getopt_init;
+ getopt "v";
+ expect "1. result", getopt_result, to_be: "v";
+ getopt "v";
+ expect "1. done", getopt_result, to_be: -1;
+
+ # ── 2. multiple separate flags ────────────────────────────────────────────
+ shlex_split "-a -b -c";
+ getopt_init;
+ getopt "abc";
+ expect "2. first", getopt_result, to_be: "a";
+ getopt "abc";
+ expect "2. second", getopt_result, to_be: "b";
+ getopt "abc";
+ expect "2. third", getopt_result, to_be: "c";
+ getopt "abc";
+ expect "2. done", getopt_result, to_be: -1;
+
+ # ── 3. clustered flags ────────────────────────────────────────────────────
+ shlex_split "-abc";
+ getopt_init;
+ getopt "abc";
+ expect "3. first", getopt_result, to_be: "a";
+ getopt "abc";
+ expect "3. second", getopt_result, to_be: "b";
+ getopt "abc";
+ expect "3. third", getopt_result, to_be: "c";
+ getopt "abc";
+ expect "3. done", getopt_result, to_be: -1;
+
+ # ── 4. option with argument, separate token ───────────────────────────────
+ shlex_split "-o file.txt";
+ getopt_init;
+ getopt "o:";
+ expect "4. result", getopt_result, to_be: "o";
+ expect "4. optarg", optarg, to_be: "file.txt";
+ getopt "o:";
+ expect "4. done", getopt_result, to_be: -1;
+
+ # ── 5. option with argument, joined ──────────────────────────────────────
+ shlex_split "-ofile.txt";
+ getopt_init;
+ getopt "o:";
+ expect "5. result", getopt_result, to_be: "o";
+ expect "5. optarg", optarg, to_be: "file.txt";
+ getopt "o:";
+ expect "5. done", getopt_result, to_be: -1;
+
+ # ── 6. mixed flags and option-with-arg ────────────────────────────────────
+ shlex_split "-v -o out.txt -n";
+ getopt_init;
+ getopt "vno:";
+ expect "6. v", getopt_result, to_be: "v";
+ getopt "vno:";
+ expect "6. o", getopt_result, to_be: "o";
+ expect "6. optarg", optarg, to_be: "out.txt";
+ getopt "vno:";
+ expect "6. n", getopt_result, to_be: "n";
+ getopt "vno:";
+ expect "6. done", getopt_result, to_be: -1;
+
+ # ── 7. cluster ending with option-with-arg joined ─────────────────────────
+ # -voval → -v then -o val
+ shlex_split "-voval";
+ getopt_init;
+ getopt "vo:";
+ expect "7. v", getopt_result, to_be: "v";
+ getopt "vo:";
+ expect "7. o", getopt_result, to_be: "o";
+ expect "7. optarg", optarg, to_be: "val";
+ getopt "vo:";
+ expect "7. done", getopt_result, to_be: -1;
+
+ # ── 8. -- stops option parsing ────────────────────────────────────────────
+ shlex_split "-v -- -n";
+ getopt_init;
+ getopt "vn";
+ expect "8. v", getopt_result, to_be: "v";
+ getopt "vn";
+ expect "8. done", getopt_result, to_be: -1;
+ expect "8. optind points past --", optind, to_be: 3;
+
+ # ── 9. non-option arg stops parsing ──────────────────────────────────────
+ shlex_split "-v foo -n";
+ getopt_init;
+ getopt "vn";
+ expect "9. v", getopt_result, to_be: "v";
+ getopt "vn";
+ expect "9. done", getopt_result, to_be: -1;
+ expect "9. optind", optind, to_be: 2;
+
+ # ── 10. unknown option returns ? and sets optopt ──────────────────────────
+ shlex_split "-z";
+ getopt_init;
+ getopt "v";
+ expect "10. result", getopt_result, to_be: "?";
+ expect "10. optopt", optopt, to_be: "z";
+
+ # ── 11. missing required argument returns ? ───────────────────────────────
+ shlex_split "-o";
+ getopt_init;
+ getopt "o:";
+ expect "11. result", getopt_result, to_be: "?";
+
+ # ── 12. no args at all ────────────────────────────────────────────────────
+ shlex_split "";
+ getopt_init;
+ getopt "v";
+ expect "12. done", getopt_result, to_be: -1;
+
+ # ── 13. optind lands on first non-option positional ───────────────────────
+ shlex_split "-a -b foo bar";
+ getopt_init;
+ getopt "ab";
+ getopt "ab";
+ getopt "ab";
+ expect "13. optind", optind, to_be: 3;
+ expect "13. first pos", shlex_args[optind], to_be: "foo";
+}
diff --git a/test/list.test.gs b/test/list.test.gs
new file mode 100644
index 0000000..f270d5a
--- /dev/null
+++ b/test/list.test.gs
@@ -0,0 +1,621 @@
+%include ../list.gs
+
+struct xy { x=0, y=0 }
+
+list mylist = [];
+list mylist2 = [];
+list xy mypts = [];
+list xy mypts2 = [];
+
+proc unique_mylist start=1, end=-1 {
+ LIST_UNIQUE(mylist)
+}
+
+proc unique_mypts start=1, end=-1 {
+ LIST_UNIQUE(mypts, xy, x)
+}
+
+proc test_unique_basic {
+ delete mylist;
+ add 1 to mylist;
+ add 2 to mylist;
+ add 2 to mylist;
+ add 3 to mylist;
+ add 3 to mylist;
+ add 3 to mylist;
+ unique_mylist;
+ expect "unique basic length", length(mylist), to_be: "3";
+ expect "unique basic [1]", mylist[1], to_be: "1";
+ expect "unique basic [2]", mylist[2], to_be: "2";
+ expect "unique basic [3]", mylist[3], to_be: "3";
+}
+
+proc test_unique_no_duplicates {
+ delete mylist;
+ add 1 to mylist;
+ add 2 to mylist;
+ add 3 to mylist;
+ unique_mylist;
+ expect "unique no dupes length", length(mylist), to_be: "3";
+ expect "unique no dupes [1]", mylist[1], to_be: "1";
+ expect "unique no dupes [2]", mylist[2], to_be: "2";
+ expect "unique no dupes [3]", mylist[3], to_be: "3";
+}
+
+proc test_unique_all_duplicates {
+ delete mylist;
+ add 5 to mylist;
+ add 5 to mylist;
+ add 5 to mylist;
+ unique_mylist;
+ expect "unique all dupes length", length(mylist), to_be: "1";
+ expect "unique all dupes [1]", mylist[1], to_be: "5";
+}
+
+proc test_unique_partial {
+ delete mylist;
+ add 9 to mylist;
+ add 2 to mylist;
+ add 2 to mylist;
+ add 3 to mylist;
+ add 9 to mylist;
+ unique_mylist start:2, end:4;
+ expect "unique partial [1] untouched", mylist[1], to_be: "9";
+ expect "unique partial length", length(mylist), to_be: "4";
+ expect "unique partial [2]", mylist[2], to_be: "2";
+ expect "unique partial [3]", mylist[3], to_be: "3";
+ expect "unique partial [4] untouched", mylist[4], to_be: "9";
+}
+
+proc test_unique_negative_indices {
+ delete mylist;
+ add 9 to mylist;
+ add 2 to mylist;
+ add 2 to mylist;
+ add 3 to mylist;
+ add 9 to mylist;
+ unique_mylist start:2, end:-2;
+ expect "unique neg [1] untouched", mylist[1], to_be: "9";
+ expect "unique neg length", length(mylist), to_be: "4";
+ expect "unique neg [2]", mylist[2], to_be: "2";
+ expect "unique neg [3]", mylist[3], to_be: "3";
+ expect "unique neg [4] untouched", mylist[4], to_be: "9";
+}
+
+proc test_unique_key {
+ delete mypts;
+ local xy p = xy{};
+ p.x = 1; p.y = 10; add p to mypts;
+ p.x = 2; p.y = 20; add p to mypts;
+ p.x = 2; p.y = 99; add p to mypts;
+ p.x = 3; p.y = 30; add p to mypts;
+ unique_mypts;
+ expect "unique key length", length(mypts), to_be: "3";
+ expect "unique key [1].x", mypts[1].x, to_be: "1";
+ expect "unique key [2].x", mypts[2].x, to_be: "2";
+ expect "unique key [2].y kept first", mypts[2].y, to_be: "20";
+ expect "unique key [3].x", mypts[3].x, to_be: "3";
+}
+
+proc sort_mylist start=1, end=-1 {
+ LIST_SORT(mylist)
+}
+
+proc sort_mypts start=1, end=-1 {
+ LIST_SORT(mypts, xy, x)
+}
+
+proc test_sort_basic {
+ delete mylist;
+ add 3 to mylist;
+ add 1 to mylist;
+ add 4 to mylist;
+ add 2 to mylist;
+ sort_mylist;
+ expect "sort basic [1]", mylist[1], to_be: "1";
+ expect "sort basic [2]", mylist[2], to_be: "2";
+ expect "sort basic [3]", mylist[3], to_be: "3";
+ expect "sort basic [4]", mylist[4], to_be: "4";
+}
+
+proc test_sort_partial {
+ delete mylist;
+ add 9 to mylist;
+ add 3 to mylist;
+ add 1 to mylist;
+ add 2 to mylist;
+ add 9 to mylist;
+ sort_mylist start:2, end:4;
+ expect "sort partial [1] untouched", mylist[1], to_be: "9";
+ expect "sort partial [2]", mylist[2], to_be: "1";
+ expect "sort partial [3]", mylist[3], to_be: "2";
+ expect "sort partial [4]", mylist[4], to_be: "3";
+ expect "sort partial [5] untouched", mylist[5], to_be: "9";
+}
+
+proc test_sort_negative_indices {
+ delete mylist;
+ add 9 to mylist;
+ add 4 to mylist;
+ add 2 to mylist;
+ add 3 to mylist;
+ add 9 to mylist;
+ sort_mylist start:2, end:-2;
+ expect "sort neg [1] untouched", mylist[1], to_be: "9";
+ expect "sort neg [2]", mylist[2], to_be: "2";
+ expect "sort neg [3]", mylist[3], to_be: "3";
+ expect "sort neg [4]", mylist[4], to_be: "4";
+ expect "sort neg [5] untouched", mylist[5], to_be: "9";
+}
+
+proc test_sort_key {
+ delete mypts;
+ local xy p = xy{};
+ p.x = 5; p.y = 0; add p to mypts;
+ p.x = 1; p.y = 0; add p to mypts;
+ p.x = 3; p.y = 0; add p to mypts;
+ sort_mypts;
+ expect "sort key [1].x", mypts[1].x, to_be: "1";
+ expect "sort key [2].x", mypts[2].x, to_be: "3";
+ expect "sort key [3].x", mypts[3].x, to_be: "5";
+}
+
+proc test_sort_already_sorted {
+ delete mylist;
+ add 1 to mylist;
+ add 2 to mylist;
+ add 3 to mylist;
+ sort_mylist;
+ expect "sort already sorted [1]", mylist[1], to_be: "1";
+ expect "sort already sorted [2]", mylist[2], to_be: "2";
+ expect "sort already sorted [3]", mylist[3], to_be: "3";
+}
+
+proc test_sort_single_element {
+ delete mylist;
+ add 42 to mylist;
+ sort_mylist;
+ expect "sort single element", mylist[1], to_be: "42";
+}
+
+# ── LIST_JOIN ────────────────────────────────────────────────────────────────
+
+func join_mylist(start=1, end=-1, sep=",") {
+ LIST_JOIN(mylist)
+}
+
+func join_mypts(start=1, end=-1, sep=",") {
+ LIST_JOIN(mypts, x)
+}
+
+proc test_join_basic {
+ delete mylist;
+ add "a" to mylist;
+ add "b" to mylist;
+ add "c" to mylist;
+ expect "join basic", join_mylist(), to_be: "a,b,c";
+}
+
+proc test_join_sep {
+ delete mylist;
+ add "x" to mylist;
+ add "y" to mylist;
+ add "z" to mylist;
+ expect "join sep", join_mylist(sep:" | "), to_be: "x | y | z";
+}
+
+proc test_join_partial {
+ delete mylist;
+ add "a" to mylist;
+ add "b" to mylist;
+ add "c" to mylist;
+ add "d" to mylist;
+ expect "join partial", join_mylist(start:2, end:3), to_be: "b,c";
+}
+
+proc test_join_negative_indices {
+ delete mylist;
+ add "a" to mylist;
+ add "b" to mylist;
+ add "c" to mylist;
+ add "d" to mylist;
+ expect "join neg indices", join_mylist(start:2, end:-2), to_be: "b,c";
+}
+
+proc test_join_single {
+ delete mylist;
+ add "only" to mylist;
+ expect "join single", join_mylist(), to_be: "only";
+}
+
+proc test_join_key {
+ delete mypts;
+ local xy p = xy{};
+ p.x = 1; p.y = 0; add p to mypts;
+ p.x = 2; p.y = 0; add p to mypts;
+ p.x = 3; p.y = 0; add p to mypts;
+ expect "join key", join_mypts(), to_be: "1,2,3";
+}
+
+# ── LIST_SUM ─────────────────────────────────────────────────────────────────
+
+func sum_mylist(start=1, end=-1) {
+ LIST_SUM(mylist)
+}
+
+func sum_mypts(start=1, end=-1) {
+ LIST_SUM(mypts, x)
+}
+
+proc test_sum_basic {
+ delete mylist;
+ add 1 to mylist;
+ add 2 to mylist;
+ add 3 to mylist;
+ add 4 to mylist;
+ expect "sum basic", sum_mylist(), to_be: "10";
+}
+
+proc test_sum_partial {
+ delete mylist;
+ add 1 to mylist;
+ add 2 to mylist;
+ add 3 to mylist;
+ add 4 to mylist;
+ expect "sum partial", sum_mylist(start:2, end:3), to_be: "5";
+}
+
+proc test_sum_negative_indices {
+ delete mylist;
+ add 1 to mylist;
+ add 2 to mylist;
+ add 3 to mylist;
+ add 4 to mylist;
+ expect "sum neg indices", sum_mylist(start:2, end:-2), to_be: "5";
+}
+
+proc test_sum_key {
+ delete mypts;
+ local xy p = xy{};
+ p.x = 10; p.y = 0; add p to mypts;
+ p.x = 20; p.y = 0; add p to mypts;
+ p.x = 30; p.y = 0; add p to mypts;
+ expect "sum key", sum_mypts(), to_be: "60";
+}
+
+# ── LIST_MIN ─────────────────────────────────────────────────────────────────
+
+func min_mylist(start=1, end=-1) {
+ LIST_MIN(mylist)
+}
+
+func min_mypts(start=1, end=-1) {
+ LIST_MIN(mypts, x)
+}
+
+proc test_min_basic {
+ delete mylist;
+ add 3 to mylist;
+ add 1 to mylist;
+ add 4 to mylist;
+ add 2 to mylist;
+ expect "min basic", min_mylist(), to_be: "1";
+}
+
+proc test_min_partial {
+ delete mylist;
+ add 1 to mylist;
+ add 5 to mylist;
+ add 3 to mylist;
+ add 1 to mylist;
+ expect "min partial", min_mylist(start:2, end:3), to_be: "3";
+}
+
+proc test_min_negative_indices {
+ delete mylist;
+ add 1 to mylist;
+ add 5 to mylist;
+ add 3 to mylist;
+ add 1 to mylist;
+ expect "min neg indices", min_mylist(start:2, end:-2), to_be: "3";
+}
+
+proc test_min_key {
+ delete mypts;
+ local xy p = xy{};
+ p.x = 7; p.y = 0; add p to mypts;
+ p.x = 2; p.y = 0; add p to mypts;
+ p.x = 5; p.y = 0; add p to mypts;
+ expect "min key", min_mypts(), to_be: "2";
+}
+
+# ── LIST_MAX ─────────────────────────────────────────────────────────────────
+
+func max_mylist(start=1, end=-1) {
+ LIST_MAX(mylist)
+}
+
+func max_mypts(start=1, end=-1) {
+ LIST_MAX(mypts, x)
+}
+
+proc test_max_basic {
+ delete mylist;
+ add 3 to mylist;
+ add 1 to mylist;
+ add 4 to mylist;
+ add 2 to mylist;
+ expect "max basic", max_mylist(), to_be: "4";
+}
+
+proc test_max_partial {
+ delete mylist;
+ add 9 to mylist;
+ add 2 to mylist;
+ add 5 to mylist;
+ add 9 to mylist;
+ expect "max partial", max_mylist(start:2, end:3), to_be: "5";
+}
+
+proc test_max_negative_indices {
+ delete mylist;
+ add 9 to mylist;
+ add 2 to mylist;
+ add 5 to mylist;
+ add 9 to mylist;
+ expect "max neg indices", max_mylist(start:2, end:-2), to_be: "5";
+}
+
+proc test_max_key {
+ delete mypts;
+ local xy p = xy{};
+ p.x = 7; p.y = 0; add p to mypts;
+ p.x = 2; p.y = 0; add p to mypts;
+ p.x = 5; p.y = 0; add p to mypts;
+ expect "max key", max_mypts(), to_be: "7";
+}
+
+# ── LIST_REVERSE ─────────────────────────────────────────────────────────────
+
+proc reverse_mylist start=1, end=-1 {
+ LIST_REVERSE(mylist)
+}
+
+proc reverse_mypts start=1, end=-1 {
+ LIST_REVERSE(xy, mypts)
+}
+
+proc test_reverse_basic {
+ delete mylist;
+ add 1 to mylist;
+ add 2 to mylist;
+ add 3 to mylist;
+ add 4 to mylist;
+ reverse_mylist;
+ expect "reverse basic [1]", mylist[1], to_be: "4";
+ expect "reverse basic [2]", mylist[2], to_be: "3";
+ expect "reverse basic [3]", mylist[3], to_be: "2";
+ expect "reverse basic [4]", mylist[4], to_be: "1";
+}
+
+proc test_reverse_partial {
+ delete mylist;
+ add 1 to mylist;
+ add 2 to mylist;
+ add 3 to mylist;
+ add 4 to mylist;
+ add 5 to mylist;
+ reverse_mylist start:2, end:4;
+ expect "reverse partial [1] untouched", mylist[1], to_be: "1";
+ expect "reverse partial [2]", mylist[2], to_be: "4";
+ expect "reverse partial [3]", mylist[3], to_be: "3";
+ expect "reverse partial [4]", mylist[4], to_be: "2";
+ expect "reverse partial [5] untouched", mylist[5], to_be: "5";
+}
+
+proc test_reverse_negative_indices {
+ delete mylist;
+ add 1 to mylist;
+ add 2 to mylist;
+ add 3 to mylist;
+ add 4 to mylist;
+ add 5 to mylist;
+ reverse_mylist start:2, end:-2;
+ expect "reverse neg [1] untouched", mylist[1], to_be: "1";
+ expect "reverse neg [2]", mylist[2], to_be: "4";
+ expect "reverse neg [3]", mylist[3], to_be: "3";
+ expect "reverse neg [4]", mylist[4], to_be: "2";
+ expect "reverse neg [5] untouched", mylist[5], to_be: "5";
+}
+
+proc test_reverse_single {
+ delete mylist;
+ add 42 to mylist;
+ reverse_mylist;
+ expect "reverse single", mylist[1], to_be: "42";
+}
+
+proc test_reverse_typed {
+ delete mypts;
+ local xy p = xy{};
+ p.x = 1; p.y = 10; add p to mypts;
+ p.x = 2; p.y = 20; add p to mypts;
+ p.x = 3; p.y = 30; add p to mypts;
+ reverse_mypts;
+ expect "reverse typed [1].x", mypts[1].x, to_be: "3";
+ expect "reverse typed [2].x", mypts[2].x, to_be: "2";
+ expect "reverse typed [3].x", mypts[3].x, to_be: "1";
+ expect "reverse typed [1].y", mypts[1].y, to_be: "30";
+}
+
+# ── LIST_COPY ────────────────────────────────────────────────────────────────
+
+proc copy_mylist_to_mylist2 start=1, end=-1 {
+ LIST_COPY(mylist, mylist2)
+}
+
+proc test_copy_basic {
+ delete mylist;
+ delete mylist2;
+ add 10 to mylist;
+ add 20 to mylist;
+ add 30 to mylist;
+ copy_mylist_to_mylist2;
+ expect "copy basic length", length(mylist2), to_be: "3";
+ expect "copy basic [1]", mylist2[1], to_be: "10";
+ expect "copy basic [2]", mylist2[2], to_be: "20";
+ expect "copy basic [3]", mylist2[3], to_be: "30";
+}
+
+proc test_copy_partial {
+ delete mylist;
+ delete mylist2;
+ add 10 to mylist;
+ add 20 to mylist;
+ add 30 to mylist;
+ add 40 to mylist;
+ copy_mylist_to_mylist2 start:2, end:3;
+ expect "copy partial length", length(mylist2), to_be: "2";
+ expect "copy partial [1]", mylist2[1], to_be: "20";
+ expect "copy partial [2]", mylist2[2], to_be: "30";
+}
+
+proc test_copy_negative_indices {
+ delete mylist;
+ delete mylist2;
+ add 10 to mylist;
+ add 20 to mylist;
+ add 30 to mylist;
+ add 40 to mylist;
+ copy_mylist_to_mylist2 start:2, end:-2;
+ expect "copy neg length", length(mylist2), to_be: "2";
+ expect "copy neg [1]", mylist2[1], to_be: "20";
+ expect "copy neg [2]", mylist2[2], to_be: "30";
+}
+
+proc test_copy_appends {
+ delete mylist;
+ delete mylist2;
+ add 1 to mylist;
+ add 2 to mylist;
+ add 99 to mylist2;
+ copy_mylist_to_mylist2;
+ expect "copy appends length", length(mylist2), to_be: "3";
+ expect "copy appends [1]", mylist2[1], to_be: "99";
+ expect "copy appends [2]", mylist2[2], to_be: "1";
+ expect "copy appends [3]", mylist2[3], to_be: "2";
+}
+
+# ── LIST_EXTEND ──────────────────────────────────────────────────────────────
+
+proc extend_mylist_to_mylist2 start=1, end=-1 {
+ LIST_EXTEND(mylist, mylist2)
+}
+
+proc test_extend_basic {
+ delete mylist;
+ delete mylist2;
+ add 1 to mylist;
+ add 2 to mylist;
+ add 3 to mylist;
+ extend_mylist_to_mylist2;
+ expect "extend basic length", length(mylist2), to_be: "3";
+ expect "extend basic [1]", mylist2[1], to_be: "1";
+ expect "extend basic [2]", mylist2[2], to_be: "2";
+ expect "extend basic [3]", mylist2[3], to_be: "3";
+}
+
+proc test_extend_partial {
+ delete mylist;
+ delete mylist2;
+ add 10 to mylist;
+ add 20 to mylist;
+ add 30 to mylist;
+ add 40 to mylist;
+ extend_mylist_to_mylist2 start:2, end:3;
+ expect "extend partial length", length(mylist2), to_be: "2";
+ expect "extend partial [1]", mylist2[1], to_be: "20";
+ expect "extend partial [2]", mylist2[2], to_be: "30";
+}
+
+proc test_extend_negative_indices {
+ delete mylist;
+ delete mylist2;
+ add 10 to mylist;
+ add 20 to mylist;
+ add 30 to mylist;
+ add 40 to mylist;
+ extend_mylist_to_mylist2 start:2, end:-2;
+ expect "extend neg length", length(mylist2), to_be: "2";
+ expect "extend neg [1]", mylist2[1], to_be: "20";
+ expect "extend neg [2]", mylist2[2], to_be: "30";
+}
+
+proc test_extend_appends {
+ delete mylist;
+ delete mylist2;
+ add 7 to mylist;
+ add 8 to mylist;
+ add 99 to mylist2;
+ extend_mylist_to_mylist2;
+ expect "extend appends length", length(mylist2), to_be: "3";
+ expect "extend appends [1]", mylist2[1], to_be: "99";
+ expect "extend appends [2]", mylist2[2], to_be: "7";
+ expect "extend appends [3]", mylist2[3], to_be: "8";
+}
+
+# ── RUN ALL ──────────────────────────────────────────────────────────────────
+
+proc test {
+ test_sort_basic;
+ test_sort_partial;
+ test_sort_negative_indices;
+ test_sort_key;
+ test_sort_already_sorted;
+ test_sort_single_element;
+
+ test_join_basic;
+ test_join_sep;
+ test_join_partial;
+ test_join_negative_indices;
+ test_join_single;
+ test_join_key;
+
+ test_sum_basic;
+ test_sum_partial;
+ test_sum_negative_indices;
+ test_sum_key;
+
+ test_min_basic;
+ test_min_partial;
+ test_min_negative_indices;
+ test_min_key;
+
+ test_max_basic;
+ test_max_partial;
+ test_max_negative_indices;
+ test_max_key;
+
+ test_reverse_basic;
+ test_reverse_partial;
+ test_reverse_negative_indices;
+ test_reverse_single;
+ test_reverse_typed;
+
+ test_copy_basic;
+ test_copy_partial;
+ test_copy_negative_indices;
+ test_copy_appends;
+
+ test_extend_basic;
+ test_extend_partial;
+ test_extend_negative_indices;
+ test_extend_appends;
+
+ test_unique_basic;
+ test_unique_no_duplicates;
+ test_unique_all_duplicates;
+ test_unique_partial;
+ test_unique_negative_indices;
+ test_unique_key;
+}
diff --git a/test/math.test.gs b/test/math.test.gs
new file mode 100644
index 0000000..c0765bf
--- /dev/null
+++ b/test/math.test.gs
@@ -0,0 +1,145 @@
+%include ../math.gs
+
+proc test {
+ expect "PI", PI, to_be: "3.141592653589793";
+ expect "E", E, to_be: "2.718281828459045";
+
+ # MIN / MAX — boundary inversion, negatives, equality
+ expect "MIN(-1, 1)", MIN(_(-1), _(1)), to_be: "-1";
+ expect "MIN(-2, -1)", MIN(_(-2), _(-1)), to_be: "-2";
+ expect "MIN(1, 1)", MIN(_(1), _(1)), to_be: "1";
+ expect "MAX(-1, 1)", MAX(_(-1), _(1)), to_be: "1";
+ expect "MAX(-2, -1)", MAX(_(-2), _(-1)), to_be: "-1";
+ expect "MAX(1, 1)", MAX(_(1), _(1)), to_be: "1";
+
+ # RGB / RGBA — black, white, primaries, alpha boundary
+ expect "RGB(0, 0, 0)", RGB(_(0), _(0), _(0)), to_be: "0";
+ expect "RGB(255, 255, 255)", RGB(_(255), _(255), _(255)), to_be: "16777215";
+ expect "RGB(255, 0, 0)", RGB(_(255), _(0), _(0)), to_be: "16711680";
+ expect "RGB(0, 255, 0)", RGB(_(0), _(255), _(0)), to_be: "65280";
+ expect "RGB(0, 0, 255)", RGB(_(0), _(0), _(255)), to_be: "255";
+ expect "RGBA(0, 0, 0, 0)", RGBA(_(0), _(0), _(0), _(0)), to_be: "0";
+ expect "RGBA(255, 255, 255, 255)", RGBA(_(255), _(255), _(255), _(255)), to_be: "4294967295";
+ expect "RGBA(0, 0, 0, 255)", RGBA(_(0), _(0), _(0), _(255)), to_be: "4278190080";
+ expect "RGBA(255, 255, 255, 0)", RGBA(_(255), _(255), _(255), _(0)), to_be: "16777215";
+ expect "RGBA(1, 2, 3, 4)", RGBA(_(1), _(2), _(3), _(4)), to_be: "67305987";
+
+ # HEX / BIN / OCT — zero, single digit, multi-byte
+ expect "HEX('0')", HEX(_("0")), to_be: "0";
+ expect "HEX('FF')", HEX(_("FF")), to_be: "255";
+ expect "HEX('FF0000')", HEX(_("FF0000")), to_be: "16711680";
+ expect "BIN('0')", BIN(_("0")), to_be: "0";
+ expect "BIN('1')", BIN(_("1")), to_be: "1";
+ expect "BIN('10')", BIN(_("10")), to_be: "2";
+ expect "BIN('11111111')", BIN(_("11111111")), to_be: "255";
+ expect "OCT('0')", OCT(_("0")), to_be: "0";
+ expect "OCT('7')", OCT(_("7")), to_be: "7";
+ expect "OCT('10')", OCT(_("10")), to_be: "8";
+ expect "OCT('377')", OCT(_("377")), to_be: "255";
+
+ # SIGN — positive, zero, negative, fractional, infinity
+ expect "SIGN(1)", SIGN(_(1)), to_be: "1";
+ expect "SIGN(0)", SIGN(_(0)), to_be: "0";
+ expect "SIGN(-1)", SIGN(_(-1)), to_be: "-1";
+ expect "SIGN(0.001)", SIGN(_(0.001)), to_be: "1";
+ expect "SIGN(Infinity)", SIGN(_("Infinity")), to_be: "1";
+
+ # Hyperbolic trig — zero, identity, symmetry
+ expect "ACOSH(1)", ACOSH(_(1)), to_be: "0";
+ expect "ACOSH(2)", ACOSH(_(2)), to_be: "1.3169578969248166";
+ expect "ASINH(0)", ASINH(_(0)), to_be: "0";
+ expect "ASINH(1)", ASINH(_(1)), to_be: "0.8813735870195429";
+ expect "ASINH(-1)", ASINH(_(-1)), to_be: "-0.8813735870195428";
+ expect "ATANH(0)", ATANH(_(0)), to_be: "0";
+ expect "ATANH(0.5)", ATANH(_(0.5)), to_be: "0.5493061443340548";
+ expect "ATANH(-0.5)",ATANH(_(-0.5)),to_be: "-0.5493061443340548";
+ expect "ATANH(0.99)",ATANH(_(0.99)),to_be: "2.6466524123622457";
+ expect "COSH(0)", COSH(_(0)), to_be: "1";
+ expect "COSH(1)", COSH(_(1)), to_be: "1.5430806348152437";
+ expect "COSH(-1)", COSH(_(-1)), to_be: "1.5430806348152437"; # even function
+ expect "SINH(0)", SINH(_(0)), to_be: "0";
+ expect "SINH(1)", SINH(_(1)), to_be: "1.1752011936438014";
+ expect "SINH(-1)", SINH(_(-1)), to_be: "-1.1752011936438014"; # odd function
+ expect "TANH(0)", TANH(_(0)), to_be: "0";
+ expect "TANH(1)", TANH(_(1)), to_be: "0.7615941559557649";
+ expect "TANH(-1)", TANH(_(-1)), to_be: "-0.7615941559557649";
+ expect "TANH(10)", TANH(_(10)), to_be: "0.9999999958776927"; # near-1 saturation
+
+ # MAG / DIST — zero, axis-aligned, Pythagorean triple, negatives
+ expect "MAG(0, 0)", MAG(_(0), _(0)), to_be: "0";
+ expect "MAG(3, 4)", MAG(_(3), _(4)), to_be: "5";
+ expect "MAG(-3, -4)", MAG(_(-3), _(-4)), to_be: "5";
+ expect "DIST(0, 0, 0, 0)", DIST(_(0), _(0), _(0), _(0)), to_be: "0";
+ expect "DIST(0, 0, 3, 4)", DIST(_(0), _(0), _(3), _(4)), to_be: "5";
+ expect "DIST(-1, -1, 2, 3)", DIST(_(-1), _(-1), _(2), _(3)), to_be: "5";
+ expect "DIST(2, 3, 2, 7)", DIST(_(2), _(3), _(2), _(7)), to_be: "4"; # vertical
+
+ # RAD / DEG — zero, full circle, inverse relationship
+ expect "RAD(0)", RAD(_(0)), to_be: "0";
+ expect "RAD(180)", RAD(_(180)), to_be: "3.141592653589793";
+ expect "RAD(360)", RAD(_(360)), to_be: "6.283185307179586";
+ expect "RAD(-90)", RAD(_(-90)), to_be: "-1.5707963267948966";
+ expect "DEG(0)", DEG(_(0)), to_be: "0";
+ expect "DEG(PI)", DEG(_(PI)), to_be: "180";
+ expect "DEG(2*PI)", DEG(_(2*PI)), to_be: "360";
+ expect "DEG(-PI/2)", DEG(_(-PI/2)),to_be: "-90";
+
+ # POW / ROOT — identity, zero exp, fractional, inverse pair
+ expect "POW(2, 0)", POW(_(2), _(0)), to_be: "1";
+ expect "POW(2, 10)", POW(_(2), _(10)), to_be: "1024";
+ expect "POW(4, 0.5)", POW(_(4), _(0.5)), to_be: "2";
+ expect "POW(1, 100)", POW(_(1), _(100)), to_be: "1";
+ expect "ROOT(4, 2)", ROOT(_(4), _(2)), to_be: "2";
+ expect "ROOT(8, 3)", ROOT(_(8), _(3)), to_be: "2";
+ expect "ROOT(1, 5)", ROOT(_(1), _(5)), to_be: "1";
+
+ # LOG — log(1)=0, log(base)=1, powers
+ expect "LOG(1, 10)", LOG(_(1), _(10)), to_be: "0";
+ expect "LOG(10, 10)", LOG(_(10), _(10)), to_be: "1";
+ expect "LOG(1000, 10)", LOG(_(1000), _(10)), to_be: "2.9999999999999996";
+ expect "LOG(E, E)", LOG(_(E), _(E)), to_be: "1";
+ expect "LOG(1024, 2)", LOG(_(1024), _(2)), to_be: "10";
+
+ # LERP — endpoints, midpoint, negative range
+ expect "LERP(0, 0, 10)", LERP(_(0), _(0), _(10)), to_be: "0";
+ expect "LERP(1, 0, 10)", LERP(_(1), _(0), _(10)), to_be: "10";
+ expect "LERP(0.5, 0, 10)", LERP(_(0.5), _(0), _(10)), to_be: "5";
+ expect "LERP(0.5, -10, 10)",LERP(_(0.5), _(-10), _(10)),to_be: "0";
+
+ # INVLERP — inverse of LERP, endpoints, midpoint
+ expect "INVLERP(0, 0, 10)", INVLERP(_(0), _(0), _(10)), to_be: "0";
+ expect "INVLERP(10, 0, 10)", INVLERP(_(10), _(0), _(10)), to_be: "1";
+ expect "INVLERP(5, 0, 10)", INVLERP(_(5), _(0), _(10)), to_be: "0.5";
+ expect "INVLERP(0, -10, 10)",INVLERP(_(0), _(-10), _(10)),to_be: "0.5";
+
+ # REMAP — endpoint preservation, midpoint, range flip
+ expect "REMAP(0, 0, 1, 0, 100)", REMAP(_(0), _(0), _(1), _(0), _(100)), to_be: "0";
+ expect "REMAP(1, 0, 1, 0, 100)", REMAP(_(1), _(0), _(1), _(0), _(100)), to_be: "100";
+ expect "REMAP(0.5, 0, 1, 0, 100)", REMAP(_(0.5), _(0), _(1), _(0), _(100)), to_be: "50";
+ expect "REMAP(5, 0, 10, -1, 1)", REMAP(_(5), _(0), _(10), _(-1), _(1)), to_be: "0";
+
+ # CLAMP — within, below, above, boundary exact
+ expect "CLAMP(5, 0, 10)", CLAMP(_(5), _(0), _(10)), to_be: "5";
+ expect "CLAMP(-5, 0, 10)", CLAMP(_(-5), _(0), _(10)), to_be: "0";
+ expect "CLAMP(15, 0, 10)", CLAMP(_(15), _(0), _(10)), to_be: "10";
+ expect "CLAMP(0, 0, 10)", CLAMP(_(0), _(0), _(10)), to_be: "0"; # lower boundary
+ expect "CLAMP(10, 0, 10)", CLAMP(_(10), _(0), _(10)), to_be: "10"; # upper boundary
+
+ # POSITIVE_CLAMP / NEGATIVE_CLAMP — zero crossing, fractional
+ expect "POSITIVE_CLAMP(5)", POSITIVE_CLAMP(_(5)), to_be: "5";
+ expect "POSITIVE_CLAMP(-5)", POSITIVE_CLAMP(_(-5)), to_be: "0";
+ expect "POSITIVE_CLAMP(0)", POSITIVE_CLAMP(_(0)), to_be: "0";
+ expect "POSITIVE_CLAMP(-0.001)",POSITIVE_CLAMP(_(-0.001)),to_be: "0";
+ expect "NEGATIVE_CLAMP(-5)", NEGATIVE_CLAMP(_(-5)), to_be: "-5";
+ expect "NEGATIVE_CLAMP(5)", NEGATIVE_CLAMP(_(5)), to_be: "0";
+ expect "NEGATIVE_CLAMP(0)", NEGATIVE_CLAMP(_(0)), to_be: "0";
+ expect "NEGATIVE_CLAMP(0.001)",NEGATIVE_CLAMP(_(0.001)),to_be: "0";
+
+ # APPROX — equal, within epsilon, just outside, negative span
+ expect "APPROX(1, 1, 0.0001)", APPROX(_(1), _(1), _(0.0001)), to_be: "1";
+ expect "APPROX(1, 1.00001, 0.0001)", APPROX(_(1), _(1.00001), _(0.0001)), to_be: "1";
+ expect "APPROX(1, 1.001, 0.0001)", APPROX(_(1), _(1.001), _(0.0001)), to_be: "0";
+ expect "APPROX(0, 1, 1)", APPROX(_(0), _(1), _(1)), to_be: "0"; # exactly at boundary
+ expect "APPROX(-1, 1, 3)", APPROX(_(-1), _(1), _(3)), to_be: "1";
+ expect "APPROX(-1, 1, 1)", APPROX(_(-1), _(1), _(1)), to_be: "0";
+}
diff --git a/test/md5.test.gs b/test/md5.test.gs
new file mode 100644
index 0000000..929b4aa
--- /dev/null
+++ b/test/md5.test.gs
@@ -0,0 +1,10 @@
+%include std/bitwise.gs
+%include std/bytes.gs
+%include std/md5.gs
+
+proc test {
+ delete md5_input;
+ md5_input_encode_ascii "aspizu";
+ md5;
+ expect "md5('aspizu')", md5_output_decode_hex(), to_be: "3E82F1CFE9773B2887D827976C75E6E7";
+}
diff --git a/test/sha256.test.gs b/test/sha256.test.gs
new file mode 100644
index 0000000..0361f01
--- /dev/null
+++ b/test/sha256.test.gs
@@ -0,0 +1,10 @@
+%include std/bitwise.gs
+%include std/bytes.gs
+%include std/sha256.gs
+
+proc test {
+ delete sha256_input;
+ sha256_input_encode_ascii "aspizu";
+ sha256;
+ expect "sha256('aspizu')", sha256_output_decode_hex(), to_be: "D9A064F15C829582610A8C0A7C3C06A8F01B9DF383D78544451AAC3EBB57E0E3";
+}
diff --git a/test/shlex.test.gs b/test/shlex.test.gs
new file mode 100644
index 0000000..8c1b7ca
--- /dev/null
+++ b/test/shlex.test.gs
@@ -0,0 +1,64 @@
+%include ../shlex.gs
+
+proc test {
+ # 1. basic whitespace splitting
+ shlex_split "one two three";
+ expect "1. shlex_args[1]", shlex_args[1], to_be: "one";
+ expect "1. shlex_args[2]", shlex_args[2], to_be: "two";
+ expect "1. shlex_args[3]", shlex_args[3], to_be: "three";
+
+ # 2. single quotes preserve spaces
+ shlex_split "'hello world' foo";
+ expect "2. shlex_args[1]", shlex_args[1], to_be: "hello world";
+ expect "2. shlex_args[2]", shlex_args[2], to_be: "foo";
+
+ # 3. double quotes preserve spaces
+ shlex_split "\"hello world\" foo";
+ expect "3. shlex_args[1]", shlex_args[1], to_be: "hello world";
+ expect "3. shlex_args[2]", shlex_args[2], to_be: "foo";
+
+ # 4. backslash escapes a space outside quotes
+ shlex_split "hello\\ world foo";
+ expect "4. shlex_args[1]", shlex_args[1], to_be: "hello world";
+ expect "4. shlex_args[2]", shlex_args[2], to_be: "foo";
+
+ # 5. adjacent quoting concatenates into one token
+ shlex_split "foo\"bar\"'baz'";
+ expect "5. shlex_args[1]", shlex_args[1], to_be: "foobarbaz";
+ expect "5. length", length shlex_args, to_be: 1;
+
+ # 6. backslash escape inside double quotes
+ shlex_split "\"say \\\"hi\\\"\"";
+ expect "6. shlex_args[1]", shlex_args[1], to_be: "say \"hi\"";
+
+ # 7. single quotes treat backslash as literal
+ shlex_split "'back\\slash'";
+ expect "7. shlex_args[1]", shlex_args[1], to_be: "back\\slash";
+
+ # 8. multiple spaces between tokens are collapsed
+ shlex_split "a b c";
+ expect "8. shlex_args[1]", shlex_args[1], to_be: "a";
+ expect "8. shlex_args[2]", shlex_args[2], to_be: "b";
+ expect "8. shlex_args[3]", shlex_args[3], to_be: "c";
+ expect "8. length", length shlex_args, to_be: 3;
+
+ # 9. empty single-quoted string produces an empty token
+ shlex_split "a '' b";
+ expect "9. shlex_args[1]", shlex_args[1], to_be: "a";
+ expect "9. shlex_args[2]", shlex_args[2], to_be: "";
+ expect "9. shlex_args[3]", shlex_args[3], to_be: "b";
+
+ # 10. flag-style token with = and quoted value
+ shlex_split "--msg='fix bug'";
+ expect "10. shlex_args[1]", shlex_args[1], to_be: "--msg=fix bug";
+ expect "10. length", length shlex_args, to_be: 1;
+
+ # 11. only whitespace produces no tokens
+ shlex_split " ";
+ expect "11. length", length shlex_args, to_be: 0;
+
+ # 12. single token, no spaces
+ shlex_split "hello";
+ expect "12. shlex_args[1]", shlex_args[1], to_be: "hello";
+ expect "12. length", length shlex_args, to_be: 1;
+}
diff --git a/test/stage.gs b/test/stage.gs
deleted file mode 100644
index f5f4981..0000000
--- a/test/stage.gs
+++ /dev/null
@@ -1 +0,0 @@
-costumes "blank.svg";
diff --git a/test/string.test.gs b/test/string.test.gs
new file mode 100644
index 0000000..ac5d9a8
--- /dev/null
+++ b/test/string.test.gs
@@ -0,0 +1,449 @@
+%include ../string.gs
+
+proc test {
+
+ # =========================================================================
+ # str_slice
+ # =========================================================================
+
+ # Basic usage
+ expect "str_slice('hello', 2, 4)", str_slice("hello", 2, 4), to_be: "ell";
+ expect "str_slice('hello', 1, 5)", str_slice("hello", 1, 5), to_be: "hello";
+ expect "str_slice('hello', 1, 1)", str_slice("hello", 1, 1), to_be: "h";
+ expect "str_slice('hello', 5, 5)", str_slice("hello", 5, 5), to_be: "o";
+
+ # Negative indices
+ expect "str_slice('hello', -3)", str_slice("hello", -3), to_be: "llo";
+ expect "str_slice('hello', -1)", str_slice("hello", -1), to_be: "o";
+ expect "str_slice('hello', 2, -1)",str_slice("hello", 2, -1),to_be: "ello";
+ expect "str_slice('hello', -3, -1)",str_slice("hello", -3, -1),to_be: "llo";
+ expect "str_slice('hello', -5, -1)",str_slice("hello", -5, -1),to_be: "hello";
+
+ # Default args (full string)
+ expect "str_slice('hello')", str_slice("hello"), to_be: "hello";
+ expect "str_slice('hello', 2)", str_slice("hello", 2), to_be: "ello";
+
+ # Out-of-bounds clamping
+ expect "str_slice('hello', 0, 3)", str_slice("hello", 0, 3), to_be: "hel";
+ expect "str_slice('hello', 1, 99)",str_slice("hello", 1, 99),to_be: "hello";
+ expect "str_slice('hello', 3, 99)",str_slice("hello", 3, 99),to_be: "llo";
+
+ # Invalid range → empty
+ expect "str_slice('hello', 4, 2)", str_slice("hello", 4, 2), to_be: "";
+ expect "str_slice('hello', 6, 8)", str_slice("hello", 6, 8), to_be: "";
+ expect "str_slice('', 1, 3)", str_slice("", 1, 3), to_be: "";
+
+ # Single character string
+ expect "str_slice('x', 1, 1)", str_slice("x", 1, 1), to_be: "x";
+ expect "str_slice('x', 2, 3)", str_slice("x", 2, 3), to_be: "";
+
+ # =========================================================================
+ # str_ends_with
+ # =========================================================================
+
+ expect_true "str_ends_with('hello', 'lo')", str_ends_with("hello", "lo");
+ expect_true "str_ends_with('hello', 'hello')", str_ends_with("hello", "hello");
+ expect_true "str_ends_with('hello', 'o')", str_ends_with("hello", "o");
+ expect_false "str_ends_with('hello', 'he')", str_ends_with("hello", "he");
+ expect_false "str_ends_with('hello', 'x')", str_ends_with("hello", "x");
+ expect_true "str_ends_with('hello', '')", str_ends_with("hello", "");
+ expect_true "str_ends_with('', '')", str_ends_with("", "");
+
+ # =========================================================================
+ # str_starts_with
+ # =========================================================================
+
+ expect_true "str_starts_with('hello', 'he')", str_starts_with("hello", "he");
+ expect_true "str_starts_with('hello', 'hello')", str_starts_with("hello", "hello");
+ expect_true "str_starts_with('hello', 'h')", str_starts_with("hello", "h");
+ expect_false "str_starts_with('hello', 'lo')", str_starts_with("hello", "lo");
+ expect_false "str_starts_with('hello', 'x')", str_starts_with("hello", "x");
+ expect_true "str_starts_with('hello', '')", str_starts_with("hello", "");
+ expect_true "str_starts_with('', '')", str_starts_with("", "");
+
+ # =========================================================================
+ # str_reverse
+ # =========================================================================
+
+ expect "str_reverse('hello')", str_reverse("hello"), to_be: "olleh";
+ expect "str_reverse('abcd')", str_reverse("abcd"), to_be: "dcba";
+ expect "str_reverse('a')", str_reverse("a"), to_be: "a";
+ expect "str_reverse('')", str_reverse(""), to_be: "";
+ expect "str_reverse('ab')", str_reverse("ab"), to_be: "ba";
+ expect "str_reverse('racecar')",str_reverse("racecar"),to_be: "racecar";
+ expect "str_reverse(' hi')", str_reverse(" hi"), to_be: "ih ";
+
+ # =========================================================================
+ # str_upper
+ # =========================================================================
+
+ expect "str_upper('hello')", str_upper("hello"), to_be: "HELLO";
+ expect "str_upper('Hello!')", str_upper("Hello!"), to_be: "HELLO!";
+ expect "str_upper('123')", str_upper("123"), to_be: "123";
+ expect "str_upper('HELLO')", str_upper("HELLO"), to_be: "HELLO";
+ expect "str_upper('')", str_upper(""), to_be: "";
+ expect "str_upper('a1b2c3')", str_upper("a1b2c3"), to_be: "A1B2C3";
+ expect "str_upper('hello world')", str_upper("hello world"), to_be: "HELLO WORLD";
+
+ # =========================================================================
+ # str_lower
+ # =========================================================================
+
+ expect "str_lower('HELLO')", str_lower("HELLO"), to_be: "hello";
+ expect "str_lower('Hello!')", str_lower("Hello!"), to_be: "hello!";
+ expect "str_lower('123')", str_lower("123"), to_be: "123";
+ expect "str_lower('hello')", str_lower("hello"), to_be: "hello";
+ expect "str_lower('')", str_lower(""), to_be: "";
+ expect "str_lower('A1B2C3')", str_lower("A1B2C3"), to_be: "a1b2c3";
+ expect "str_lower('HELLO WORLD')", str_lower("HELLO WORLD"), to_be: "hello world";
+
+ # =========================================================================
+ # str_capitalize
+ # =========================================================================
+
+ expect "str_capitalize('hello')", str_capitalize("hello"), to_be: "Hello";
+ expect "str_capitalize('HELLO')", str_capitalize("HELLO"), to_be: "Hello";
+ expect "str_capitalize('hELLO wORLD')", str_capitalize("hELLO wORLD"), to_be: "Hello world";
+ expect "str_capitalize('a')", str_capitalize("a"), to_be: "A";
+ expect "str_capitalize('ABC')", str_capitalize("ABC"), to_be: "Abc";
+ expect "str_capitalize('123abc')", str_capitalize("123abc"), to_be: "123abc";
+
+ # =========================================================================
+ # str_title
+ # =========================================================================
+
+ expect "str_title('hello world')", str_title("hello world"), to_be: "Hello World";
+ expect "str_title('HELLO WORLD')", str_title("HELLO WORLD"), to_be: "Hello World";
+ expect "str_title('it is a test')", str_title("it is a test"), to_be: "It Is A Test";
+ expect "str_title('one')", str_title("one"), to_be: "One";
+ expect "str_title('')", str_title(""), to_be: "";
+ expect "str_title('hello')", str_title("hello"), to_be: "Hello";
+ # Non-alpha acts as word boundary
+ expect "str_title('it\\'s a test')", str_title("it's a test"), to_be: "It'S A Test";
+ expect "str_title('foo-bar')", str_title("foo-bar"), to_be: "Foo-Bar";
+
+ # =========================================================================
+ # str_repeat
+ # =========================================================================
+
+ expect "str_repeat('ab', 3)", str_repeat("ab", 3), to_be: "ababab";
+ expect "str_repeat('hi', 1)", str_repeat("hi", 1), to_be: "hi";
+ expect "str_repeat('x', 0)", str_repeat("x", 0), to_be: "";
+ expect "str_repeat('', 5)", str_repeat("", 5), to_be: "";
+ expect "str_repeat('abc',2)", str_repeat("abc",2), to_be: "abcabc";
+ expect "str_repeat('-', 4)", str_repeat("-", 4), to_be: "----";
+
+ # =========================================================================
+ # str_split (results stored in list str_split)
+ # =========================================================================
+
+ str_split "a,b,c", ",";
+ expect "str_split 'a,b,c' [1]", str_split[1], to_be: "a";
+ expect "str_split 'a,b,c' [2]", str_split[2], to_be: "b";
+ expect "str_split 'a,b,c' [3]", str_split[3], to_be: "c";
+ expect "str_split 'a,b,c' len", length(str_split), to_be: "3";
+
+ str_split "hello";
+ expect "str_split 'hello' [1]", str_split[1], to_be: "hello";
+ expect "str_split 'hello' len", length(str_split), to_be: "1";
+
+ str_split "a,,b", ",";
+ expect "str_split 'a,,b' [1]", str_split[1], to_be: "a";
+ expect "str_split 'a,,b' [2]", str_split[2], to_be: "";
+ expect "str_split 'a,,b' [3]", str_split[3], to_be: "b";
+ expect "str_split 'a,,b' len", length(str_split), to_be: "3";
+
+ str_split ",a,", ",";
+ expect "str_split ',a,' [1]", str_split[1], to_be: "";
+ expect "str_split ',a,' [2]", str_split[2], to_be: "a";
+ expect "str_split ',a,' [3]", str_split[3], to_be: "";
+ expect "str_split ',a,' len", length(str_split), to_be: "3";
+
+ str_split "one two three";
+ expect "str_split 'one two three' [1]", str_split[1], to_be: "one";
+ expect "str_split 'one two three' [2]", str_split[2], to_be: "two";
+ expect "str_split 'one two three' [3]", str_split[3], to_be: "three";
+
+ # =========================================================================
+ # str_split_lines
+ # =========================================================================
+
+ str_split_lines "a\nb\nc";
+ expect "str_split_lines [1]", str_split_lines[1], to_be: "a";
+ expect "str_split_lines [2]", str_split_lines[2], to_be: "b";
+ expect "str_split_lines [3]", str_split_lines[3], to_be: "c";
+ expect "str_split_lines len", length(str_split_lines), to_be: "3";
+
+ # Trailing newline is ignored
+ str_split_lines "end\n";
+ expect "str_split_lines 'end\\n' [1]", str_split_lines[1], to_be: "end";
+ expect "str_split_lines 'end\\n' len", length(str_split_lines), to_be: "1";
+
+ str_split_lines "hello";
+ expect "str_split_lines 'hello' [1]", str_split_lines[1], to_be: "hello";
+ expect "str_split_lines 'hello' len", length(str_split_lines), to_be: "1";
+
+ str_split_lines "a\n\nb";
+ expect "str_split_lines 'a\\n\\nb' [1]", str_split_lines[1], to_be: "a";
+ expect "str_split_lines 'a\\n\\nb' [2]", str_split_lines[2], to_be: "";
+ expect "str_split_lines 'a\\n\\nb' [3]", str_split_lines[3], to_be: "b";
+
+ # =========================================================================
+ # str_truncate
+ # =========================================================================
+
+ expect "str_truncate('hello world', 8)", str_truncate("hello world", 8), to_be: "hello...";
+ expect "str_truncate('hi', 10)", str_truncate("hi", 10), to_be: "hi";
+ expect "str_truncate('abcdefg', 7)", str_truncate("abcdefg", 7), to_be: "abcdefg";
+ expect "str_truncate('abcdefg', 6)", str_truncate("abcdefg", 6), to_be: "abc...";
+ expect "str_truncate('abcdefg', 3)", str_truncate("abcdefg", 3), to_be: "...";
+ expect "str_truncate('hi', 2)", str_truncate("hi", 2), to_be: "hi";
+ expect "str_truncate('', 5)", str_truncate("", 5), to_be: "";
+
+ # =========================================================================
+ # str_count_char
+ # =========================================================================
+
+ expect "str_count_char('hello', 'lo')", str_count_char("hello", "lo"), to_be: "3";
+ expect "str_count_char('aabbcc', 'ac')", str_count_char("aabbcc", "ac"), to_be: "4";
+ expect "str_count_char('abc', 'xyz')", str_count_char("abc", "xyz"), to_be: "0";
+ expect "str_count_char('', 'a')", str_count_char("", "a"), to_be: "0";
+ expect "str_count_char('aaaa', 'a')", str_count_char("aaaa", "a"), to_be: "4";
+ expect "str_count_char('hello', 'l')", str_count_char("hello", "l"), to_be: "2";
+ expect "str_count_char('hello', 'aeiou')", str_count_char("hello", "aeiou"), to_be: "2";
+
+ # =========================================================================
+ # str_count
+ # =========================================================================
+
+ expect "str_count('this is it', 'is')", str_count("this is it", "is"), to_be: "2";
+ expect "str_count('aaaa', 'aa')", str_count("aaaa", "aa"), to_be: "2";
+ expect "str_count('banana', 'an')", str_count("banana", "an"), to_be: "2";
+ expect "str_count('hello', 'xyz')", str_count("hello", "xyz"), to_be: "0";
+ expect "str_count('abc', '')", str_count("abc", ""), to_be: "4";
+ expect "str_count('hello', 'l')", str_count("hello", "l"), to_be: "2";
+ expect "str_count('hello', 'o')", str_count("hello", "o"), to_be: "1";
+ expect "str_count('aaaaa', 'aaa')", str_count("aaaaa", "aaa"), to_be: "1";
+ expect "str_count('', 'a')", str_count("", "a"), to_be: "0";
+ expect "str_count('', '')", str_count("", ""), to_be: "1";
+ expect "str_count('aaa', 'aa')", str_count("aaa", "aa"), to_be: "1";
+
+ # =========================================================================
+ # str_lstrip
+ # =========================================================================
+
+ expect "str_lstrip(' hello')", str_lstrip(" hello"), to_be: "hello";
+ expect "str_lstrip('hello ')", str_lstrip("hello "), to_be: "hello ";
+ expect "str_lstrip(' hello ')", str_lstrip(" hello "), to_be: "hello ";
+ expect "str_lstrip('xxhello', 'x')", str_lstrip("xxhello", "x"), to_be: "hello";
+ expect "str_lstrip('hello', 'x')", str_lstrip("hello", "x"), to_be: "hello";
+ expect "str_lstrip('', 'x')", str_lstrip("", "x"), to_be: "";
+ expect "str_lstrip('\t\nhello')", str_lstrip("\t\nhello"), to_be: "hello";
+
+ # =========================================================================
+ # str_rstrip
+ # =========================================================================
+
+ expect "str_rstrip('hello ')", str_rstrip("hello "), to_be: "hello";
+ expect "str_rstrip(' hello')", str_rstrip(" hello"), to_be: " hello";
+ expect "str_rstrip(' hello ')", str_rstrip(" hello "), to_be: " hello";
+ expect "str_rstrip('helloxx', 'x')", str_rstrip("helloxx", "x"), to_be: "hello";
+ expect "str_rstrip('hello', 'x')", str_rstrip("hello", "x"), to_be: "hello";
+ expect "str_rstrip('', 'x')", str_rstrip("", "x"), to_be: "";
+ expect "str_rstrip('hello\t\n')", str_rstrip("hello\t\n"), to_be: "hello";
+
+ # =========================================================================
+ # str_strip
+ # =========================================================================
+
+ expect "str_strip(' hello ')", str_strip(" hello "), to_be: "hello";
+ expect "str_strip('hello')", str_strip("hello"), to_be: "hello";
+ expect "str_strip('xxhelloxx', 'x')", str_strip("xxhelloxx", "x"), to_be: "hello";
+ expect "str_strip(' hello')", str_strip(" hello"), to_be: "hello";
+ expect "str_strip('hello ')", str_strip("hello "), to_be: "hello";
+ expect "str_strip('')", str_strip(""), to_be: "";
+ expect "str_strip('\t hello \n')", str_strip("\t hello \n"), to_be: "hello";
+
+ # =========================================================================
+ # str_is_alnum
+ # =========================================================================
+
+ expect_true "str_is_alnum('abc123')", str_is_alnum("abc123");
+ expect_true "str_is_alnum('ABC123')", str_is_alnum("ABC123");
+ expect_true "str_is_alnum('abc')", str_is_alnum("abc");
+ expect_true "str_is_alnum('123')", str_is_alnum("123");
+ expect_false "str_is_alnum('abc!')", str_is_alnum("abc!");
+ expect_false "str_is_alnum('abc 123')", str_is_alnum("abc 123");
+ expect_false "str_is_alnum('')", str_is_alnum("");
+
+ # =========================================================================
+ # str_is_alpha
+ # =========================================================================
+
+ expect_true "str_is_alpha('hello')", str_is_alpha("hello");
+ expect_true "str_is_alpha('HELLO')", str_is_alpha("HELLO");
+ expect_true "str_is_alpha('Hello')", str_is_alpha("Hello");
+ expect_false "str_is_alpha('hello1')", str_is_alpha("hello1");
+ expect_false "str_is_alpha('hello!')", str_is_alpha("hello!");
+ expect_false "str_is_alpha('123')", str_is_alpha("123");
+ expect_false "str_is_alpha('')", str_is_alpha("");
+
+ # =========================================================================
+ # str_is_digit
+ # =========================================================================
+
+ expect_true "str_is_digit('42')", str_is_digit("42");
+ expect_true "str_is_digit('0')", str_is_digit("0");
+ expect_true "str_is_digit('-5')", str_is_digit("-5");
+ expect_false "str_is_digit('3.14')", str_is_digit("3.14");
+ expect_false "str_is_digit('hello')", str_is_digit("hello");
+ expect_false "str_is_digit('12abc')", str_is_digit("12abc");
+ expect_false "str_is_digit('')", str_is_digit("");
+
+ # =========================================================================
+ # str_find_char
+ # =========================================================================
+
+ expect "str_find_char('hello', 'l')", str_find_char("hello", "l"), to_be: "3";
+ expect "str_find_char('hello', 'h')", str_find_char("hello", "h"), to_be: "1";
+ expect "str_find_char('hello', 'o')", str_find_char("hello", "o"), to_be: "5";
+ expect "str_find_char('hello', 'z')", str_find_char("hello", "z"), to_be: "0";
+ expect "str_find_char('abca', 'a')", str_find_char("abca", "a"), to_be: "1";
+ expect "str_find_char('', 'a')", str_find_char("", "a"), to_be: "0";
+
+ # =========================================================================
+ # str_rfind_char
+ # =========================================================================
+
+ expect "str_rfind_char('hello', 'l')", str_rfind_char("hello", "l"), to_be: "4";
+ expect "str_rfind_char('hello', 'h')", str_rfind_char("hello", "h"), to_be: "1";
+ expect "str_rfind_char('hello', 'o')", str_rfind_char("hello", "o"), to_be: "5";
+ expect "str_rfind_char('hello', 'z')", str_rfind_char("hello", "z"), to_be: "0";
+ expect "str_rfind_char('abca', 'a')", str_rfind_char("abca", "a"), to_be: "4";
+ expect "str_rfind_char('', 'a')", str_rfind_char("", "a"), to_be: "0";
+
+ # =========================================================================
+ # str_splice
+ # =========================================================================
+
+ expect "str_splice('hello world', 6)", str_splice("hello world", 6), to_be: "hello";
+ expect "str_splice('hello world', 6, 5)", str_splice("hello world", 6, 5), to_be: "hello ";
+ expect "str_splice('hello world', 6, 5, '!')", str_splice("hello world", 6, 5, "!"), to_be: "hello !";
+ expect "str_splice('hello', 1)", str_splice("hello", 1), to_be: "";
+ expect "str_splice('hello', 3, 1)", str_splice("hello", 3, 1), to_be: "helo";
+ expect "str_splice('hello', 3, 1, 'XY')", str_splice("hello", 3, 1, "XY"), to_be: "heXYlo";
+ expect "str_splice('hello', 6, 0, '!')", str_splice("hello", 6, 0, "!"), to_be: "hello!";
+ expect "str_splice('abcde', 2, 3, 'Z')", str_splice("abcde", 2, 3, "Z"), to_be: "aZe";
+
+ # =========================================================================
+ # str_replace
+ # =========================================================================
+
+ expect "str_replace('aabbaa', 'aa', 'X')", str_replace("aabbaa", "aa", "X"), to_be: "XbbX";
+ expect "str_replace('hello', 'l', 'r')", str_replace("hello", "l", "r"), to_be: "herro";
+ expect "str_replace('hello', 'z', 'r')", str_replace("hello", "z", "r"), to_be: "hello";
+ expect "str_replace('hello', 'hello', '')", str_replace("hello", "hello", ""), to_be: "";
+ expect "str_replace('aaaa', 'aa', 'X')", str_replace("aaaa", "aa", "X"), to_be: "XX";
+ expect "str_replace('', 'a', 'b')", str_replace("", "a", "b"), to_be: "";
+ expect "str_replace('abc', 'b', 'BB')", str_replace("abc", "b", "BB"), to_be: "aBBc";
+
+ # =========================================================================
+ # str_replacen
+ # =========================================================================
+
+ expect "str_replacen('aabbaa', 'aa', 'X', 1)", str_replacen("aabbaa", "aa", "X", 1), to_be: "Xbbaa";
+ expect "str_replacen('aabbaa', 'aa', 'X', 2)", str_replacen("aabbaa", "aa", "X", 2), to_be: "XbbX";
+ expect "str_replacen('hello', 'l', 'r', 0)", str_replacen("hello", "l", "r", 0), to_be: "hello";
+ expect "str_replacen('hello', 'l', 'r', 1)", str_replacen("hello", "l", "r", 1), to_be: "herlo";
+ expect "str_replacen('aaaa', 'a', 'X', 3)", str_replacen("aaaa", "a", "X", 3), to_be: "XXXa";
+ expect "str_replacen('abc', 'z', 'X', 5)", str_replacen("abc", "z", "X", 5), to_be: "abc";
+
+ # =========================================================================
+ # str_replacenth
+ # =========================================================================
+
+ expect "str_replacenth('aabbaa', 'aa', 'X', 1)", str_replacenth("aabbaa", "aa", "X", 1), to_be: "Xbbaa";
+ expect "str_replacenth('aabbaa', 'aa', 'X', 2)", str_replacenth("aabbaa", "aa", "X", 2), to_be: "aabbX";
+ expect "str_replacenth('hello', 'l', 'r', 2)", str_replacenth("hello", "l", "r", 2), to_be: "helro";
+ expect "str_replacenth('hello', 'l', 'r', 1)", str_replacenth("hello", "l", "r", 1), to_be: "herlo";
+ expect "str_replacenth('aaaa', 'a', 'X', 3)", str_replacenth("aaaa", "a", "X", 3), to_be: "aaXa";
+ # Fewer occurrences than n → unchanged
+ expect "str_replacenth('hello', 'z', 'X', 1)", str_replacenth("hello", "z", "X", 1), to_be: "hello";
+
+ # =========================================================================
+ # str_remove_prefix
+ # =========================================================================
+
+ expect "str_remove_prefix('hello world', 'hello ')", str_remove_prefix("hello world", "hello "), to_be: "world";
+ expect "str_remove_prefix('hello world', 'world')", str_remove_prefix("hello world", "world"), to_be: "hello world";
+ expect "str_remove_prefix('hello', '')", str_remove_prefix("hello", ""), to_be: "hello";
+ expect "str_remove_prefix('hello', 'hello')", str_remove_prefix("hello", "hello"), to_be: "";
+ expect "str_remove_prefix('hello', 'xyz')", str_remove_prefix("hello", "xyz"), to_be: "hello";
+ expect "str_remove_prefix('aabaa', 'aa')", str_remove_prefix("aabaa", "aa"), to_be: "baa";
+
+ # =========================================================================
+ # str_remove_suffix
+ # =========================================================================
+
+ expect "str_remove_suffix('hello world', ' world')", str_remove_suffix("hello world", " world"), to_be: "hello";
+ expect "str_remove_suffix('hello world', 'hello')", str_remove_suffix("hello world", "hello"), to_be: "hello world";
+ expect "str_remove_suffix('hello', '')", str_remove_suffix("hello", ""), to_be: "hello";
+ expect "str_remove_suffix('hello', 'hello')", str_remove_suffix("hello", "hello"), to_be: "";
+ expect "str_remove_suffix('hello', 'xyz')", str_remove_suffix("hello", "xyz"), to_be: "hello";
+ expect "str_remove_suffix('aabaa', 'aa')", str_remove_suffix("aabaa", "aa"), to_be: "aab";
+
+ # =========================================================================
+ # str_find
+ # =========================================================================
+
+ expect "str_find('hello world', 'world')", str_find("hello world", "world"), to_be: "7";
+ expect "str_find('hello world', 'hello')", str_find("hello world", "hello"), to_be: "1";
+ expect "str_find('hello world', ' ')", str_find("hello world", " "), to_be: "6";
+ expect "str_find('hello world', 'xyz')", str_find("hello world", "xyz"), to_be: "0";
+ expect "str_find('aabaa', 'aa')", str_find("aabaa", "aa"), to_be: "1";
+ expect "str_find('hello', 'hello')", str_find("hello", "hello"), to_be: "1";
+ expect "str_find('hello', 'helloo')", str_find("hello", "helloo"), to_be: "0";
+ expect "str_find('', 'a')", str_find("", "a"), to_be: "0";
+ expect "str_find('abcabc', 'bc')", str_find("abcabc", "bc"), to_be: "2";
+ expect "str_find('hello', 'o')", str_find("hello", "o"), to_be: "5";
+
+ # =========================================================================
+ # str_center
+ # =========================================================================
+
+ expect "str_center('hello', 10)", str_center("hello", 10), to_be: " hello ";
+ expect "str_center('hello', 10, '-')", str_center("hello", 10, "-"), to_be: "--hello--";
+ expect "str_center('hello', 5)", str_center("hello", 5), to_be: "hello";
+ expect "str_center('hello', 6)", str_center("hello", 6), to_be: " hello";
+ expect "str_center('hello', 7)", str_center("hello", 7), to_be: " hello ";
+ expect "str_center('', 5)", str_center("", 5), to_be: " ";
+ expect "str_center('a', 5)", str_center("a", 5), to_be: " a ";
+ expect "str_center('ab', 5)", str_center("ab", 5), to_be: " ab ";
+ expect "str_center('abc', 5)", str_center("abc", 5), to_be: " abc";
+ expect "str_center('x', 1)", str_center("x", 1), to_be: "x";
+ expect "str_center('x', 0)", str_center("x", 0), to_be: "x";
+
+ # =========================================================================
+ # str_ljust
+ # =========================================================================
+
+ expect "str_ljust('hello', 10)", str_ljust("hello", 10), to_be: "hello ";
+ expect "str_ljust('hello', 10, '-')", str_ljust("hello", 10, "-"), to_be: "hello-----";
+ expect "str_ljust('hello', 5)", str_ljust("hello", 5), to_be: "hello";
+ expect "str_ljust('hello', 7)", str_ljust("hello", 7), to_be: "hello ";
+ expect "str_ljust('hello', 3)", str_ljust("hello", 3), to_be: "hello";
+ expect "str_ljust('', 5)", str_ljust("", 5), to_be: " ";
+ expect "str_ljust('a', 5)", str_ljust("a", 5), to_be: "a ";
+
+ # =========================================================================
+ # str_rjust
+ # =========================================================================
+
+ expect "str_rjust('hello', 10)", str_rjust("hello", 10), to_be: " hello";
+ expect "str_rjust('hello', 10, '-')", str_rjust("hello", 10, "-"), to_be: "-----hello";
+ expect "str_rjust('hello', 5)", str_rjust("hello", 5), to_be: "hello";
+ expect "str_rjust('hello', 7)", str_rjust("hello", 7), to_be: " hello";
+ expect "str_rjust('hello', 3)", str_rjust("hello", 3), to_be: "hello";
+ expect "str_rjust('', 5)", str_rjust("", 5), to_be: " ";
+ expect "str_rjust('a', 5)", str_rjust("a", 5), to_be: " a";
+}
diff --git a/test/test.gs b/test/test.gs
deleted file mode 100644
index fa0656f..0000000
--- a/test/test.gs
+++ /dev/null
@@ -1,190 +0,0 @@
-%include ../math
-%include ../string
-%include ../list
-%include ../emoji
-%include ../cskv
-%include ../cmd
-
-list console;
-
-%define ASSERT_EQ(LEFT,RIGHT,MESSAGE) \
- if not casecmp(""&(LEFT), ""&(RIGHT)) { \
- add (MESSAGE)&" should be equal to "&(RIGHT)&", but it is "&(LEFT) to console; \
- }
-
-costumes "blank.svg" as "@ascii/";
-
-list things;
-
-struct point {x, y}
-
-list point points;
-
-proc test {
- # math
- ASSERT_EQ(MIN(1, 2), 1, "MIN(1, 2)");
- ASSERT_EQ(MAX(1, 2), 2, "MAX(1, 2)");
- ASSERT_EQ(RGB(255, 0, 0), 16711680, "RGB(255, 0, 0)");
- ASSERT_EQ(RGBA(255, 0, 0, 0.5), 25100288, "RGBA(255, 0, 0, 0.5)");
- ASSERT_EQ(HEX("FF"), 255, "HEX(\"FF\") should be ");
- ASSERT_EQ(BIN("11111111"), 255, "BIN(\"11111111\")");
- ASSERT_EQ(OCT("377"), 255, "OCT(\"377\")");
- ASSERT_EQ(ACOSH(2), 1.3169578969248166, "ACOSH(2)");
- ASSERT_EQ(ASINH(2), 1.4436354751788103, "ASINH(2)");
- ASSERT_EQ(ATANH(0.5), 0.5493061443340548, "ATANH(0.5)");
- ASSERT_EQ(COSH(2), 3.7621956910836314, "COSH(2)");
- ASSERT_EQ(SINH(2), 3.626860407847019, "SINH(2)");
- ASSERT_EQ(TANH(1), 0.7615941559557649, "TANH(1)");
- ASSERT_EQ(DIST(0, 0, 1, 1), 1.4142135623730951, "DIST(0, 0, 1, 1)");
- ASSERT_EQ(MAG(1, 1), 1.4142135623730951, "MAG(1, 1)");
- ASSERT_EQ(GAMMA(5), 2.0783258451246165, "GAMMA(5)");
- ASSERT_EQ(POSITIVE_CLAMP(-1), 0, "POSITIVE_CLAMP(-1)");
- ASSERT_EQ(NEGATIVE_CLAMP(1), 0, "NEGATIVE_CLAMP(1)");
- ASSERT_EQ(CLAMP(1, 0, 2), 1, "CLAMP(1, 0, 2)");
- ASSERT_EQ(CLAMP(-1, 0, 2), 0, "CLAMP(-1, 0, 2)");
- ASSERT_EQ(BIT(0, 255), 255, "BIT(0, 255)");
- ASSERT_EQ(LERP(0, 1, 0.5), 0.5, "LERP(0, 1, 0.5)");
- ASSERT_EQ(MAP(0, 1, 50, 100, 0.5), 75, "MAP(0, 1, 50, 100, 0.5)");
- ASSERT_EQ(RAD("90"), PI/2, "RAD(90)");
- ASSERT_EQ(DEG(PI/"2"), 90, "DEG(PI/2)");
- # string
- ASSERT_EQ(countchar("AAA", "A"), 3, "countchar(...)");
- ASSERT_EQ(countchar("AAA", "B"), 0, "countchar(...)");
- ASSERT_EQ(countchars("AAA", "A"), 3, "countchars(...)");
- ASSERT_EQ(countchars("AAA", "B"), 0, "countchars(...)");
- ASSERT_EQ(slice("hello world", 1, 6), "hello", "slice(...)");
- ASSERT_EQ(slice("hello world", 7, 12), "world", "slice(...)");
- ASSERT_EQ(replace("lollollyllylollylly", "lolly", "LO"), "lolLOllyLOlly", "replace(...)");
- ASSERT_EQ(replacen("one one one", "one", "two", 2), "two two one", "lreplacen(...)");
- ASSERT_EQ(replacenth("one one one", "one", "two", 2), "one two one", "replacenth(...)");
- ASSERT_EQ(splice("hello world", 7, 5, "universe"), "hello universe", "1 splice(...)");
- ASSERT_EQ(splice("hello world", 7, 5, ""), "hello ", "2 splice(...)");
- ASSERT_EQ(uppercase("hello world"), "HELLO WORLD", "uppercase(...)");
- ASSERT_EQ(lowercase("HELLO WORLD"), "hello world", "lowercase(...)");
- ASSERT_EQ(capitalize("HELLO World"), "Hello world", "capitalize(...)");
- ASSERT_EQ(findchar("hello world", "l"), 3, "1 findchar(...)");
- ASSERT_EQ(findchar("hello world", "x"), 0, "2 findchar(...)");
- ASSERT_EQ(rfindchar("hello world", "l"), 10, "1 rfindchar(...)");
- ASSERT_EQ(rfindchar("hello world", "x"), 0, "2 rfindchar(...)");
- ASSERT_EQ(isalnum("Abc123"), true, "1 isalnum(...)");
- ASSERT_EQ(isalnum("Abc123!@#"), false, "2 isalnum(...)");
- ASSERT_EQ(isalnum(""), false, "3 isalnum(...)");
- ASSERT_EQ(isalpha("Abc"), true, "1 isalpha(...)");
- ASSERT_EQ(isalpha("Abc123"), false, "2 isalpha(...)");
- ASSERT_EQ(isalpha(""), false, "2 isalpha(...)");
- ASSERT_EQ(lstrip("www.example.com", "w."), "example.com", "1 lstrip(...)");
- ASSERT_EQ(lstrip(" hello ", " "), "hello ", "2 lstrip(...)");
- ASSERT_EQ(rstrip("www.example.com", ".com"), "www.example", "1 rstrip(...)");
- ASSERT_EQ(rstrip(" hello ", " "), " hello", "2 rstrip(...)");
- ASSERT_EQ(strip(" ", "< >"), "HELLO", "strip(...)");
- split "one,two,three,four,five", ",";
- ASSERT_EQ(split[1], "one", "split(...)[1]");
- ASSERT_EQ(split[2], "two", "split(...)[2]");
- ASSERT_EQ(split[3], "three", "split(...)[3]");
- ASSERT_EQ(split[4], "four", "split(...)[4]");
- ASSERT_EQ(split[5], "five", "split(...)[5]");
- JOIN(split, ",", joined);
- ASSERT_EQ(joined, "one,two,three,four,five", "JOIN(...)");
- ASSERT_EQ(reverse("hello"), "olleh", "reverse(...)");
- ASSERT_EQ(repeatstr("hello", 3), "hellohellohello", "repeatstr(...)");
- ASSERT_EQ(titlecase("hello world"), "Hello World", "titlecase(...)");
- splitlines "";
- ASSERT_EQ(length(split), 0, "1 splitlines(...)");
- splitlines "Two lines\n";
- ASSERT_EQ(length(split), 1, "1 splitlines(...)");
- ASSERT_EQ(split[1], "Two lines", "1 splitlines(...)");
- ASSERT_EQ(truncate("Hello world!", 12), "Hello world!", "1 shorten(...)");
- ASSERT_EQ(truncate("Hello world!", 11), "Hello ...", "2 shorten(...)");
- ASSERT_EQ(truncate("Hello world!", 10), "Hello...", "3 shorten(...)");
- # list
- split "5,3,1,2,4", ",";
- INSERTION_SORT(split);
- JOIN(split, ",", joined);
- ASSERT_EQ(joined, "1,2,3,4,5", "INSERTION_SORT(...)");
- delete points;
- add point { x: 2, y: 200 } to points;
- add point { x: 1, y: 100 } to points;
- add point { x: 4, y: 400 } to points;
- add point { x: 3, y: 300 } to points;
- INSERTION_SORT_BY_FIELD(point, points, .x);
- ASSERT_EQ(points[1].x, 1, "INSERTION_SORT_BY_FIELD(...)[1]");
- ASSERT_EQ(points[2].x, 2, "INSERTION_SORT_BY_FIELD(...)[2]");
- ASSERT_EQ(points[3].x, 3, "INSERTION_SORT_BY_FIELD(...)[3]");
- ASSERT_EQ(points[4].x, 4, "INSERTION_SORT_BY_FIELD(...)[4]");
- split "1,2,3,4,5", ",";
- COUNT(split, split[i] % 2 == 0, count);
- ASSERT_EQ(count, 2, "COUNT(...)");
- SUM(split, split[i] % 2 == 0, sum);
- ASSERT_EQ(sum, 6, "SUM(...)");
- JOIN_BY_FIELD(points, .x, ",", joined);
- ASSERT_EQ(joined, "1,2,3,4", "JOIN_BY_FIELD(...)");
- FINDMAX(split, split[i] % 2 == 0, max);
- ASSERT_EQ(max, 4, "FINDMAX(...)");
- FINDMIN(split, split[i] % 2 == 0, min);
- ASSERT_EQ(min, 2, "FINDMIN(...)");
- REVERSE(split);
- JOIN(split, ",", joined);
- ASSERT_EQ(joined, "5,4,3,2,1", "REVERSE(...)");
- COPY(split, things);
- JOIN(things, ",", joined);
- ASSERT_EQ(joined, "5,4,3,2,1", "COPY(...)");
- EXTEND(split, things);
- JOIN(things, ",", joined);
- ASSERT_EQ(joined, "5,4,3,2,1,5,4,3,2,1", "EXTEND(...)");
- UNIQUE(split);
- JOIN(split, ",", joined);
- ASSERT_EQ(joined, "5,4,3,2,1", "UNIQUE(...)");
- SUM_BY_FIELD(points, .x, points[i].x % 2 == 0, sum);
- ASSERT_EQ(sum, 6, "SUM_BY_FIELD(...)");
- # TODO [BLOCKED BY]: https://github.com/aspizu/goboscript/issues/71
- #FINDMAX_BY_FIELD(point, points, .x, points[i] % 2 == 0, pmax);
- #ASSERT_EQ(pmax.x, 4, "FINDMAX_BY_FIELD(...)");
- #FINDMIN_BY_FIELD(point, points, .x, points[i] % 2 == 0, pmin);
- #ASSERT_EQ(pmin.x, 2, "FINDMIN_BY_FIELD(...)");
- add point { x: 2, y: 200 } to points;
- add point { x: 1, y: 100 } to points;
- add point { x: 4, y: 400 } to points;
- UNIQUE_BY_FIELD(points, .x);
- JOIN_BY_FIELD(points, .x, ",", joined);
- ASSERT_EQ(joined, "1,2,3,4", "UNIQUE_BY_FIELD(...)");
- ASSERT_EQ(ENDSWITH("hello world", "world"), "true", "1 ENDSWITH(...)");
- ASSERT_EQ(ENDSWITH("hello world", "hello"), "false", "2 ENDSWITH(...)");
- ASSERT_EQ(STARTSWITH("hello world", "hello"), "true", "1 STARTSWITH(...)");
- ASSERT_EQ(STARTSWITH("hello world", "world"), "false", "2 STARTSWITH(...)");
- ASSERT_EQ(REMOVEPREFIX("hello world", "hello"), " world", "REMOVEPREFIX(...)");
- ASSERT_EQ(REMOVESUFFIX("hello world", "world"), "hello ", "REMOVESUFFIX(...)");
- # emoji
- if EMOJI("football") != "🏈" {
- add "football" to console;
- }
- if EMOJI("ping_pong") != "🏓" {
- add "ping_pong" to console;
- }
- if EMOJI("soccer") != "⚽" {
- add "soccer" to console;
- }
- if EMOJI("basketball") != "🏀" {
- add "basketball" to console;
- }
- # cskv
- cskv_unpack "a:1,b:2,array:3,A,B,C,c:3";
- ASSERT_EQ(cskv_pack(), "a:1,b:2,array:3,A,B,C,c:3", "cskv_pack(...)");
- # cmd
- local cmd = "echo -n 'Multiple \\' words'; echo -n 'Single \\\\' word' \\' \\;";
- i = cmd_next(1, cmd);
- ASSERT_EQ(cmd_args[1], "echo", "cmd_args[1]");
- ASSERT_EQ(cmd_args[2], "-n", "cmd_args[2]");
- ASSERT_EQ(cmd_args[3], "Multiple \\' words", "cmd_args[3]");
- i = cmd_next(i, cmd);
- ASSERT_EQ(cmd_args[1], "echo", "cmd_args[1]");
- ASSERT_EQ(cmd_args[2], "-n", "cmd_args[2]");
- ASSERT_EQ(cmd_args[3], "Single \\\\' word", "cmd_args[3]");
- ASSERT_EQ(cmd_args[4], "'", "cmd_args[4]");
- ASSERT_EQ(cmd_args[5], ";", "cmd_args[5]");
-}
-
-onflag {
- delete console;
- show console;
- test;
-}
diff --git a/test/test.py b/test/test.py
new file mode 100644
index 0000000..2c17a2e
--- /dev/null
+++ b/test/test.py
@@ -0,0 +1,146 @@
+import argparse
+import hashlib
+import pathlib
+import shlex
+import shutil
+import subprocess
+import sys
+import tempfile
+
+BLANK_SVG = '\n'
+STAGE_GS = 'costumes "blank.svg";\n'
+MAIN_GS = """\
+costumes "blank.svg" as "@ascii/";
+
+%include lib/test.gs
+
+func __testing_eq(a, b) {
+ if length($a) != length($b) {
+ return false;
+ }
+ local i = 1;
+ repeat length($a) {
+ switch_costume $a;
+ local c = costume_number();
+ switch_costume $b;
+ if c != costume_number() {
+ return false;
+ }
+ i++;
+ }
+ return true;
+}
+
+proc expect expr, value, to_be {
+ if not __testing_eq($value+"", $to_be+"") {
+ error "expected `" & $expr & "` to be `" & $to_be & "` but got `" & $value & "`";
+ }
+}
+
+proc expect_true expr, value {
+ if not $value {
+ error "expected `" & $expr & "` to be true but got `" & $value & "`";
+ }
+}
+
+proc expect_false expr, value {
+ if $value {
+ error "expected `" & $expr & "` to be false but got `" & $value & "`";
+ }
+}
+
+func _(value) {
+ return $value;
+}
+
+onflag {
+ test;
+}
+"""
+
+
+def resolve_includes(
+ input: pathlib.Path,
+ libdir: pathlib.Path,
+ prefix_map: dict[str, str] | None = None,
+) -> None:
+ prefix_map = prefix_map or {}
+ parent_dir = input.parent
+ lines = input.read_text().splitlines()
+ result = []
+ for line in lines:
+ if line.startswith("%include "):
+ include_path_str = line[len("%include ") :].strip()
+
+ # Apply prefix remapping before any other resolution.
+ for from_prefix, to_prefix in prefix_map.items():
+ if include_path_str.startswith(from_prefix):
+ include_path_str = to_prefix + include_path_str[len(from_prefix) :]
+ break
+
+ if include_path_str.startswith("std/"):
+ result.append(f"%include {include_path_str}")
+ continue
+
+ resolved = parent_dir.joinpath(include_path_str).resolve()
+ if not resolved.exists():
+ result.append(f"%include {include_path_str}")
+ continue
+
+ file_hash = hashlib.md5(str(resolved).encode()).hexdigest()
+ dest = libdir.joinpath(f"{file_hash}.gs")
+ if not dest.exists():
+ shutil.copy2(resolved, dest)
+ result.append(f"%include lib/{file_hash}.gs")
+ else:
+ result.append(line)
+ result.append("")
+ libdir.joinpath("test.gs").write_text("\n".join(result))
+
+
+def parse_prefix_map(pairs: list[str]) -> dict[str, str]:
+ """Parse a list of 'from=to' strings into a prefix mapping dict."""
+ mapping: dict[str, str] = {}
+ for pair in pairs:
+ if "=" not in pair:
+ sys.stderr.write(f"invalid --map entry (expected 'from=to'): {pair!r}\n")
+ sys.exit(1)
+ from_prefix, _, to_prefix = pair.partition("=")
+ mapping[from_prefix] = to_prefix
+ return mapping
+
+
+argparser = argparse.ArgumentParser()
+argparser.add_argument("input", type=pathlib.Path)
+argparser.add_argument(
+ "--map",
+ metavar="FROM=TO",
+ action="append",
+ default=[],
+ dest="prefix_map",
+ help=(
+ "Remap an import prefix before resolution. "
+ "May be specified multiple times. "
+ "Example: --map vendor/=../../third_party/"
+ ),
+)
+args = argparser.parse_args()
+input: pathlib.Path = args.input
+if input.suffixes != [".test", ".gs"]:
+ sys.stderr.write("input must be a `.test.gs` file\n")
+ sys.exit(1)
+
+prefix_map = parse_prefix_map(args.prefix_map)
+prefix_map["std/"] = "../"
+
+with tempfile.TemporaryDirectory() as tmpdir:
+ tmpdir = pathlib.Path(tmpdir)
+ tmpdir.joinpath("blank.svg").write_text(BLANK_SVG)
+ tmpdir.joinpath("stage.gs").write_text(STAGE_GS)
+ libdir = tmpdir.joinpath("lib")
+ libdir.mkdir()
+ resolve_includes(input, libdir, prefix_map)
+ tmpdir.joinpath("main.gs").write_text(MAIN_GS)
+ subprocess.run(shlex.split("goboscript build"), cwd=tmpdir).check_returncode()
+ subprocess.run(shlex.split("tw load"), cwd=tmpdir).check_returncode()
+ subprocess.run(shlex.split("tw start --listen")).check_returncode()
diff --git a/uuid.gs b/uuid.gs
index 5b8cf77..f7ef719 100644
--- a/uuid.gs
+++ b/uuid.gs
@@ -4,10 +4,13 @@
%define UUID_RANDHEX4 UUID_RANDHEX2 & UUID_RANDHEX2
%define UUID_RANDHEX8 UUID_RANDHEX4 & UUID_RANDHEX4
%define UUID_RANDHEX12 UUID_RANDHEX8 & UUID_RANDHEX4
-%define UUID_V4 UUID_RANDHEX8 \
- & "-" & UUID_RANDHEX4 \
- & "-4" & UUID_RANDHEX3 \
- & "-" & "89AB"[random(1, 4)] & UUID_RANDHEX3 \
- & "-" & UUID_RANDHEX12
%define UUID_NIL "00000000-0000-0000-0000-000000000000"
%define UUID_MAX "FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF"
+
+func uuid_v4() {
+ return UUID_RANDHEX8
+ & "-" & UUID_RANDHEX4
+ & "-4" & UUID_RANDHEX3
+ & "-" & "89AB"[random(1, 4)] & UUID_RANDHEX3
+ & "-" & UUID_RANDHEX12;
+}