diff --git a/demo/form/form-control.css b/demo/form/form-control.css
new file mode 100644
index 0000000..a39a4cd
--- /dev/null
+++ b/demo/form/form-control.css
@@ -0,0 +1,50 @@
+:host {
+ display: block;
+}
+
+#container {
+ position: relative;
+}
+
+:host(:invalid) #input {
+ color: red;
+}
+
+#matches-wrapper {
+ position: absolute;
+ bottom: 0;
+ transform: translateY(calc(100% + 4px));
+ background-color: white;
+ box-shadow: inset 0 0 0 1px black;
+ padding: 4px;
+}
+
+#matches {
+ width: 140px;
+ max-height: 400px;
+ overflow: auto;
+ box-sizing: border-box;
+ display: flex;
+ flex-direction: column;
+ gap: 1px;
+}
+#container:not(:focus-within) #matches-wrapper {
+ display: none;
+}
+
+.match {
+ display: block;
+ text-align: left;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ flex-shrink: 0;
+}
+
+#no-matches {
+ color: gray;
+}
+
+.match + #no-matches {
+ display: none;
+}
diff --git a/demo/form/form-control.js b/demo/form/form-control.js
new file mode 100644
index 0000000..5635963
--- /dev/null
+++ b/demo/form/form-control.js
@@ -0,0 +1,273 @@
+import XElement from '../../x-element.js';
+import data from './form-control.json' with { type: 'json' };
+import styleSheet from './form-control.css' with { type: 'css' };
+
+const entries = Object.entries(data);
+
+class FormControl extends XElement {
+ static #internalsMap = new WeakMap();
+
+ static get formAssociated() {
+ return true;
+ }
+
+ static get styles() {
+ return [styleSheet];
+ }
+
+ static createRenderRoot(host) {
+ return host.attachShadow({ mode: 'open', delegatesFocus: true });
+ }
+
+ // TODO: This feels awkward to keep internals… internal. We need access to
+ // this in callbacks so it’s not currently feasible to make it private on the
+ // “host” instance.
+ static #getInternals(host) {
+ return FormControl.#internalsMap.get(host);
+ }
+
+ static get properties() {
+ return {
+ // Public interface (see also getters / setters below)
+ name: {
+ type: String,
+ reflect: true,
+ },
+ required: {
+ type: Boolean,
+ reflect: true,
+ },
+ value: {
+ type: String,
+ reflect: true,
+ // TODO: Setting the default to "''" here ensures that validation will
+ // be hit. However, this has a weird side-effect of immediately marking
+ // the field as “:invalid” — which is typically not what users will
+ // expect. Not sure if we’re missing something from the spec still…
+ default: '',
+ observe: (host, value) => {
+ const input = host.shadowRoot.getElementById('input');
+ const internals = FormControl.#getInternals(host);
+ internals.setFormValue(value);
+ // TODO: This binding within the observer feels a little awkward. It
+ // would break if we property-bound with a “live” updater though.
+ input.value = value;
+ FormControl.validate(host);
+ },
+ },
+
+ // Internal interface
+ emoji: {
+ type: String,
+ internal: true,
+ input: ['value'],
+ compute: value => {
+ if (value) {
+ const codePoint = data[value];
+ if (codePoint) {
+ return String.fromCodePoint(...codePoint);
+ }
+ }
+ },
+ },
+ matches: {
+ type: Array,
+ internal: true,
+ default: () => [],
+ },
+ };
+ }
+
+ static get listeners() {
+ return {
+ input: (host) => {
+ this.input(host);
+ },
+ change: (host, event) => {
+ host.value = event.target.value;
+ this.change(host);
+ },
+ click: (host, event) => {
+ if (event.target.dataset.value) {
+ const input = host.shadowRoot.getElementById('input');
+ host.value = event.target.dataset.value;
+ input.value = host.value;
+ this.match(host);
+ this.change(host);
+ input.focus();
+ }
+ },
+ keydown: (host, event) => {
+ if (event.key === 'ArrowDown') {
+ event.preventDefault();
+ const input = host.shadowRoot.getElementById('input');
+ const matches = host.shadowRoot.getElementById('matches');
+ const activeElement = host.shadowRoot.activeElement;
+ if (activeElement === input) {
+ matches.firstElementChild?.focus();
+ } else if (matches.contains(activeElement)) {
+ activeElement.nextElementSibling?.focus();
+ }
+ } else if (event.key === 'ArrowUp') {
+ event.preventDefault();
+ const input = host.shadowRoot.getElementById('input');
+ const matches = host.shadowRoot.getElementById('matches');
+ const activeElement = host.shadowRoot.activeElement;
+ if (matches.contains(activeElement)) {
+ const previousElementSibling = activeElement.previousElementSibling;
+ if (previousElementSibling) {
+ previousElementSibling.focus();
+ } else {
+ input.focus();
+ }
+ }
+ } else if (event.key === 'Enter') {
+ // TODO: Inputs typically submit when you hit enter. Not sure that
+ // there is a way to control that from the element itself.
+ const input = host.shadowRoot.getElementById('input');
+ input.blur();
+ }
+ },
+ };
+ }
+
+ static template(html) {
+ return ({ emoji, matches }) => {
+ return html`
+
+
${emoji}
+
+
+ ${matches.map(match => {
+ return html`
+
+ ${match.emoji} ${match.value}
+
+ `;
+ })}
+
(no matches)
+
+
+
+ `;
+ };
+ }
+
+ static match(host) {
+ const substring = host.shadowRoot.getElementById('input').value;
+ if (substring) {
+ host.internal.matches = entries
+ .filter(([value]) => value.includes(substring))
+ .slice(0, 100)
+ .map(([value, codePoint]) => ({ value, emoji: String.fromCodePoint(...codePoint) }));
+ } else {
+ host.internal.matches = entries
+ .slice(0, 100)
+ .map(([value, codePoint]) => ({ value, emoji: String.fromCodePoint(...codePoint) }));
+ }
+ }
+
+ static input(host) {
+ this.match(host);
+ const eventType = 'input';
+ const eventData = { bubbles: true };
+ host.dispatchEvent(new CustomEvent(eventType, eventData));
+ }
+
+ static change(host) {
+ const eventType = 'change';
+ const eventData = { bubbles: true };
+ host.dispatchEvent(new CustomEvent(eventType, eventData));
+ }
+
+ static validate(host) {
+ const input = host.shadowRoot.getElementById('input');
+ const internals = FormControl.#getInternals(host);
+ const valueOk = !!data[host.value];
+ const hasValue = !!host.value;
+ const required = host.required;
+ if (!required && !hasValue || valueOk) {
+ internals.setValidity({
+ valueMissing: false,
+ customError: false,
+ });
+ } else if (required && !hasValue) {
+ internals.setValidity({
+ valueMissing: true,
+ customError: false,
+ }, 'Please enter an emoji.', input);
+ } else {
+ internals.setValidity({
+ valueMissing: false,
+ customError: true,
+ }, 'Unrecognized emoji.', input);
+ }
+ }
+
+ connectedCallback() {
+ // TODO: This is awkward to need to initialize ahead of the connected
+ // callback. We do this to satisfy the observe callback for our value.
+ if (!FormControl.#getInternals(this)) {
+ // Initialize the form control.
+ FormControl.#internalsMap.set(this, this.attachInternals());
+ }
+ super.connectedCallback();
+ FormControl.match(this);
+ }
+
+ formAssociatedCallback(/*form*/) {
+ // TODO: Consider adding this lifecycle function to the base class.
+ // super.formAssociatedCallback(form);
+ }
+
+ formDisabledCallback(/*disabled*/) {
+ // TODO: Consider adding this lifecycle function to the base class.
+ // super.formDisabledCallback(disabled);
+ }
+
+ formResetCallback() {
+ // TODO: Consider adding this lifecycle function to the base class.
+ // super.formResetCallback();
+ }
+
+ formStateRestoreCallback(/*state, mode*/) {
+ // TODO: Consider adding this lifecycle function to the base class.
+ // super.formStateRestoreCallback(state, mode);
+ }
+
+ get form() {
+ const internals = FormControl.#getInternals(this);
+ return internals.form;
+ }
+
+ get type() {
+ return this.localName;
+ }
+
+ get validity() {
+ const internals = FormControl.#getInternals(this);
+ return internals.validity;
+ }
+
+ get validationMessage() {
+ const internals = FormControl.#getInternals(this);
+ return internals.validationMessage;
+ }
+
+ get willValidate() {
+ const internals = FormControl.#getInternals(this);
+ return internals.willValidate;
+ }
+
+ checkValidity() {
+ const internals = FormControl.#getInternals(this);
+ return internals.checkValidity();
+ }
+
+ reportValidity() {
+ const internals = FormControl.#getInternals(this);
+ return internals.reportValidity();
+ }
+}
+
+customElements.define('form-control', FormControl);
diff --git a/demo/form/form-control.json b/demo/form/form-control.json
new file mode 100644
index 0000000..4fbe0b0
--- /dev/null
+++ b/demo/form/form-control.json
@@ -0,0 +1,1570 @@
+{
+ "hash": ["0x0023", "0xFE0F", "0x20E3"],
+ "keycap_star": ["0x002A", "0xFE0F", "0x20E3"],
+ "zero": ["0x0030", "0xFE0F", "0x20E3"],
+ "one": ["0x0031", "0xFE0F", "0x20E3"],
+ "two": ["0x0032", "0xFE0F", "0x20E3"],
+ "three": ["0x0033", "0xFE0F", "0x20E3"],
+ "four": ["0x0034", "0xFE0F", "0x20E3"],
+ "five": ["0x0035", "0xFE0F", "0x20E3"],
+ "six": ["0x0036", "0xFE0F", "0x20E3"],
+ "seven": ["0x0037", "0xFE0F", "0x20E3"],
+ "eight": ["0x0038", "0xFE0F", "0x20E3"],
+ "nine": ["0x0039", "0xFE0F", "0x20E3"],
+ "copyright": ["0x00A9", "0xFE0F"],
+ "registered": ["0x00AE", "0xFE0F"],
+ "mahjong": ["0x1F004"],
+ "black_joker": ["0x1F0CF"],
+ "a": ["0x1F170", "0xFE0F"],
+ "b": ["0x1F171", "0xFE0F"],
+ "o2": ["0x1F17E", "0xFE0F"],
+ "parking": ["0x1F17F", "0xFE0F"],
+ "ab": ["0x1F18E"],
+ "cl": ["0x1F191"],
+ "cool": ["0x1F192"],
+ "free": ["0x1F193"],
+ "id": ["0x1F194"],
+ "new": ["0x1F195"],
+ "ng": ["0x1F196"],
+ "ok": ["0x1F197"],
+ "sos": ["0x1F198"],
+ "up": ["0x1F199"],
+ "vs": ["0x1F19A"],
+ "flag-ac": ["0x1F1E6", "0x1F1E8"],
+ "flag-ad": ["0x1F1E6", "0x1F1E9"],
+ "flag-ae": ["0x1F1E6", "0x1F1EA"],
+ "flag-af": ["0x1F1E6", "0x1F1EB"],
+ "flag-ag": ["0x1F1E6", "0x1F1EC"],
+ "flag-ai": ["0x1F1E6", "0x1F1EE"],
+ "flag-al": ["0x1F1E6", "0x1F1F1"],
+ "flag-am": ["0x1F1E6", "0x1F1F2"],
+ "flag-ao": ["0x1F1E6", "0x1F1F4"],
+ "flag-aq": ["0x1F1E6", "0x1F1F6"],
+ "flag-ar": ["0x1F1E6", "0x1F1F7"],
+ "flag-as": ["0x1F1E6", "0x1F1F8"],
+ "flag-at": ["0x1F1E6", "0x1F1F9"],
+ "flag-au": ["0x1F1E6", "0x1F1FA"],
+ "flag-aw": ["0x1F1E6", "0x1F1FC"],
+ "flag-ax": ["0x1F1E6", "0x1F1FD"],
+ "flag-az": ["0x1F1E6", "0x1F1FF"],
+ "flag-ba": ["0x1F1E7", "0x1F1E6"],
+ "flag-bb": ["0x1F1E7", "0x1F1E7"],
+ "flag-bd": ["0x1F1E7", "0x1F1E9"],
+ "flag-be": ["0x1F1E7", "0x1F1EA"],
+ "flag-bf": ["0x1F1E7", "0x1F1EB"],
+ "flag-bg": ["0x1F1E7", "0x1F1EC"],
+ "flag-bh": ["0x1F1E7", "0x1F1ED"],
+ "flag-bi": ["0x1F1E7", "0x1F1EE"],
+ "flag-bj": ["0x1F1E7", "0x1F1EF"],
+ "flag-bl": ["0x1F1E7", "0x1F1F1"],
+ "flag-bm": ["0x1F1E7", "0x1F1F2"],
+ "flag-bn": ["0x1F1E7", "0x1F1F3"],
+ "flag-bo": ["0x1F1E7", "0x1F1F4"],
+ "flag-bq": ["0x1F1E7", "0x1F1F6"],
+ "flag-br": ["0x1F1E7", "0x1F1F7"],
+ "flag-bs": ["0x1F1E7", "0x1F1F8"],
+ "flag-bt": ["0x1F1E7", "0x1F1F9"],
+ "flag-bv": ["0x1F1E7", "0x1F1FB"],
+ "flag-bw": ["0x1F1E7", "0x1F1FC"],
+ "flag-by": ["0x1F1E7", "0x1F1FE"],
+ "flag-bz": ["0x1F1E7", "0x1F1FF"],
+ "flag-ca": ["0x1F1E8", "0x1F1E6"],
+ "flag-cc": ["0x1F1E8", "0x1F1E8"],
+ "flag-cd": ["0x1F1E8", "0x1F1E9"],
+ "flag-cf": ["0x1F1E8", "0x1F1EB"],
+ "flag-cg": ["0x1F1E8", "0x1F1EC"],
+ "flag-ch": ["0x1F1E8", "0x1F1ED"],
+ "flag-ci": ["0x1F1E8", "0x1F1EE"],
+ "flag-ck": ["0x1F1E8", "0x1F1F0"],
+ "flag-cl": ["0x1F1E8", "0x1F1F1"],
+ "flag-cm": ["0x1F1E8", "0x1F1F2"],
+ "cn": ["0x1F1E8", "0x1F1F3"],
+ "flag-co": ["0x1F1E8", "0x1F1F4"],
+ "flag-cp": ["0x1F1E8", "0x1F1F5"],
+ "flag-cr": ["0x1F1E8", "0x1F1F7"],
+ "flag-cu": ["0x1F1E8", "0x1F1FA"],
+ "flag-cv": ["0x1F1E8", "0x1F1FB"],
+ "flag-cw": ["0x1F1E8", "0x1F1FC"],
+ "flag-cx": ["0x1F1E8", "0x1F1FD"],
+ "flag-cy": ["0x1F1E8", "0x1F1FE"],
+ "flag-cz": ["0x1F1E8", "0x1F1FF"],
+ "de": ["0x1F1E9", "0x1F1EA"],
+ "flag-dg": ["0x1F1E9", "0x1F1EC"],
+ "flag-dj": ["0x1F1E9", "0x1F1EF"],
+ "flag-dk": ["0x1F1E9", "0x1F1F0"],
+ "flag-dm": ["0x1F1E9", "0x1F1F2"],
+ "flag-do": ["0x1F1E9", "0x1F1F4"],
+ "flag-dz": ["0x1F1E9", "0x1F1FF"],
+ "flag-ea": ["0x1F1EA", "0x1F1E6"],
+ "flag-ec": ["0x1F1EA", "0x1F1E8"],
+ "flag-ee": ["0x1F1EA", "0x1F1EA"],
+ "flag-eg": ["0x1F1EA", "0x1F1EC"],
+ "flag-eh": ["0x1F1EA", "0x1F1ED"],
+ "flag-er": ["0x1F1EA", "0x1F1F7"],
+ "es": ["0x1F1EA", "0x1F1F8"],
+ "flag-et": ["0x1F1EA", "0x1F1F9"],
+ "flag-eu": ["0x1F1EA", "0x1F1FA"],
+ "flag-fi": ["0x1F1EB", "0x1F1EE"],
+ "flag-fj": ["0x1F1EB", "0x1F1EF"],
+ "flag-fk": ["0x1F1EB", "0x1F1F0"],
+ "flag-fm": ["0x1F1EB", "0x1F1F2"],
+ "flag-fo": ["0x1F1EB", "0x1F1F4"],
+ "fr": ["0x1F1EB", "0x1F1F7"],
+ "flag-ga": ["0x1F1EC", "0x1F1E6"],
+ "gb": ["0x1F1EC", "0x1F1E7"],
+ "flag-gd": ["0x1F1EC", "0x1F1E9"],
+ "flag-ge": ["0x1F1EC", "0x1F1EA"],
+ "flag-gf": ["0x1F1EC", "0x1F1EB"],
+ "flag-gg": ["0x1F1EC", "0x1F1EC"],
+ "flag-gh": ["0x1F1EC", "0x1F1ED"],
+ "flag-gi": ["0x1F1EC", "0x1F1EE"],
+ "flag-gl": ["0x1F1EC", "0x1F1F1"],
+ "flag-gm": ["0x1F1EC", "0x1F1F2"],
+ "flag-gn": ["0x1F1EC", "0x1F1F3"],
+ "flag-gp": ["0x1F1EC", "0x1F1F5"],
+ "flag-gq": ["0x1F1EC", "0x1F1F6"],
+ "flag-gr": ["0x1F1EC", "0x1F1F7"],
+ "flag-gs": ["0x1F1EC", "0x1F1F8"],
+ "flag-gt": ["0x1F1EC", "0x1F1F9"],
+ "flag-gu": ["0x1F1EC", "0x1F1FA"],
+ "flag-gw": ["0x1F1EC", "0x1F1FC"],
+ "flag-gy": ["0x1F1EC", "0x1F1FE"],
+ "flag-hk": ["0x1F1ED", "0x1F1F0"],
+ "flag-hm": ["0x1F1ED", "0x1F1F2"],
+ "flag-hn": ["0x1F1ED", "0x1F1F3"],
+ "flag-hr": ["0x1F1ED", "0x1F1F7"],
+ "flag-ht": ["0x1F1ED", "0x1F1F9"],
+ "flag-hu": ["0x1F1ED", "0x1F1FA"],
+ "flag-ic": ["0x1F1EE", "0x1F1E8"],
+ "flag-id": ["0x1F1EE", "0x1F1E9"],
+ "flag-ie": ["0x1F1EE", "0x1F1EA"],
+ "flag-il": ["0x1F1EE", "0x1F1F1"],
+ "flag-im": ["0x1F1EE", "0x1F1F2"],
+ "flag-in": ["0x1F1EE", "0x1F1F3"],
+ "flag-io": ["0x1F1EE", "0x1F1F4"],
+ "flag-iq": ["0x1F1EE", "0x1F1F6"],
+ "flag-ir": ["0x1F1EE", "0x1F1F7"],
+ "flag-is": ["0x1F1EE", "0x1F1F8"],
+ "it": ["0x1F1EE", "0x1F1F9"],
+ "flag-je": ["0x1F1EF", "0x1F1EA"],
+ "flag-jm": ["0x1F1EF", "0x1F1F2"],
+ "flag-jo": ["0x1F1EF", "0x1F1F4"],
+ "jp": ["0x1F1EF", "0x1F1F5"],
+ "flag-ke": ["0x1F1F0", "0x1F1EA"],
+ "flag-kg": ["0x1F1F0", "0x1F1EC"],
+ "flag-kh": ["0x1F1F0", "0x1F1ED"],
+ "flag-ki": ["0x1F1F0", "0x1F1EE"],
+ "flag-km": ["0x1F1F0", "0x1F1F2"],
+ "flag-kn": ["0x1F1F0", "0x1F1F3"],
+ "flag-kp": ["0x1F1F0", "0x1F1F5"],
+ "kr": ["0x1F1F0", "0x1F1F7"],
+ "flag-kw": ["0x1F1F0", "0x1F1FC"],
+ "flag-ky": ["0x1F1F0", "0x1F1FE"],
+ "flag-kz": ["0x1F1F0", "0x1F1FF"],
+ "flag-la": ["0x1F1F1", "0x1F1E6"],
+ "flag-lb": ["0x1F1F1", "0x1F1E7"],
+ "flag-lc": ["0x1F1F1", "0x1F1E8"],
+ "flag-li": ["0x1F1F1", "0x1F1EE"],
+ "flag-lk": ["0x1F1F1", "0x1F1F0"],
+ "flag-lr": ["0x1F1F1", "0x1F1F7"],
+ "flag-ls": ["0x1F1F1", "0x1F1F8"],
+ "flag-lt": ["0x1F1F1", "0x1F1F9"],
+ "flag-lu": ["0x1F1F1", "0x1F1FA"],
+ "flag-lv": ["0x1F1F1", "0x1F1FB"],
+ "flag-ly": ["0x1F1F1", "0x1F1FE"],
+ "flag-ma": ["0x1F1F2", "0x1F1E6"],
+ "flag-mc": ["0x1F1F2", "0x1F1E8"],
+ "flag-md": ["0x1F1F2", "0x1F1E9"],
+ "flag-me": ["0x1F1F2", "0x1F1EA"],
+ "flag-mf": ["0x1F1F2", "0x1F1EB"],
+ "flag-mg": ["0x1F1F2", "0x1F1EC"],
+ "flag-mh": ["0x1F1F2", "0x1F1ED"],
+ "flag-mk": ["0x1F1F2", "0x1F1F0"],
+ "flag-ml": ["0x1F1F2", "0x1F1F1"],
+ "flag-mm": ["0x1F1F2", "0x1F1F2"],
+ "flag-mn": ["0x1F1F2", "0x1F1F3"],
+ "flag-mo": ["0x1F1F2", "0x1F1F4"],
+ "flag-mp": ["0x1F1F2", "0x1F1F5"],
+ "flag-mq": ["0x1F1F2", "0x1F1F6"],
+ "flag-mr": ["0x1F1F2", "0x1F1F7"],
+ "flag-ms": ["0x1F1F2", "0x1F1F8"],
+ "flag-mt": ["0x1F1F2", "0x1F1F9"],
+ "flag-mu": ["0x1F1F2", "0x1F1FA"],
+ "flag-mv": ["0x1F1F2", "0x1F1FB"],
+ "flag-mw": ["0x1F1F2", "0x1F1FC"],
+ "flag-mx": ["0x1F1F2", "0x1F1FD"],
+ "flag-my": ["0x1F1F2", "0x1F1FE"],
+ "flag-mz": ["0x1F1F2", "0x1F1FF"],
+ "flag-na": ["0x1F1F3", "0x1F1E6"],
+ "flag-nc": ["0x1F1F3", "0x1F1E8"],
+ "flag-ne": ["0x1F1F3", "0x1F1EA"],
+ "flag-nf": ["0x1F1F3", "0x1F1EB"],
+ "flag-ng": ["0x1F1F3", "0x1F1EC"],
+ "flag-ni": ["0x1F1F3", "0x1F1EE"],
+ "flag-nl": ["0x1F1F3", "0x1F1F1"],
+ "flag-no": ["0x1F1F3", "0x1F1F4"],
+ "flag-np": ["0x1F1F3", "0x1F1F5"],
+ "flag-nr": ["0x1F1F3", "0x1F1F7"],
+ "flag-nu": ["0x1F1F3", "0x1F1FA"],
+ "flag-nz": ["0x1F1F3", "0x1F1FF"],
+ "flag-om": ["0x1F1F4", "0x1F1F2"],
+ "flag-pa": ["0x1F1F5", "0x1F1E6"],
+ "flag-pe": ["0x1F1F5", "0x1F1EA"],
+ "flag-pf": ["0x1F1F5", "0x1F1EB"],
+ "flag-pg": ["0x1F1F5", "0x1F1EC"],
+ "flag-ph": ["0x1F1F5", "0x1F1ED"],
+ "flag-pk": ["0x1F1F5", "0x1F1F0"],
+ "flag-pl": ["0x1F1F5", "0x1F1F1"],
+ "flag-pm": ["0x1F1F5", "0x1F1F2"],
+ "flag-pn": ["0x1F1F5", "0x1F1F3"],
+ "flag-pr": ["0x1F1F5", "0x1F1F7"],
+ "flag-ps": ["0x1F1F5", "0x1F1F8"],
+ "flag-pt": ["0x1F1F5", "0x1F1F9"],
+ "flag-pw": ["0x1F1F5", "0x1F1FC"],
+ "flag-py": ["0x1F1F5", "0x1F1FE"],
+ "flag-qa": ["0x1F1F6", "0x1F1E6"],
+ "flag-re": ["0x1F1F7", "0x1F1EA"],
+ "flag-ro": ["0x1F1F7", "0x1F1F4"],
+ "flag-rs": ["0x1F1F7", "0x1F1F8"],
+ "ru": ["0x1F1F7", "0x1F1FA"],
+ "flag-rw": ["0x1F1F7", "0x1F1FC"],
+ "flag-sa": ["0x1F1F8", "0x1F1E6"],
+ "flag-sb": ["0x1F1F8", "0x1F1E7"],
+ "flag-sc": ["0x1F1F8", "0x1F1E8"],
+ "flag-sd": ["0x1F1F8", "0x1F1E9"],
+ "flag-se": ["0x1F1F8", "0x1F1EA"],
+ "flag-sg": ["0x1F1F8", "0x1F1EC"],
+ "flag-sh": ["0x1F1F8", "0x1F1ED"],
+ "flag-si": ["0x1F1F8", "0x1F1EE"],
+ "flag-sj": ["0x1F1F8", "0x1F1EF"],
+ "flag-sk": ["0x1F1F8", "0x1F1F0"],
+ "flag-sl": ["0x1F1F8", "0x1F1F1"],
+ "flag-sm": ["0x1F1F8", "0x1F1F2"],
+ "flag-sn": ["0x1F1F8", "0x1F1F3"],
+ "flag-so": ["0x1F1F8", "0x1F1F4"],
+ "flag-sr": ["0x1F1F8", "0x1F1F7"],
+ "flag-ss": ["0x1F1F8", "0x1F1F8"],
+ "flag-st": ["0x1F1F8", "0x1F1F9"],
+ "flag-sv": ["0x1F1F8", "0x1F1FB"],
+ "flag-sx": ["0x1F1F8", "0x1F1FD"],
+ "flag-sy": ["0x1F1F8", "0x1F1FE"],
+ "flag-sz": ["0x1F1F8", "0x1F1FF"],
+ "flag-ta": ["0x1F1F9", "0x1F1E6"],
+ "flag-tc": ["0x1F1F9", "0x1F1E8"],
+ "flag-td": ["0x1F1F9", "0x1F1E9"],
+ "flag-tf": ["0x1F1F9", "0x1F1EB"],
+ "flag-tg": ["0x1F1F9", "0x1F1EC"],
+ "flag-th": ["0x1F1F9", "0x1F1ED"],
+ "flag-tj": ["0x1F1F9", "0x1F1EF"],
+ "flag-tk": ["0x1F1F9", "0x1F1F0"],
+ "flag-tl": ["0x1F1F9", "0x1F1F1"],
+ "flag-tm": ["0x1F1F9", "0x1F1F2"],
+ "flag-tn": ["0x1F1F9", "0x1F1F3"],
+ "flag-to": ["0x1F1F9", "0x1F1F4"],
+ "flag-tr": ["0x1F1F9", "0x1F1F7"],
+ "flag-tt": ["0x1F1F9", "0x1F1F9"],
+ "flag-tv": ["0x1F1F9", "0x1F1FB"],
+ "flag-tw": ["0x1F1F9", "0x1F1FC"],
+ "flag-tz": ["0x1F1F9", "0x1F1FF"],
+ "flag-ua": ["0x1F1FA", "0x1F1E6"],
+ "flag-ug": ["0x1F1FA", "0x1F1EC"],
+ "flag-um": ["0x1F1FA", "0x1F1F2"],
+ "flag-un": ["0x1F1FA", "0x1F1F3"],
+ "us": ["0x1F1FA", "0x1F1F8"],
+ "flag-uy": ["0x1F1FA", "0x1F1FE"],
+ "flag-uz": ["0x1F1FA", "0x1F1FF"],
+ "flag-va": ["0x1F1FB", "0x1F1E6"],
+ "flag-vc": ["0x1F1FB", "0x1F1E8"],
+ "flag-ve": ["0x1F1FB", "0x1F1EA"],
+ "flag-vg": ["0x1F1FB", "0x1F1EC"],
+ "flag-vi": ["0x1F1FB", "0x1F1EE"],
+ "flag-vn": ["0x1F1FB", "0x1F1F3"],
+ "flag-vu": ["0x1F1FB", "0x1F1FA"],
+ "flag-wf": ["0x1F1FC", "0x1F1EB"],
+ "flag-ws": ["0x1F1FC", "0x1F1F8"],
+ "flag-xk": ["0x1F1FD", "0x1F1F0"],
+ "flag-ye": ["0x1F1FE", "0x1F1EA"],
+ "flag-yt": ["0x1F1FE", "0x1F1F9"],
+ "flag-za": ["0x1F1FF", "0x1F1E6"],
+ "flag-zm": ["0x1F1FF", "0x1F1F2"],
+ "flag-zw": ["0x1F1FF", "0x1F1FC"],
+ "koko": ["0x1F201"],
+ "sa": ["0x1F202", "0xFE0F"],
+ "u7121": ["0x1F21A"],
+ "u6307": ["0x1F22F"],
+ "u7981": ["0x1F232"],
+ "u7a7a": ["0x1F233"],
+ "u5408": ["0x1F234"],
+ "u6e80": ["0x1F235"],
+ "u6709": ["0x1F236"],
+ "u6708": ["0x1F237", "0xFE0F"],
+ "u7533": ["0x1F238"],
+ "u5272": ["0x1F239"],
+ "u55b6": ["0x1F23A"],
+ "ideograph_advantage": ["0x1F250"],
+ "accept": ["0x1F251"],
+ "cyclone": ["0x1F300"],
+ "foggy": ["0x1F301"],
+ "closed_umbrella": ["0x1F302"],
+ "night_with_stars": ["0x1F303"],
+ "sunrise_over_mountains": ["0x1F304"],
+ "sunrise": ["0x1F305"],
+ "city_sunset": ["0x1F306"],
+ "city_sunrise": ["0x1F307"],
+ "rainbow": ["0x1F308"],
+ "bridge_at_night": ["0x1F309"],
+ "ocean": ["0x1F30A"],
+ "volcano": ["0x1F30B"],
+ "milky_way": ["0x1F30C"],
+ "earth_africa": ["0x1F30D"],
+ "earth_americas": ["0x1F30E"],
+ "earth_asia": ["0x1F30F"],
+ "globe_with_meridians": ["0x1F310"],
+ "new_moon": ["0x1F311"],
+ "waxing_crescent_moon": ["0x1F312"],
+ "first_quarter_moon": ["0x1F313"],
+ "moon": ["0x1F314"],
+ "full_moon": ["0x1F315"],
+ "waning_gibbous_moon": ["0x1F316"],
+ "last_quarter_moon": ["0x1F317"],
+ "waning_crescent_moon": ["0x1F318"],
+ "crescent_moon": ["0x1F319"],
+ "new_moon_with_face": ["0x1F31A"],
+ "first_quarter_moon_with_face": ["0x1F31B"],
+ "last_quarter_moon_with_face": ["0x1F31C"],
+ "full_moon_with_face": ["0x1F31D"],
+ "sun_with_face": ["0x1F31E"],
+ "star2": ["0x1F31F"],
+ "stars": ["0x1F320"],
+ "thermometer": ["0x1F321", "0xFE0F"],
+ "mostly_sunny": ["0x1F324", "0xFE0F"],
+ "barely_sunny": ["0x1F325", "0xFE0F"],
+ "partly_sunny_rain": ["0x1F326", "0xFE0F"],
+ "rain_cloud": ["0x1F327", "0xFE0F"],
+ "snow_cloud": ["0x1F328", "0xFE0F"],
+ "lightning": ["0x1F329", "0xFE0F"],
+ "tornado": ["0x1F32A", "0xFE0F"],
+ "fog": ["0x1F32B", "0xFE0F"],
+ "wind_blowing_face": ["0x1F32C", "0xFE0F"],
+ "hotdog": ["0x1F32D"],
+ "taco": ["0x1F32E"],
+ "burrito": ["0x1F32F"],
+ "chestnut": ["0x1F330"],
+ "seedling": ["0x1F331"],
+ "evergreen_tree": ["0x1F332"],
+ "deciduous_tree": ["0x1F333"],
+ "palm_tree": ["0x1F334"],
+ "cactus": ["0x1F335"],
+ "hot_pepper": ["0x1F336", "0xFE0F"],
+ "tulip": ["0x1F337"],
+ "cherry_blossom": ["0x1F338"],
+ "rose": ["0x1F339"],
+ "hibiscus": ["0x1F33A"],
+ "sunflower": ["0x1F33B"],
+ "blossom": ["0x1F33C"],
+ "corn": ["0x1F33D"],
+ "ear_of_rice": ["0x1F33E"],
+ "herb": ["0x1F33F"],
+ "four_leaf_clover": ["0x1F340"],
+ "maple_leaf": ["0x1F341"],
+ "fallen_leaf": ["0x1F342"],
+ "leaves": ["0x1F343"],
+ "mushroom": ["0x1F344"],
+ "tomato": ["0x1F345"],
+ "eggplant": ["0x1F346"],
+ "grapes": ["0x1F347"],
+ "melon": ["0x1F348"],
+ "watermelon": ["0x1F349"],
+ "tangerine": ["0x1F34A"],
+ "lemon": ["0x1F34B"],
+ "banana": ["0x1F34C"],
+ "pineapple": ["0x1F34D"],
+ "apple": ["0x1F34E"],
+ "green_apple": ["0x1F34F"],
+ "pear": ["0x1F350"],
+ "peach": ["0x1F351"],
+ "cherries": ["0x1F352"],
+ "strawberry": ["0x1F353"],
+ "hamburger": ["0x1F354"],
+ "pizza": ["0x1F355"],
+ "meat_on_bone": ["0x1F356"],
+ "poultry_leg": ["0x1F357"],
+ "rice_cracker": ["0x1F358"],
+ "rice_ball": ["0x1F359"],
+ "rice": ["0x1F35A"],
+ "curry": ["0x1F35B"],
+ "ramen": ["0x1F35C"],
+ "spaghetti": ["0x1F35D"],
+ "bread": ["0x1F35E"],
+ "fries": ["0x1F35F"],
+ "sweet_potato": ["0x1F360"],
+ "dango": ["0x1F361"],
+ "oden": ["0x1F362"],
+ "sushi": ["0x1F363"],
+ "fried_shrimp": ["0x1F364"],
+ "fish_cake": ["0x1F365"],
+ "icecream": ["0x1F366"],
+ "shaved_ice": ["0x1F367"],
+ "ice_cream": ["0x1F368"],
+ "doughnut": ["0x1F369"],
+ "cookie": ["0x1F36A"],
+ "chocolate_bar": ["0x1F36B"],
+ "candy": ["0x1F36C"],
+ "lollipop": ["0x1F36D"],
+ "custard": ["0x1F36E"],
+ "honey_pot": ["0x1F36F"],
+ "cake": ["0x1F370"],
+ "bento": ["0x1F371"],
+ "stew": ["0x1F372"],
+ "fried_egg": ["0x1F373"],
+ "fork_and_knife": ["0x1F374"],
+ "tea": ["0x1F375"],
+ "sake": ["0x1F376"],
+ "wine_glass": ["0x1F377"],
+ "cocktail": ["0x1F378"],
+ "tropical_drink": ["0x1F379"],
+ "beer": ["0x1F37A"],
+ "beers": ["0x1F37B"],
+ "baby_bottle": ["0x1F37C"],
+ "knife_fork_plate": ["0x1F37D", "0xFE0F"],
+ "champagne": ["0x1F37E"],
+ "popcorn": ["0x1F37F"],
+ "ribbon": ["0x1F380"],
+ "gift": ["0x1F381"],
+ "birthday": ["0x1F382"],
+ "jack_o_lantern": ["0x1F383"],
+ "christmas_tree": ["0x1F384"],
+ "santa": ["0x1F385"],
+ "fireworks": ["0x1F386"],
+ "sparkler": ["0x1F387"],
+ "balloon": ["0x1F388"],
+ "tada": ["0x1F389"],
+ "confetti_ball": ["0x1F38A"],
+ "tanabata_tree": ["0x1F38B"],
+ "crossed_flags": ["0x1F38C"],
+ "bamboo": ["0x1F38D"],
+ "dolls": ["0x1F38E"],
+ "flags": ["0x1F38F"],
+ "wind_chime": ["0x1F390"],
+ "rice_scene": ["0x1F391"],
+ "school_satchel": ["0x1F392"],
+ "mortar_board": ["0x1F393"],
+ "medal": ["0x1F396", "0xFE0F"],
+ "reminder_ribbon": ["0x1F397", "0xFE0F"],
+ "studio_microphone": ["0x1F399", "0xFE0F"],
+ "level_slider": ["0x1F39A", "0xFE0F"],
+ "control_knobs": ["0x1F39B", "0xFE0F"],
+ "film_frames": ["0x1F39E", "0xFE0F"],
+ "admission_tickets": ["0x1F39F", "0xFE0F"],
+ "carousel_horse": ["0x1F3A0"],
+ "ferris_wheel": ["0x1F3A1"],
+ "roller_coaster": ["0x1F3A2"],
+ "fishing_pole_and_fish": ["0x1F3A3"],
+ "microphone": ["0x1F3A4"],
+ "movie_camera": ["0x1F3A5"],
+ "cinema": ["0x1F3A6"],
+ "headphones": ["0x1F3A7"],
+ "art": ["0x1F3A8"],
+ "tophat": ["0x1F3A9"],
+ "circus_tent": ["0x1F3AA"],
+ "ticket": ["0x1F3AB"],
+ "clapper": ["0x1F3AC"],
+ "performing_arts": ["0x1F3AD"],
+ "video_game": ["0x1F3AE"],
+ "dart": ["0x1F3AF"],
+ "slot_machine": ["0x1F3B0"],
+ "8ball": ["0x1F3B1"],
+ "game_die": ["0x1F3B2"],
+ "bowling": ["0x1F3B3"],
+ "flower_playing_cards": ["0x1F3B4"],
+ "musical_note": ["0x1F3B5"],
+ "notes": ["0x1F3B6"],
+ "saxophone": ["0x1F3B7"],
+ "guitar": ["0x1F3B8"],
+ "musical_keyboard": ["0x1F3B9"],
+ "trumpet": ["0x1F3BA"],
+ "violin": ["0x1F3BB"],
+ "musical_score": ["0x1F3BC"],
+ "running_shirt_with_sash": ["0x1F3BD"],
+ "tennis": ["0x1F3BE"],
+ "ski": ["0x1F3BF"],
+ "basketball": ["0x1F3C0"],
+ "checkered_flag": ["0x1F3C1"],
+ "snowboarder": ["0x1F3C2"],
+ "woman-running": ["0x1F3C3", "0x200D", "0x2640", "0xFE0F"],
+ "man-running": ["0x1F3C3", "0x200D", "0x2642", "0xFE0F"],
+ "runner": ["0x1F3C3"],
+ "woman-surfing": ["0x1F3C4", "0x200D", "0x2640", "0xFE0F"],
+ "man-surfing": ["0x1F3C4", "0x200D", "0x2642", "0xFE0F"],
+ "surfer": ["0x1F3C4"],
+ "sports_medal": ["0x1F3C5"],
+ "trophy": ["0x1F3C6"],
+ "horse_racing": ["0x1F3C7"],
+ "football": ["0x1F3C8"],
+ "rugby_football": ["0x1F3C9"],
+ "woman-swimming": ["0x1F3CA", "0x200D", "0x2640", "0xFE0F"],
+ "man-swimming": ["0x1F3CA", "0x200D", "0x2642", "0xFE0F"],
+ "swimmer": ["0x1F3CA"],
+ "woman-lifting-weights": ["0x1F3CB", "0xFE0F", "0x200D", "0x2640", "0xFE0F"],
+ "man-lifting-weights": ["0x1F3CB", "0xFE0F", "0x200D", "0x2642", "0xFE0F"],
+ "weight_lifter": ["0x1F3CB", "0xFE0F"],
+ "woman-golfing": ["0x1F3CC", "0xFE0F", "0x200D", "0x2640", "0xFE0F"],
+ "man-golfing": ["0x1F3CC", "0xFE0F", "0x200D", "0x2642", "0xFE0F"],
+ "golfer": ["0x1F3CC", "0xFE0F"],
+ "racing_motorcycle": ["0x1F3CD", "0xFE0F"],
+ "racing_car": ["0x1F3CE", "0xFE0F"],
+ "cricket_bat_and_ball": ["0x1F3CF"],
+ "volleyball": ["0x1F3D0"],
+ "field_hockey_stick_and_ball": ["0x1F3D1"],
+ "ice_hockey_stick_and_puck": ["0x1F3D2"],
+ "table_tennis_paddle_and_ball": ["0x1F3D3"],
+ "snow_capped_mountain": ["0x1F3D4", "0xFE0F"],
+ "camping": ["0x1F3D5", "0xFE0F"],
+ "beach_with_umbrella": ["0x1F3D6", "0xFE0F"],
+ "building_construction": ["0x1F3D7", "0xFE0F"],
+ "house_buildings": ["0x1F3D8", "0xFE0F"],
+ "cityscape": ["0x1F3D9", "0xFE0F"],
+ "derelict_house_building": ["0x1F3DA", "0xFE0F"],
+ "classical_building": ["0x1F3DB", "0xFE0F"],
+ "desert": ["0x1F3DC", "0xFE0F"],
+ "desert_island": ["0x1F3DD", "0xFE0F"],
+ "national_park": ["0x1F3DE", "0xFE0F"],
+ "stadium": ["0x1F3DF", "0xFE0F"],
+ "house": ["0x1F3E0"],
+ "house_with_garden": ["0x1F3E1"],
+ "office": ["0x1F3E2"],
+ "post_office": ["0x1F3E3"],
+ "european_post_office": ["0x1F3E4"],
+ "hospital": ["0x1F3E5"],
+ "bank": ["0x1F3E6"],
+ "atm": ["0x1F3E7"],
+ "hotel": ["0x1F3E8"],
+ "love_hotel": ["0x1F3E9"],
+ "convenience_store": ["0x1F3EA"],
+ "school": ["0x1F3EB"],
+ "department_store": ["0x1F3EC"],
+ "factory": ["0x1F3ED"],
+ "izakaya_lantern": ["0x1F3EE"],
+ "japanese_castle": ["0x1F3EF"],
+ "european_castle": ["0x1F3F0"],
+ "rainbow-flag": ["0x1F3F3", "0xFE0F", "0x200D", "0x1F308"],
+ "waving_white_flag": ["0x1F3F3", "0xFE0F"],
+ "flag-england": ["0x1F3F4", "0xE0067", "0xE0062", "0xE0065", "0xE006E", "0xE0067", "0xE007F"],
+ "flag-scotland": ["0x1F3F4", "0xE0067", "0xE0062", "0xE0073", "0xE0063", "0xE0074", "0xE007F"],
+ "flag-wales": ["0x1F3F4", "0xE0067", "0xE0062", "0xE0077", "0xE006C", "0xE0073", "0xE007F"],
+ "waving_black_flag": ["0x1F3F4"],
+ "rosette": ["0x1F3F5", "0xFE0F"],
+ "label": ["0x1F3F7", "0xFE0F"],
+ "badminton_racquet_and_shuttlecock": ["0x1F3F8"],
+ "bow_and_arrow": ["0x1F3F9"],
+ "amphora": ["0x1F3FA"],
+ "skin-tone-2": ["0x1F3FB"],
+ "skin-tone-3": ["0x1F3FC"],
+ "skin-tone-4": ["0x1F3FD"],
+ "skin-tone-5": ["0x1F3FE"],
+ "skin-tone-6": ["0x1F3FF"],
+ "rat": ["0x1F400"],
+ "mouse2": ["0x1F401"],
+ "ox": ["0x1F402"],
+ "water_buffalo": ["0x1F403"],
+ "cow2": ["0x1F404"],
+ "tiger2": ["0x1F405"],
+ "leopard": ["0x1F406"],
+ "rabbit2": ["0x1F407"],
+ "cat2": ["0x1F408"],
+ "dragon": ["0x1F409"],
+ "crocodile": ["0x1F40A"],
+ "whale2": ["0x1F40B"],
+ "snail": ["0x1F40C"],
+ "snake": ["0x1F40D"],
+ "racehorse": ["0x1F40E"],
+ "ram": ["0x1F40F"],
+ "goat": ["0x1F410"],
+ "sheep": ["0x1F411"],
+ "monkey": ["0x1F412"],
+ "rooster": ["0x1F413"],
+ "chicken": ["0x1F414"],
+ "dog2": ["0x1F415"],
+ "pig2": ["0x1F416"],
+ "boar": ["0x1F417"],
+ "elephant": ["0x1F418"],
+ "octopus": ["0x1F419"],
+ "shell": ["0x1F41A"],
+ "bug": ["0x1F41B"],
+ "ant": ["0x1F41C"],
+ "bee": ["0x1F41D"],
+ "beetle": ["0x1F41E"],
+ "fish": ["0x1F41F"],
+ "tropical_fish": ["0x1F420"],
+ "blowfish": ["0x1F421"],
+ "turtle": ["0x1F422"],
+ "hatching_chick": ["0x1F423"],
+ "baby_chick": ["0x1F424"],
+ "hatched_chick": ["0x1F425"],
+ "bird": ["0x1F426"],
+ "penguin": ["0x1F427"],
+ "koala": ["0x1F428"],
+ "poodle": ["0x1F429"],
+ "dromedary_camel": ["0x1F42A"],
+ "camel": ["0x1F42B"],
+ "dolphin": ["0x1F42C"],
+ "mouse": ["0x1F42D"],
+ "cow": ["0x1F42E"],
+ "tiger": ["0x1F42F"],
+ "rabbit": ["0x1F430"],
+ "cat": ["0x1F431"],
+ "dragon_face": ["0x1F432"],
+ "whale": ["0x1F433"],
+ "horse": ["0x1F434"],
+ "monkey_face": ["0x1F435"],
+ "dog": ["0x1F436"],
+ "pig": ["0x1F437"],
+ "frog": ["0x1F438"],
+ "hamster": ["0x1F439"],
+ "wolf": ["0x1F43A"],
+ "bear": ["0x1F43B"],
+ "panda_face": ["0x1F43C"],
+ "pig_nose": ["0x1F43D"],
+ "feet": ["0x1F43E"],
+ "chipmunk": ["0x1F43F", "0xFE0F"],
+ "eyes": ["0x1F440"],
+ "eye-in-speech-bubble": ["0x1F441", "0xFE0F", "0x200D", "0x1F5E8", "0xFE0F"],
+ "eye": ["0x1F441", "0xFE0F"],
+ "ear": ["0x1F442"],
+ "nose": ["0x1F443"],
+ "lips": ["0x1F444"],
+ "tongue": ["0x1F445"],
+ "point_up_2": ["0x1F446"],
+ "point_down": ["0x1F447"],
+ "point_left": ["0x1F448"],
+ "point_right": ["0x1F449"],
+ "facepunch": ["0x1F44A"],
+ "wave": ["0x1F44B"],
+ "ok_hand": ["0x1F44C"],
+ "+1": ["0x1F44D"],
+ "-1": ["0x1F44E"],
+ "clap": ["0x1F44F"],
+ "open_hands": ["0x1F450"],
+ "crown": ["0x1F451"],
+ "womans_hat": ["0x1F452"],
+ "eyeglasses": ["0x1F453"],
+ "necktie": ["0x1F454"],
+ "shirt": ["0x1F455"],
+ "jeans": ["0x1F456"],
+ "dress": ["0x1F457"],
+ "kimono": ["0x1F458"],
+ "bikini": ["0x1F459"],
+ "womans_clothes": ["0x1F45A"],
+ "purse": ["0x1F45B"],
+ "handbag": ["0x1F45C"],
+ "pouch": ["0x1F45D"],
+ "mans_shoe": ["0x1F45E"],
+ "athletic_shoe": ["0x1F45F"],
+ "high_heel": ["0x1F460"],
+ "sandal": ["0x1F461"],
+ "boot": ["0x1F462"],
+ "footprints": ["0x1F463"],
+ "bust_in_silhouette": ["0x1F464"],
+ "busts_in_silhouette": ["0x1F465"],
+ "boy": ["0x1F466"],
+ "girl": ["0x1F467"],
+ "male-farmer": ["0x1F468", "0x200D", "0x1F33E"],
+ "male-cook": ["0x1F468", "0x200D", "0x1F373"],
+ "male-student": ["0x1F468", "0x200D", "0x1F393"],
+ "male-singer": ["0x1F468", "0x200D", "0x1F3A4"],
+ "male-artist": ["0x1F468", "0x200D", "0x1F3A8"],
+ "male-teacher": ["0x1F468", "0x200D", "0x1F3EB"],
+ "male-factory-worker": ["0x1F468", "0x200D", "0x1F3ED"],
+ "man-boy-boy": ["0x1F468", "0x200D", "0x1F466", "0x200D", "0x1F466"],
+ "man-boy": ["0x1F468", "0x200D", "0x1F466"],
+ "man-girl-boy": ["0x1F468", "0x200D", "0x1F467", "0x200D", "0x1F466"],
+ "man-girl-girl": ["0x1F468", "0x200D", "0x1F467", "0x200D", "0x1F467"],
+ "man-girl": ["0x1F468", "0x200D", "0x1F467"],
+ "man-man-boy": ["0x1F468", "0x200D", "0x1F468", "0x200D", "0x1F466"],
+ "man-man-boy-boy": ["0x1F468", "0x200D", "0x1F468", "0x200D", "0x1F466", "0x200D", "0x1F466"],
+ "man-man-girl": ["0x1F468", "0x200D", "0x1F468", "0x200D", "0x1F467"],
+ "man-man-girl-boy": ["0x1F468", "0x200D", "0x1F468", "0x200D", "0x1F467", "0x200D", "0x1F466"],
+ "man-man-girl-girl": ["0x1F468", "0x200D", "0x1F468", "0x200D", "0x1F467", "0x200D", "0x1F467"],
+ "man-woman-boy": ["0x1F468", "0x200D", "0x1F469", "0x200D", "0x1F466"],
+ "man-woman-boy-boy": ["0x1F468", "0x200D", "0x1F469", "0x200D", "0x1F466", "0x200D", "0x1F466"],
+ "man-woman-girl": ["0x1F468", "0x200D", "0x1F469", "0x200D", "0x1F467"],
+ "man-woman-girl-boy": ["0x1F468", "0x200D", "0x1F469", "0x200D", "0x1F467", "0x200D", "0x1F466"],
+ "man-woman-girl-girl": ["0x1F468", "0x200D", "0x1F469", "0x200D", "0x1F467", "0x200D", "0x1F467"],
+ "male-technologist": ["0x1F468", "0x200D", "0x1F4BB"],
+ "male-office-worker": ["0x1F468", "0x200D", "0x1F4BC"],
+ "male-mechanic": ["0x1F468", "0x200D", "0x1F527"],
+ "male-scientist": ["0x1F468", "0x200D", "0x1F52C"],
+ "male-astronaut": ["0x1F468", "0x200D", "0x1F680"],
+ "male-firefighter": ["0x1F468", "0x200D", "0x1F692"],
+ "male-doctor": ["0x1F468", "0x200D", "0x2695", "0xFE0F"],
+ "male-judge": ["0x1F468", "0x200D", "0x2696", "0xFE0F"],
+ "male-pilot": ["0x1F468", "0x200D", "0x2708", "0xFE0F"],
+ "man-heart-man": ["0x1F468", "0x200D", "0x2764", "0xFE0F", "0x200D", "0x1F468"],
+ "man-kiss-man": ["0x1F468", "0x200D", "0x2764", "0xFE0F", "0x200D", "0x1F48B", "0x200D", "0x1F468"],
+ "man": ["0x1F468"],
+ "female-farmer": ["0x1F469", "0x200D", "0x1F33E"],
+ "female-cook": ["0x1F469", "0x200D", "0x1F373"],
+ "female-student": ["0x1F469", "0x200D", "0x1F393"],
+ "female-singer": ["0x1F469", "0x200D", "0x1F3A4"],
+ "female-artist": ["0x1F469", "0x200D", "0x1F3A8"],
+ "female-teacher": ["0x1F469", "0x200D", "0x1F3EB"],
+ "female-factory-worker": ["0x1F469", "0x200D", "0x1F3ED"],
+ "woman-boy-boy": ["0x1F469", "0x200D", "0x1F466", "0x200D", "0x1F466"],
+ "woman-boy": ["0x1F469", "0x200D", "0x1F466"],
+ "woman-girl-boy": ["0x1F469", "0x200D", "0x1F467", "0x200D", "0x1F466"],
+ "woman-girl-girl": ["0x1F469", "0x200D", "0x1F467", "0x200D", "0x1F467"],
+ "woman-girl": ["0x1F469", "0x200D", "0x1F467"],
+ "woman-woman-boy": ["0x1F469", "0x200D", "0x1F469", "0x200D", "0x1F466"],
+ "woman-woman-boy-boy": ["0x1F469", "0x200D", "0x1F469", "0x200D", "0x1F466", "0x200D", "0x1F466"],
+ "woman-woman-girl": ["0x1F469", "0x200D", "0x1F469", "0x200D", "0x1F467"],
+ "woman-woman-girl-boy": ["0x1F469", "0x200D", "0x1F469", "0x200D", "0x1F467", "0x200D", "0x1F466"],
+ "woman-woman-girl-girl": ["0x1F469", "0x200D", "0x1F469", "0x200D", "0x1F467", "0x200D", "0x1F467"],
+ "female-technologist": ["0x1F469", "0x200D", "0x1F4BB"],
+ "female-office-worker": ["0x1F469", "0x200D", "0x1F4BC"],
+ "female-mechanic": ["0x1F469", "0x200D", "0x1F527"],
+ "female-scientist": ["0x1F469", "0x200D", "0x1F52C"],
+ "female-astronaut": ["0x1F469", "0x200D", "0x1F680"],
+ "female-firefighter": ["0x1F469", "0x200D", "0x1F692"],
+ "female-doctor": ["0x1F469", "0x200D", "0x2695", "0xFE0F"],
+ "female-judge": ["0x1F469", "0x200D", "0x2696", "0xFE0F"],
+ "female-pilot": ["0x1F469", "0x200D", "0x2708", "0xFE0F"],
+ "woman-heart-man": ["0x1F469", "0x200D", "0x2764", "0xFE0F", "0x200D", "0x1F468"],
+ "woman-heart-woman": ["0x1F469", "0x200D", "0x2764", "0xFE0F", "0x200D", "0x1F469"],
+ "woman-kiss-man": ["0x1F469", "0x200D", "0x2764", "0xFE0F", "0x200D", "0x1F48B", "0x200D", "0x1F468"],
+ "woman-kiss-woman": ["0x1F469", "0x200D", "0x2764", "0xFE0F", "0x200D", "0x1F48B", "0x200D", "0x1F469"],
+ "woman": ["0x1F469"],
+ "family": ["0x1F46A"],
+ "couple": ["0x1F46B"],
+ "two_men_holding_hands": ["0x1F46C"],
+ "two_women_holding_hands": ["0x1F46D"],
+ "female-police-officer": ["0x1F46E", "0x200D", "0x2640", "0xFE0F"],
+ "male-police-officer": ["0x1F46E", "0x200D", "0x2642", "0xFE0F"],
+ "cop": ["0x1F46E"],
+ "woman-with-bunny-ears-partying": ["0x1F46F", "0x200D", "0x2640", "0xFE0F"],
+ "man-with-bunny-ears-partying": ["0x1F46F", "0x200D", "0x2642", "0xFE0F"],
+ "dancers": ["0x1F46F"],
+ "bride_with_veil": ["0x1F470"],
+ "blond-haired-woman": ["0x1F471", "0x200D", "0x2640", "0xFE0F"],
+ "blond-haired-man": ["0x1F471", "0x200D", "0x2642", "0xFE0F"],
+ "person_with_blond_hair": ["0x1F471"],
+ "man_with_gua_pi_mao": ["0x1F472"],
+ "woman-wearing-turban": ["0x1F473", "0x200D", "0x2640", "0xFE0F"],
+ "man-wearing-turban": ["0x1F473", "0x200D", "0x2642", "0xFE0F"],
+ "man_with_turban": ["0x1F473"],
+ "older_man": ["0x1F474"],
+ "older_woman": ["0x1F475"],
+ "baby": ["0x1F476"],
+ "female-construction-worker": ["0x1F477", "0x200D", "0x2640", "0xFE0F"],
+ "male-construction-worker": ["0x1F477", "0x200D", "0x2642", "0xFE0F"],
+ "construction_worker": ["0x1F477"],
+ "princess": ["0x1F478"],
+ "japanese_ogre": ["0x1F479"],
+ "japanese_goblin": ["0x1F47A"],
+ "ghost": ["0x1F47B"],
+ "angel": ["0x1F47C"],
+ "alien": ["0x1F47D"],
+ "space_invader": ["0x1F47E"],
+ "imp": ["0x1F47F"],
+ "skull": ["0x1F480"],
+ "woman-tipping-hand": ["0x1F481", "0x200D", "0x2640", "0xFE0F"],
+ "man-tipping-hand": ["0x1F481", "0x200D", "0x2642", "0xFE0F"],
+ "information_desk_person": ["0x1F481"],
+ "female-guard": ["0x1F482", "0x200D", "0x2640", "0xFE0F"],
+ "male-guard": ["0x1F482", "0x200D", "0x2642", "0xFE0F"],
+ "guardsman": ["0x1F482"],
+ "dancer": ["0x1F483"],
+ "lipstick": ["0x1F484"],
+ "nail_care": ["0x1F485"],
+ "woman-getting-massage": ["0x1F486", "0x200D", "0x2640", "0xFE0F"],
+ "man-getting-massage": ["0x1F486", "0x200D", "0x2642", "0xFE0F"],
+ "massage": ["0x1F486"],
+ "woman-getting-haircut": ["0x1F487", "0x200D", "0x2640", "0xFE0F"],
+ "man-getting-haircut": ["0x1F487", "0x200D", "0x2642", "0xFE0F"],
+ "haircut": ["0x1F487"],
+ "barber": ["0x1F488"],
+ "syringe": ["0x1F489"],
+ "pill": ["0x1F48A"],
+ "kiss": ["0x1F48B"],
+ "love_letter": ["0x1F48C"],
+ "ring": ["0x1F48D"],
+ "gem": ["0x1F48E"],
+ "couplekiss": ["0x1F48F"],
+ "bouquet": ["0x1F490"],
+ "couple_with_heart": ["0x1F491"],
+ "wedding": ["0x1F492"],
+ "heartbeat": ["0x1F493"],
+ "broken_heart": ["0x1F494"],
+ "two_hearts": ["0x1F495"],
+ "sparkling_heart": ["0x1F496"],
+ "heartpulse": ["0x1F497"],
+ "cupid": ["0x1F498"],
+ "blue_heart": ["0x1F499"],
+ "green_heart": ["0x1F49A"],
+ "yellow_heart": ["0x1F49B"],
+ "purple_heart": ["0x1F49C"],
+ "gift_heart": ["0x1F49D"],
+ "revolving_hearts": ["0x1F49E"],
+ "heart_decoration": ["0x1F49F"],
+ "diamond_shape_with_a_dot_inside": ["0x1F4A0"],
+ "bulb": ["0x1F4A1"],
+ "anger": ["0x1F4A2"],
+ "bomb": ["0x1F4A3"],
+ "zzz": ["0x1F4A4"],
+ "boom": ["0x1F4A5"],
+ "sweat_drops": ["0x1F4A6"],
+ "droplet": ["0x1F4A7"],
+ "dash": ["0x1F4A8"],
+ "hankey": ["0x1F4A9"],
+ "muscle": ["0x1F4AA"],
+ "dizzy": ["0x1F4AB"],
+ "speech_balloon": ["0x1F4AC"],
+ "thought_balloon": ["0x1F4AD"],
+ "white_flower": ["0x1F4AE"],
+ "100": ["0x1F4AF"],
+ "moneybag": ["0x1F4B0"],
+ "currency_exchange": ["0x1F4B1"],
+ "heavy_dollar_sign": ["0x1F4B2"],
+ "credit_card": ["0x1F4B3"],
+ "yen": ["0x1F4B4"],
+ "dollar": ["0x1F4B5"],
+ "euro": ["0x1F4B6"],
+ "pound": ["0x1F4B7"],
+ "money_with_wings": ["0x1F4B8"],
+ "chart": ["0x1F4B9"],
+ "seat": ["0x1F4BA"],
+ "computer": ["0x1F4BB"],
+ "briefcase": ["0x1F4BC"],
+ "minidisc": ["0x1F4BD"],
+ "floppy_disk": ["0x1F4BE"],
+ "cd": ["0x1F4BF"],
+ "dvd": ["0x1F4C0"],
+ "file_folder": ["0x1F4C1"],
+ "open_file_folder": ["0x1F4C2"],
+ "page_with_curl": ["0x1F4C3"],
+ "page_facing_up": ["0x1F4C4"],
+ "date": ["0x1F4C5"],
+ "calendar": ["0x1F4C6"],
+ "card_index": ["0x1F4C7"],
+ "chart_with_upwards_trend": ["0x1F4C8"],
+ "chart_with_downwards_trend": ["0x1F4C9"],
+ "bar_chart": ["0x1F4CA"],
+ "clipboard": ["0x1F4CB"],
+ "pushpin": ["0x1F4CC"],
+ "round_pushpin": ["0x1F4CD"],
+ "paperclip": ["0x1F4CE"],
+ "straight_ruler": ["0x1F4CF"],
+ "triangular_ruler": ["0x1F4D0"],
+ "bookmark_tabs": ["0x1F4D1"],
+ "ledger": ["0x1F4D2"],
+ "notebook": ["0x1F4D3"],
+ "notebook_with_decorative_cover": ["0x1F4D4"],
+ "closed_book": ["0x1F4D5"],
+ "book": ["0x1F4D6"],
+ "green_book": ["0x1F4D7"],
+ "blue_book": ["0x1F4D8"],
+ "orange_book": ["0x1F4D9"],
+ "books": ["0x1F4DA"],
+ "name_badge": ["0x1F4DB"],
+ "scroll": ["0x1F4DC"],
+ "memo": ["0x1F4DD"],
+ "telephone_receiver": ["0x1F4DE"],
+ "pager": ["0x1F4DF"],
+ "fax": ["0x1F4E0"],
+ "satellite_antenna": ["0x1F4E1"],
+ "loudspeaker": ["0x1F4E2"],
+ "mega": ["0x1F4E3"],
+ "outbox_tray": ["0x1F4E4"],
+ "inbox_tray": ["0x1F4E5"],
+ "package": ["0x1F4E6"],
+ "e-mail": ["0x1F4E7"],
+ "incoming_envelope": ["0x1F4E8"],
+ "envelope_with_arrow": ["0x1F4E9"],
+ "mailbox_closed": ["0x1F4EA"],
+ "mailbox": ["0x1F4EB"],
+ "mailbox_with_mail": ["0x1F4EC"],
+ "mailbox_with_no_mail": ["0x1F4ED"],
+ "postbox": ["0x1F4EE"],
+ "postal_horn": ["0x1F4EF"],
+ "newspaper": ["0x1F4F0"],
+ "iphone": ["0x1F4F1"],
+ "calling": ["0x1F4F2"],
+ "vibration_mode": ["0x1F4F3"],
+ "mobile_phone_off": ["0x1F4F4"],
+ "no_mobile_phones": ["0x1F4F5"],
+ "signal_strength": ["0x1F4F6"],
+ "camera": ["0x1F4F7"],
+ "camera_with_flash": ["0x1F4F8"],
+ "video_camera": ["0x1F4F9"],
+ "tv": ["0x1F4FA"],
+ "radio": ["0x1F4FB"],
+ "vhs": ["0x1F4FC"],
+ "film_projector": ["0x1F4FD", "0xFE0F"],
+ "prayer_beads": ["0x1F4FF"],
+ "twisted_rightwards_arrows": ["0x1F500"],
+ "repeat": ["0x1F501"],
+ "repeat_one": ["0x1F502"],
+ "arrows_clockwise": ["0x1F503"],
+ "arrows_counterclockwise": ["0x1F504"],
+ "low_brightness": ["0x1F505"],
+ "high_brightness": ["0x1F506"],
+ "mute": ["0x1F507"],
+ "speaker": ["0x1F508"],
+ "sound": ["0x1F509"],
+ "loud_sound": ["0x1F50A"],
+ "battery": ["0x1F50B"],
+ "electric_plug": ["0x1F50C"],
+ "mag": ["0x1F50D"],
+ "mag_right": ["0x1F50E"],
+ "lock_with_ink_pen": ["0x1F50F"],
+ "closed_lock_with_key": ["0x1F510"],
+ "key": ["0x1F511"],
+ "lock": ["0x1F512"],
+ "unlock": ["0x1F513"],
+ "bell": ["0x1F514"],
+ "no_bell": ["0x1F515"],
+ "bookmark": ["0x1F516"],
+ "link": ["0x1F517"],
+ "radio_button": ["0x1F518"],
+ "back": ["0x1F519"],
+ "end": ["0x1F51A"],
+ "on": ["0x1F51B"],
+ "soon": ["0x1F51C"],
+ "top": ["0x1F51D"],
+ "underage": ["0x1F51E"],
+ "keycap_ten": ["0x1F51F"],
+ "capital_abcd": ["0x1F520"],
+ "abcd": ["0x1F521"],
+ "1234": ["0x1F522"],
+ "symbols": ["0x1F523"],
+ "abc": ["0x1F524"],
+ "fire": ["0x1F525"],
+ "flashlight": ["0x1F526"],
+ "wrench": ["0x1F527"],
+ "hammer": ["0x1F528"],
+ "nut_and_bolt": ["0x1F529"],
+ "hocho": ["0x1F52A"],
+ "gun": ["0x1F52B"],
+ "microscope": ["0x1F52C"],
+ "telescope": ["0x1F52D"],
+ "crystal_ball": ["0x1F52E"],
+ "six_pointed_star": ["0x1F52F"],
+ "beginner": ["0x1F530"],
+ "trident": ["0x1F531"],
+ "black_square_button": ["0x1F532"],
+ "white_square_button": ["0x1F533"],
+ "red_circle": ["0x1F534"],
+ "large_blue_circle": ["0x1F535"],
+ "large_orange_diamond": ["0x1F536"],
+ "large_blue_diamond": ["0x1F537"],
+ "small_orange_diamond": ["0x1F538"],
+ "small_blue_diamond": ["0x1F539"],
+ "small_red_triangle": ["0x1F53A"],
+ "small_red_triangle_down": ["0x1F53B"],
+ "arrow_up_small": ["0x1F53C"],
+ "arrow_down_small": ["0x1F53D"],
+ "om_symbol": ["0x1F549", "0xFE0F"],
+ "dove_of_peace": ["0x1F54A", "0xFE0F"],
+ "kaaba": ["0x1F54B"],
+ "mosque": ["0x1F54C"],
+ "synagogue": ["0x1F54D"],
+ "menorah_with_nine_branches": ["0x1F54E"],
+ "clock1": ["0x1F550"],
+ "clock2": ["0x1F551"],
+ "clock3": ["0x1F552"],
+ "clock4": ["0x1F553"],
+ "clock5": ["0x1F554"],
+ "clock6": ["0x1F555"],
+ "clock7": ["0x1F556"],
+ "clock8": ["0x1F557"],
+ "clock9": ["0x1F558"],
+ "clock10": ["0x1F559"],
+ "clock11": ["0x1F55A"],
+ "clock12": ["0x1F55B"],
+ "clock130": ["0x1F55C"],
+ "clock230": ["0x1F55D"],
+ "clock330": ["0x1F55E"],
+ "clock430": ["0x1F55F"],
+ "clock530": ["0x1F560"],
+ "clock630": ["0x1F561"],
+ "clock730": ["0x1F562"],
+ "clock830": ["0x1F563"],
+ "clock930": ["0x1F564"],
+ "clock1030": ["0x1F565"],
+ "clock1130": ["0x1F566"],
+ "clock1230": ["0x1F567"],
+ "candle": ["0x1F56F", "0xFE0F"],
+ "mantelpiece_clock": ["0x1F570", "0xFE0F"],
+ "hole": ["0x1F573", "0xFE0F"],
+ "man_in_business_suit_levitating": ["0x1F574", "0xFE0F"],
+ "female-detective": ["0x1F575", "0xFE0F", "0x200D", "0x2640", "0xFE0F"],
+ "male-detective": ["0x1F575", "0xFE0F", "0x200D", "0x2642", "0xFE0F"],
+ "sleuth_or_spy": ["0x1F575", "0xFE0F"],
+ "dark_sunglasses": ["0x1F576", "0xFE0F"],
+ "spider": ["0x1F577", "0xFE0F"],
+ "spider_web": ["0x1F578", "0xFE0F"],
+ "joystick": ["0x1F579", "0xFE0F"],
+ "man_dancing": ["0x1F57A"],
+ "linked_paperclips": ["0x1F587", "0xFE0F"],
+ "lower_left_ballpoint_pen": ["0x1F58A", "0xFE0F"],
+ "lower_left_fountain_pen": ["0x1F58B", "0xFE0F"],
+ "lower_left_paintbrush": ["0x1F58C", "0xFE0F"],
+ "lower_left_crayon": ["0x1F58D", "0xFE0F"],
+ "raised_hand_with_fingers_splayed": ["0x1F590", "0xFE0F"],
+ "middle_finger": ["0x1F595"],
+ "spock-hand": ["0x1F596"],
+ "black_heart": ["0x1F5A4"],
+ "desktop_computer": ["0x1F5A5", "0xFE0F"],
+ "printer": ["0x1F5A8", "0xFE0F"],
+ "three_button_mouse": ["0x1F5B1", "0xFE0F"],
+ "trackball": ["0x1F5B2", "0xFE0F"],
+ "frame_with_picture": ["0x1F5BC", "0xFE0F"],
+ "card_index_dividers": ["0x1F5C2", "0xFE0F"],
+ "card_file_box": ["0x1F5C3", "0xFE0F"],
+ "file_cabinet": ["0x1F5C4", "0xFE0F"],
+ "wastebasket": ["0x1F5D1", "0xFE0F"],
+ "spiral_note_pad": ["0x1F5D2", "0xFE0F"],
+ "spiral_calendar_pad": ["0x1F5D3", "0xFE0F"],
+ "compression": ["0x1F5DC", "0xFE0F"],
+ "old_key": ["0x1F5DD", "0xFE0F"],
+ "rolled_up_newspaper": ["0x1F5DE", "0xFE0F"],
+ "dagger_knife": ["0x1F5E1", "0xFE0F"],
+ "speaking_head_in_silhouette": ["0x1F5E3", "0xFE0F"],
+ "left_speech_bubble": ["0x1F5E8", "0xFE0F"],
+ "right_anger_bubble": ["0x1F5EF", "0xFE0F"],
+ "ballot_box_with_ballot": ["0x1F5F3", "0xFE0F"],
+ "world_map": ["0x1F5FA", "0xFE0F"],
+ "mount_fuji": ["0x1F5FB"],
+ "tokyo_tower": ["0x1F5FC"],
+ "statue_of_liberty": ["0x1F5FD"],
+ "japan": ["0x1F5FE"],
+ "moyai": ["0x1F5FF"],
+ "grinning": ["0x1F600"],
+ "grin": ["0x1F601"],
+ "joy": ["0x1F602"],
+ "smiley": ["0x1F603"],
+ "smile": ["0x1F604"],
+ "sweat_smile": ["0x1F605"],
+ "laughing": ["0x1F606"],
+ "innocent": ["0x1F607"],
+ "smiling_imp": ["0x1F608"],
+ "wink": ["0x1F609"],
+ "blush": ["0x1F60A"],
+ "yum": ["0x1F60B"],
+ "relieved": ["0x1F60C"],
+ "heart_eyes": ["0x1F60D"],
+ "sunglasses": ["0x1F60E"],
+ "smirk": ["0x1F60F"],
+ "neutral_face": ["0x1F610"],
+ "expressionless": ["0x1F611"],
+ "unamused": ["0x1F612"],
+ "sweat": ["0x1F613"],
+ "pensive": ["0x1F614"],
+ "confused": ["0x1F615"],
+ "confounded": ["0x1F616"],
+ "kissing": ["0x1F617"],
+ "kissing_heart": ["0x1F618"],
+ "kissing_smiling_eyes": ["0x1F619"],
+ "kissing_closed_eyes": ["0x1F61A"],
+ "stuck_out_tongue": ["0x1F61B"],
+ "stuck_out_tongue_winking_eye": ["0x1F61C"],
+ "stuck_out_tongue_closed_eyes": ["0x1F61D"],
+ "disappointed": ["0x1F61E"],
+ "worried": ["0x1F61F"],
+ "angry": ["0x1F620"],
+ "rage": ["0x1F621"],
+ "cry": ["0x1F622"],
+ "persevere": ["0x1F623"],
+ "triumph": ["0x1F624"],
+ "disappointed_relieved": ["0x1F625"],
+ "frowning": ["0x1F626"],
+ "anguished": ["0x1F627"],
+ "fearful": ["0x1F628"],
+ "weary": ["0x1F629"],
+ "sleepy": ["0x1F62A"],
+ "tired_face": ["0x1F62B"],
+ "grimacing": ["0x1F62C"],
+ "sob": ["0x1F62D"],
+ "open_mouth": ["0x1F62E"],
+ "hushed": ["0x1F62F"],
+ "cold_sweat": ["0x1F630"],
+ "scream": ["0x1F631"],
+ "astonished": ["0x1F632"],
+ "flushed": ["0x1F633"],
+ "sleeping": ["0x1F634"],
+ "dizzy_face": ["0x1F635"],
+ "no_mouth": ["0x1F636"],
+ "mask": ["0x1F637"],
+ "smile_cat": ["0x1F638"],
+ "joy_cat": ["0x1F639"],
+ "smiley_cat": ["0x1F63A"],
+ "heart_eyes_cat": ["0x1F63B"],
+ "smirk_cat": ["0x1F63C"],
+ "kissing_cat": ["0x1F63D"],
+ "pouting_cat": ["0x1F63E"],
+ "crying_cat_face": ["0x1F63F"],
+ "scream_cat": ["0x1F640"],
+ "slightly_frowning_face": ["0x1F641"],
+ "slightly_smiling_face": ["0x1F642"],
+ "upside_down_face": ["0x1F643"],
+ "face_with_rolling_eyes": ["0x1F644"],
+ "woman-gesturing-no": ["0x1F645", "0x200D", "0x2640", "0xFE0F"],
+ "man-gesturing-no": ["0x1F645", "0x200D", "0x2642", "0xFE0F"],
+ "no_good": ["0x1F645"],
+ "woman-gesturing-ok": ["0x1F646", "0x200D", "0x2640", "0xFE0F"],
+ "man-gesturing-ok": ["0x1F646", "0x200D", "0x2642", "0xFE0F"],
+ "ok_woman": ["0x1F646"],
+ "woman-bowing": ["0x1F647", "0x200D", "0x2640", "0xFE0F"],
+ "man-bowing": ["0x1F647", "0x200D", "0x2642", "0xFE0F"],
+ "bow": ["0x1F647"],
+ "see_no_evil": ["0x1F648"],
+ "hear_no_evil": ["0x1F649"],
+ "speak_no_evil": ["0x1F64A"],
+ "woman-raising-hand": ["0x1F64B", "0x200D", "0x2640", "0xFE0F"],
+ "man-raising-hand": ["0x1F64B", "0x200D", "0x2642", "0xFE0F"],
+ "raising_hand": ["0x1F64B"],
+ "raised_hands": ["0x1F64C"],
+ "woman-frowning": ["0x1F64D", "0x200D", "0x2640", "0xFE0F"],
+ "man-frowning": ["0x1F64D", "0x200D", "0x2642", "0xFE0F"],
+ "person_frowning": ["0x1F64D"],
+ "woman-pouting": ["0x1F64E", "0x200D", "0x2640", "0xFE0F"],
+ "man-pouting": ["0x1F64E", "0x200D", "0x2642", "0xFE0F"],
+ "person_with_pouting_face": ["0x1F64E"],
+ "pray": ["0x1F64F"],
+ "rocket": ["0x1F680"],
+ "helicopter": ["0x1F681"],
+ "steam_locomotive": ["0x1F682"],
+ "railway_car": ["0x1F683"],
+ "bullettrain_side": ["0x1F684"],
+ "bullettrain_front": ["0x1F685"],
+ "train2": ["0x1F686"],
+ "metro": ["0x1F687"],
+ "light_rail": ["0x1F688"],
+ "station": ["0x1F689"],
+ "tram": ["0x1F68A"],
+ "train": ["0x1F68B"],
+ "bus": ["0x1F68C"],
+ "oncoming_bus": ["0x1F68D"],
+ "trolleybus": ["0x1F68E"],
+ "busstop": ["0x1F68F"],
+ "minibus": ["0x1F690"],
+ "ambulance": ["0x1F691"],
+ "fire_engine": ["0x1F692"],
+ "police_car": ["0x1F693"],
+ "oncoming_police_car": ["0x1F694"],
+ "taxi": ["0x1F695"],
+ "oncoming_taxi": ["0x1F696"],
+ "car": ["0x1F697"],
+ "oncoming_automobile": ["0x1F698"],
+ "blue_car": ["0x1F699"],
+ "truck": ["0x1F69A"],
+ "articulated_lorry": ["0x1F69B"],
+ "tractor": ["0x1F69C"],
+ "monorail": ["0x1F69D"],
+ "mountain_railway": ["0x1F69E"],
+ "suspension_railway": ["0x1F69F"],
+ "mountain_cableway": ["0x1F6A0"],
+ "aerial_tramway": ["0x1F6A1"],
+ "ship": ["0x1F6A2"],
+ "woman-rowing-boat": ["0x1F6A3", "0x200D", "0x2640", "0xFE0F"],
+ "man-rowing-boat": ["0x1F6A3", "0x200D", "0x2642", "0xFE0F"],
+ "rowboat": ["0x1F6A3"],
+ "speedboat": ["0x1F6A4"],
+ "traffic_light": ["0x1F6A5"],
+ "vertical_traffic_light": ["0x1F6A6"],
+ "construction": ["0x1F6A7"],
+ "rotating_light": ["0x1F6A8"],
+ "triangular_flag_on_post": ["0x1F6A9"],
+ "door": ["0x1F6AA"],
+ "no_entry_sign": ["0x1F6AB"],
+ "smoking": ["0x1F6AC"],
+ "no_smoking": ["0x1F6AD"],
+ "put_litter_in_its_place": ["0x1F6AE"],
+ "do_not_litter": ["0x1F6AF"],
+ "potable_water": ["0x1F6B0"],
+ "non-potable_water": ["0x1F6B1"],
+ "bike": ["0x1F6B2"],
+ "no_bicycles": ["0x1F6B3"],
+ "woman-biking": ["0x1F6B4", "0x200D", "0x2640", "0xFE0F"],
+ "man-biking": ["0x1F6B4", "0x200D", "0x2642", "0xFE0F"],
+ "bicyclist": ["0x1F6B4"],
+ "woman-mountain-biking": ["0x1F6B5", "0x200D", "0x2640", "0xFE0F"],
+ "man-mountain-biking": ["0x1F6B5", "0x200D", "0x2642", "0xFE0F"],
+ "mountain_bicyclist": ["0x1F6B5"],
+ "woman-walking": ["0x1F6B6", "0x200D", "0x2640", "0xFE0F"],
+ "man-walking": ["0x1F6B6", "0x200D", "0x2642", "0xFE0F"],
+ "walking": ["0x1F6B6"],
+ "no_pedestrians": ["0x1F6B7"],
+ "children_crossing": ["0x1F6B8"],
+ "mens": ["0x1F6B9"],
+ "womens": ["0x1F6BA"],
+ "restroom": ["0x1F6BB"],
+ "baby_symbol": ["0x1F6BC"],
+ "toilet": ["0x1F6BD"],
+ "wc": ["0x1F6BE"],
+ "shower": ["0x1F6BF"],
+ "bath": ["0x1F6C0"],
+ "bathtub": ["0x1F6C1"],
+ "passport_control": ["0x1F6C2"],
+ "customs": ["0x1F6C3"],
+ "baggage_claim": ["0x1F6C4"],
+ "left_luggage": ["0x1F6C5"],
+ "couch_and_lamp": ["0x1F6CB", "0xFE0F"],
+ "sleeping_accommodation": ["0x1F6CC"],
+ "shopping_bags": ["0x1F6CD", "0xFE0F"],
+ "bellhop_bell": ["0x1F6CE", "0xFE0F"],
+ "bed": ["0x1F6CF", "0xFE0F"],
+ "place_of_worship": ["0x1F6D0"],
+ "octagonal_sign": ["0x1F6D1"],
+ "shopping_trolley": ["0x1F6D2"],
+ "hammer_and_wrench": ["0x1F6E0", "0xFE0F"],
+ "shield": ["0x1F6E1", "0xFE0F"],
+ "oil_drum": ["0x1F6E2", "0xFE0F"],
+ "motorway": ["0x1F6E3", "0xFE0F"],
+ "railway_track": ["0x1F6E4", "0xFE0F"],
+ "motor_boat": ["0x1F6E5", "0xFE0F"],
+ "small_airplane": ["0x1F6E9", "0xFE0F"],
+ "airplane_departure": ["0x1F6EB"],
+ "airplane_arriving": ["0x1F6EC"],
+ "satellite": ["0x1F6F0", "0xFE0F"],
+ "passenger_ship": ["0x1F6F3", "0xFE0F"],
+ "scooter": ["0x1F6F4"],
+ "motor_scooter": ["0x1F6F5"],
+ "canoe": ["0x1F6F6"],
+ "sled": ["0x1F6F7"],
+ "flying_saucer": ["0x1F6F8"],
+ "zipper_mouth_face": ["0x1F910"],
+ "money_mouth_face": ["0x1F911"],
+ "face_with_thermometer": ["0x1F912"],
+ "nerd_face": ["0x1F913"],
+ "thinking_face": ["0x1F914"],
+ "face_with_head_bandage": ["0x1F915"],
+ "robot_face": ["0x1F916"],
+ "hugging_face": ["0x1F917"],
+ "the_horns": ["0x1F918"],
+ "call_me_hand": ["0x1F919"],
+ "raised_back_of_hand": ["0x1F91A"],
+ "left-facing_fist": ["0x1F91B"],
+ "right-facing_fist": ["0x1F91C"],
+ "handshake": ["0x1F91D"],
+ "crossed_fingers": ["0x1F91E"],
+ "i_love_you_hand_sign": ["0x1F91F"],
+ "face_with_cowboy_hat": ["0x1F920"],
+ "clown_face": ["0x1F921"],
+ "nauseated_face": ["0x1F922"],
+ "rolling_on_the_floor_laughing": ["0x1F923"],
+ "drooling_face": ["0x1F924"],
+ "lying_face": ["0x1F925"],
+ "woman-facepalming": ["0x1F926", "0x200D", "0x2640", "0xFE0F"],
+ "man-facepalming": ["0x1F926", "0x200D", "0x2642", "0xFE0F"],
+ "face_palm": ["0x1F926"],
+ "sneezing_face": ["0x1F927"],
+ "face_with_raised_eyebrow": ["0x1F928"],
+ "star-struck": ["0x1F929"],
+ "zany_face": ["0x1F92A"],
+ "shushing_face": ["0x1F92B"],
+ "face_with_symbols_on_mouth": ["0x1F92C"],
+ "face_with_hand_over_mouth": ["0x1F92D"],
+ "face_vomiting": ["0x1F92E"],
+ "exploding_head": ["0x1F92F"],
+ "pregnant_woman": ["0x1F930"],
+ "breast-feeding": ["0x1F931"],
+ "palms_up_together": ["0x1F932"],
+ "selfie": ["0x1F933"],
+ "prince": ["0x1F934"],
+ "man_in_tuxedo": ["0x1F935"],
+ "mrs_claus": ["0x1F936"],
+ "woman-shrugging": ["0x1F937", "0x200D", "0x2640", "0xFE0F"],
+ "man-shrugging": ["0x1F937", "0x200D", "0x2642", "0xFE0F"],
+ "shrug": ["0x1F937"],
+ "woman-cartwheeling": ["0x1F938", "0x200D", "0x2640", "0xFE0F"],
+ "man-cartwheeling": ["0x1F938", "0x200D", "0x2642", "0xFE0F"],
+ "person_doing_cartwheel": ["0x1F938"],
+ "woman-juggling": ["0x1F939", "0x200D", "0x2640", "0xFE0F"],
+ "man-juggling": ["0x1F939", "0x200D", "0x2642", "0xFE0F"],
+ "juggling": ["0x1F939"],
+ "fencer": ["0x1F93A"],
+ "woman-wrestling": ["0x1F93C", "0x200D", "0x2640", "0xFE0F"],
+ "man-wrestling": ["0x1F93C", "0x200D", "0x2642", "0xFE0F"],
+ "wrestlers": ["0x1F93C"],
+ "woman-playing-water-polo": ["0x1F93D", "0x200D", "0x2640", "0xFE0F"],
+ "man-playing-water-polo": ["0x1F93D", "0x200D", "0x2642", "0xFE0F"],
+ "water_polo": ["0x1F93D"],
+ "woman-playing-handball": ["0x1F93E", "0x200D", "0x2640", "0xFE0F"],
+ "man-playing-handball": ["0x1F93E", "0x200D", "0x2642", "0xFE0F"],
+ "handball": ["0x1F93E"],
+ "wilted_flower": ["0x1F940"],
+ "drum_with_drumsticks": ["0x1F941"],
+ "clinking_glasses": ["0x1F942"],
+ "tumbler_glass": ["0x1F943"],
+ "spoon": ["0x1F944"],
+ "goal_net": ["0x1F945"],
+ "first_place_medal": ["0x1F947"],
+ "second_place_medal": ["0x1F948"],
+ "third_place_medal": ["0x1F949"],
+ "boxing_glove": ["0x1F94A"],
+ "martial_arts_uniform": ["0x1F94B"],
+ "curling_stone": ["0x1F94C"],
+ "croissant": ["0x1F950"],
+ "avocado": ["0x1F951"],
+ "cucumber": ["0x1F952"],
+ "bacon": ["0x1F953"],
+ "potato": ["0x1F954"],
+ "carrot": ["0x1F955"],
+ "baguette_bread": ["0x1F956"],
+ "green_salad": ["0x1F957"],
+ "shallow_pan_of_food": ["0x1F958"],
+ "stuffed_flatbread": ["0x1F959"],
+ "egg": ["0x1F95A"],
+ "glass_of_milk": ["0x1F95B"],
+ "peanuts": ["0x1F95C"],
+ "kiwifruit": ["0x1F95D"],
+ "pancakes": ["0x1F95E"],
+ "dumpling": ["0x1F95F"],
+ "fortune_cookie": ["0x1F960"],
+ "takeout_box": ["0x1F961"],
+ "chopsticks": ["0x1F962"],
+ "bowl_with_spoon": ["0x1F963"],
+ "cup_with_straw": ["0x1F964"],
+ "coconut": ["0x1F965"],
+ "broccoli": ["0x1F966"],
+ "pie": ["0x1F967"],
+ "pretzel": ["0x1F968"],
+ "cut_of_meat": ["0x1F969"],
+ "sandwich": ["0x1F96A"],
+ "canned_food": ["0x1F96B"],
+ "crab": ["0x1F980"],
+ "lion_face": ["0x1F981"],
+ "scorpion": ["0x1F982"],
+ "turkey": ["0x1F983"],
+ "unicorn_face": ["0x1F984"],
+ "eagle": ["0x1F985"],
+ "duck": ["0x1F986"],
+ "bat": ["0x1F987"],
+ "shark": ["0x1F988"],
+ "owl": ["0x1F989"],
+ "fox_face": ["0x1F98A"],
+ "butterfly": ["0x1F98B"],
+ "deer": ["0x1F98C"],
+ "gorilla": ["0x1F98D"],
+ "lizard": ["0x1F98E"],
+ "rhinoceros": ["0x1F98F"],
+ "shrimp": ["0x1F990"],
+ "squid": ["0x1F991"],
+ "giraffe_face": ["0x1F992"],
+ "zebra_face": ["0x1F993"],
+ "hedgehog": ["0x1F994"],
+ "sauropod": ["0x1F995"],
+ "t-rex": ["0x1F996"],
+ "cricket": ["0x1F997"],
+ "cheese_wedge": ["0x1F9C0"],
+ "face_with_monocle": ["0x1F9D0"],
+ "adult": ["0x1F9D1"],
+ "child": ["0x1F9D2"],
+ "older_adult": ["0x1F9D3"],
+ "bearded_person": ["0x1F9D4"],
+ "person_with_headscarf": ["0x1F9D5"],
+ "woman_in_steamy_room": ["0x1F9D6", "0x200D", "0x2640", "0xFE0F"],
+ "man_in_steamy_room": ["0x1F9D6", "0x200D", "0x2642", "0xFE0F"],
+ "person_in_steamy_room": ["0x1F9D6"],
+ "woman_climbing": ["0x1F9D7", "0x200D", "0x2640", "0xFE0F"],
+ "man_climbing": ["0x1F9D7", "0x200D", "0x2642", "0xFE0F"],
+ "person_climbing": ["0x1F9D7"],
+ "woman_in_lotus_position": ["0x1F9D8", "0x200D", "0x2640", "0xFE0F"],
+ "man_in_lotus_position": ["0x1F9D8", "0x200D", "0x2642", "0xFE0F"],
+ "person_in_lotus_position": ["0x1F9D8"],
+ "female_mage": ["0x1F9D9", "0x200D", "0x2640", "0xFE0F"],
+ "male_mage": ["0x1F9D9", "0x200D", "0x2642", "0xFE0F"],
+ "mage": ["0x1F9D9"],
+ "female_fairy": ["0x1F9DA", "0x200D", "0x2640", "0xFE0F"],
+ "male_fairy": ["0x1F9DA", "0x200D", "0x2642", "0xFE0F"],
+ "fairy": ["0x1F9DA"],
+ "female_vampire": ["0x1F9DB", "0x200D", "0x2640", "0xFE0F"],
+ "male_vampire": ["0x1F9DB", "0x200D", "0x2642", "0xFE0F"],
+ "vampire": ["0x1F9DB"],
+ "mermaid": ["0x1F9DC", "0x200D", "0x2640", "0xFE0F"],
+ "merman": ["0x1F9DC", "0x200D", "0x2642", "0xFE0F"],
+ "merperson": ["0x1F9DC"],
+ "female_elf": ["0x1F9DD", "0x200D", "0x2640", "0xFE0F"],
+ "male_elf": ["0x1F9DD", "0x200D", "0x2642", "0xFE0F"],
+ "elf": ["0x1F9DD"],
+ "female_genie": ["0x1F9DE", "0x200D", "0x2640", "0xFE0F"],
+ "male_genie": ["0x1F9DE", "0x200D", "0x2642", "0xFE0F"],
+ "genie": ["0x1F9DE"],
+ "female_zombie": ["0x1F9DF", "0x200D", "0x2640", "0xFE0F"],
+ "male_zombie": ["0x1F9DF", "0x200D", "0x2642", "0xFE0F"],
+ "zombie": ["0x1F9DF"],
+ "brain": ["0x1F9E0"],
+ "orange_heart": ["0x1F9E1"],
+ "billed_cap": ["0x1F9E2"],
+ "scarf": ["0x1F9E3"],
+ "gloves": ["0x1F9E4"],
+ "coat": ["0x1F9E5"],
+ "socks": ["0x1F9E6"],
+ "bangbang": ["0x203C", "0xFE0F"],
+ "interrobang": ["0x2049", "0xFE0F"],
+ "tm": ["0x2122", "0xFE0F"],
+ "information_source": ["0x2139", "0xFE0F"],
+ "left_right_arrow": ["0x2194", "0xFE0F"],
+ "arrow_up_down": ["0x2195", "0xFE0F"],
+ "arrow_upper_left": ["0x2196", "0xFE0F"],
+ "arrow_upper_right": ["0x2197", "0xFE0F"],
+ "arrow_lower_right": ["0x2198", "0xFE0F"],
+ "arrow_lower_left": ["0x2199", "0xFE0F"],
+ "leftwards_arrow_with_hook": ["0x21A9", "0xFE0F"],
+ "arrow_right_hook": ["0x21AA", "0xFE0F"],
+ "watch": ["0x231A"],
+ "hourglass": ["0x231B"],
+ "keyboard": ["0x2328", "0xFE0F"],
+ "eject": ["0x23CF", "0xFE0F"],
+ "fast_forward": ["0x23E9"],
+ "rewind": ["0x23EA"],
+ "arrow_double_up": ["0x23EB"],
+ "arrow_double_down": ["0x23EC"],
+ "black_right_pointing_double_triangle_with_vertical_bar": ["0x23ED", "0xFE0F"],
+ "black_left_pointing_double_triangle_with_vertical_bar": ["0x23EE", "0xFE0F"],
+ "black_right_pointing_triangle_with_double_vertical_bar": ["0x23EF", "0xFE0F"],
+ "alarm_clock": ["0x23F0"],
+ "stopwatch": ["0x23F1", "0xFE0F"],
+ "timer_clock": ["0x23F2", "0xFE0F"],
+ "hourglass_flowing_sand": ["0x23F3"],
+ "double_vertical_bar": ["0x23F8", "0xFE0F"],
+ "black_square_for_stop": ["0x23F9", "0xFE0F"],
+ "black_circle_for_record": ["0x23FA", "0xFE0F"],
+ "m": ["0x24C2", "0xFE0F"],
+ "black_small_square": ["0x25AA", "0xFE0F"],
+ "white_small_square": ["0x25AB", "0xFE0F"],
+ "arrow_forward": ["0x25B6", "0xFE0F"],
+ "arrow_backward": ["0x25C0", "0xFE0F"],
+ "white_medium_square": ["0x25FB", "0xFE0F"],
+ "black_medium_square": ["0x25FC", "0xFE0F"],
+ "white_medium_small_square": ["0x25FD"],
+ "black_medium_small_square": ["0x25FE"],
+ "sunny": ["0x2600", "0xFE0F"],
+ "cloud": ["0x2601", "0xFE0F"],
+ "umbrella": ["0x2602", "0xFE0F"],
+ "snowman": ["0x2603", "0xFE0F"],
+ "comet": ["0x2604", "0xFE0F"],
+ "phone": ["0x260E", "0xFE0F"],
+ "ballot_box_with_check": ["0x2611", "0xFE0F"],
+ "umbrella_with_rain_drops": ["0x2614"],
+ "coffee": ["0x2615"],
+ "shamrock": ["0x2618", "0xFE0F"],
+ "point_up": ["0x261D", "0xFE0F"],
+ "skull_and_crossbones": ["0x2620", "0xFE0F"],
+ "radioactive_sign": ["0x2622", "0xFE0F"],
+ "biohazard_sign": ["0x2623", "0xFE0F"],
+ "orthodox_cross": ["0x2626", "0xFE0F"],
+ "star_and_crescent": ["0x262A", "0xFE0F"],
+ "peace_symbol": ["0x262E", "0xFE0F"],
+ "yin_yang": ["0x262F", "0xFE0F"],
+ "wheel_of_dharma": ["0x2638", "0xFE0F"],
+ "white_frowning_face": ["0x2639", "0xFE0F"],
+ "relaxed": ["0x263A", "0xFE0F"],
+ "female_sign": ["0x2640", "0xFE0F"],
+ "male_sign": ["0x2642", "0xFE0F"],
+ "aries": ["0x2648"],
+ "taurus": ["0x2649"],
+ "gemini": ["0x264A"],
+ "cancer": ["0x264B"],
+ "leo": ["0x264C"],
+ "virgo": ["0x264D"],
+ "libra": ["0x264E"],
+ "scorpius": ["0x264F"],
+ "sagittarius": ["0x2650"],
+ "capricorn": ["0x2651"],
+ "aquarius": ["0x2652"],
+ "pisces": ["0x2653"],
+ "spades": ["0x2660", "0xFE0F"],
+ "clubs": ["0x2663", "0xFE0F"],
+ "hearts": ["0x2665", "0xFE0F"],
+ "diamonds": ["0x2666", "0xFE0F"],
+ "hotsprings": ["0x2668", "0xFE0F"],
+ "recycle": ["0x267B", "0xFE0F"],
+ "wheelchair": ["0x267F"],
+ "hammer_and_pick": ["0x2692", "0xFE0F"],
+ "anchor": ["0x2693"],
+ "crossed_swords": ["0x2694", "0xFE0F"],
+ "medical_symbol": ["0x2695", "0xFE0F"],
+ "scales": ["0x2696", "0xFE0F"],
+ "alembic": ["0x2697", "0xFE0F"],
+ "gear": ["0x2699", "0xFE0F"],
+ "atom_symbol": ["0x269B", "0xFE0F"],
+ "fleur_de_lis": ["0x269C", "0xFE0F"],
+ "warning": ["0x26A0", "0xFE0F"],
+ "zap": ["0x26A1"],
+ "white_circle": ["0x26AA"],
+ "black_circle": ["0x26AB"],
+ "coffin": ["0x26B0", "0xFE0F"],
+ "funeral_urn": ["0x26B1", "0xFE0F"],
+ "soccer": ["0x26BD"],
+ "baseball": ["0x26BE"],
+ "snowman_without_snow": ["0x26C4"],
+ "partly_sunny": ["0x26C5"],
+ "thunder_cloud_and_rain": ["0x26C8", "0xFE0F"],
+ "ophiuchus": ["0x26CE"],
+ "pick": ["0x26CF", "0xFE0F"],
+ "helmet_with_white_cross": ["0x26D1", "0xFE0F"],
+ "chains": ["0x26D3", "0xFE0F"],
+ "no_entry": ["0x26D4"],
+ "shinto_shrine": ["0x26E9", "0xFE0F"],
+ "church": ["0x26EA"],
+ "mountain": ["0x26F0", "0xFE0F"],
+ "umbrella_on_ground": ["0x26F1", "0xFE0F"],
+ "fountain": ["0x26F2"],
+ "golf": ["0x26F3"],
+ "ferry": ["0x26F4", "0xFE0F"],
+ "boat": ["0x26F5"],
+ "skier": ["0x26F7", "0xFE0F"],
+ "ice_skate": ["0x26F8", "0xFE0F"],
+ "woman-bouncing-ball": ["0x26F9", "0xFE0F", "0x200D", "0x2640", "0xFE0F"],
+ "man-bouncing-ball": ["0x26F9", "0xFE0F", "0x200D", "0x2642", "0xFE0F"],
+ "person_with_ball": ["0x26F9", "0xFE0F"],
+ "tent": ["0x26FA"],
+ "fuelpump": ["0x26FD"],
+ "scissors": ["0x2702", "0xFE0F"],
+ "white_check_mark": ["0x2705"],
+ "airplane": ["0x2708", "0xFE0F"],
+ "email": ["0x2709", "0xFE0F"],
+ "fist": ["0x270A"],
+ "hand": ["0x270B"],
+ "v": ["0x270C", "0xFE0F"],
+ "writing_hand": ["0x270D", "0xFE0F"],
+ "pencil2": ["0x270F", "0xFE0F"],
+ "black_nib": ["0x2712", "0xFE0F"],
+ "heavy_check_mark": ["0x2714", "0xFE0F"],
+ "heavy_multiplication_x": ["0x2716", "0xFE0F"],
+ "latin_cross": ["0x271D", "0xFE0F"],
+ "star_of_david": ["0x2721", "0xFE0F"],
+ "sparkles": ["0x2728"],
+ "eight_spoked_asterisk": ["0x2733", "0xFE0F"],
+ "eight_pointed_black_star": ["0x2734", "0xFE0F"],
+ "snowflake": ["0x2744", "0xFE0F"],
+ "sparkle": ["0x2747", "0xFE0F"],
+ "x": ["0x274C"],
+ "negative_squared_cross_mark": ["0x274E"],
+ "question": ["0x2753"],
+ "grey_question": ["0x2754"],
+ "grey_exclamation": ["0x2755"],
+ "exclamation": ["0x2757"],
+ "heavy_heart_exclamation_mark_ornament": ["0x2763", "0xFE0F"],
+ "heart": ["0x2764", "0xFE0F"],
+ "heavy_plus_sign": ["0x2795"],
+ "heavy_minus_sign": ["0x2796"],
+ "heavy_division_sign": ["0x2797"],
+ "arrow_right": ["0x27A1", "0xFE0F"],
+ "curly_loop": ["0x27B0"],
+ "loop": ["0x27BF"],
+ "arrow_heading_up": ["0x2934", "0xFE0F"],
+ "arrow_heading_down": ["0x2935", "0xFE0F"],
+ "arrow_left": ["0x2B05", "0xFE0F"],
+ "arrow_up": ["0x2B06", "0xFE0F"],
+ "arrow_down": ["0x2B07", "0xFE0F"],
+ "black_large_square": ["0x2B1B"],
+ "white_large_square": ["0x2B1C"],
+ "star": ["0x2B50"],
+ "o": ["0x2B55"],
+ "wavy_dash": ["0x3030", "0xFE0F"],
+ "part_alternation_mark": ["0x303D", "0xFE0F"],
+ "congratulations": ["0x3297", "0xFE0F"],
+ "secret": ["0x3299", "0xFE0F"]
+}
diff --git a/demo/form/index.css b/demo/form/index.css
new file mode 100644
index 0000000..2f10030
--- /dev/null
+++ b/demo/form/index.css
@@ -0,0 +1,31 @@
+p {
+ max-width: 50ch;
+}
+
+fieldset {
+ width: min-content;
+}
+label {
+ display: block;
+ white-space: nowrap;
+ width: min-content;
+}
+label + label {
+ margin-top: 4px;
+}
+
+input {
+ display: block;
+}
+
+#submit {
+ margin-top: 8px;
+}
+
+form-control {
+ position: relative;
+ z-index: 0;
+}
+form-control:focus-within {
+ z-index: 1;
+}
diff --git a/demo/form/index.html b/demo/form/index.html
new file mode 100644
index 0000000..8661cef
--- /dev/null
+++ b/demo/form/index.html
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+ This demonstrates what it currently looks like to build a Form-Associated
+ Custom Element via x-element.
+
+
+
+
+
diff --git a/demo/form/index.js b/demo/form/index.js
new file mode 100644
index 0000000..6bfefa3
--- /dev/null
+++ b/demo/form/index.js
@@ -0,0 +1,13 @@
+const form = document.getElementById('form');
+
+form.addEventListener('submit', event => {
+ event.preventDefault();
+ const formData = new FormData(form);
+ const entries = [...formData.entries()];
+ console.log(entries); // eslint-disable-line no-console
+});
+
+// TODO: This doesn’t appear to be working just yet.
+// form.addEventListener('formdata', event => {
+// console.log([...event.formData.entries()]);
+// });
diff --git a/demo/index.html b/demo/index.html
index bf1eafb..9bb0628 100644
--- a/demo/index.html
+++ b/demo/index.html
@@ -15,6 +15,7 @@ A dead simple starting point for custom elements.
integrating with lit-html
integrating with µhtml
wrapping in react
+ form-associated custom elements
run tests
performance
diff --git a/doc/FORMS.md b/doc/FORMS.md
new file mode 100644
index 0000000..40e5b22
--- /dev/null
+++ b/doc/FORMS.md
@@ -0,0 +1,99 @@
+# Forms
+
+Both templating and managing custom form elements are different-enough from
+normal development flows that they warrant their own dedicated documentation.
+
+## What’s so different about forms?
+
+Here are a few topics which will come up throughout the document. And, it’s
+worth noting that “yes” forms are often nuanced and complex — but they are also
+incredibly powerful and designed with accessibility in mind. I.e., they’re worth
+understanding and implementing right!
+
+* [Form-Associated Custom Elements][FACE] (FACE).
+* [Element Internals][ElementInternals] (`attachInternals`).
+* Controls have to be in the form’s light DOM.
+* Timing issues related to `change` / `submit` and a control’s value need to
+ be considered.
+* There are two sources-of-truth to contend with. DOM vs. application state.
+* Form apis tend to either be imperative, or introspective (vs. declarative).
+* Attribute-to-property syncing is often, unexpectedly asymmetric.
+* Values, default values, and resetting can take finesse.
+* In general, you may need _very_ tight control.
+
+## Form-Associated Custom Element primer
+
+TODO: NOT SURE IF THIS IS THE RIGHT DIRECTION TO GO IN.
+
+Let’s just make a “simple” form control that wraps a checkbox to make a
+fancy-looking toggle.
+
+```js
+// TODO: Should we wrap an input? Or, just build one from scratch? Maybe the
+// latter is actually more interesting?
+class ToggleInput extends XElement {
+ // Instruct the browser that this element can participate in a form. This is a
+ // native browser flag.
+ static formAssociated = true;
+
+ // Instruct x-element to re-render DOM _as soon_ as properties change. This is
+ // not performant, but is often a requirement to get nuanced form-control
+ // timing just right.
+ static experimentalSynchronousRender = true;
+
+ // Write up our encapsulated CSS to make a track and a thumb.
+ static get styles() {
+ const text = `\
+ :host { display: inline; }
+ #input {}
+ #input::before {}
+ #input::after {}
+ `;
+ const styleSheet = new CSSStyleSheet();
+ styleSheet.replaceSync(text);
+ return [styleSheet];
+ };
+
+ // TODO: Demonstrate how default values need to work?
+ // Set up our interface.
+ static get properties() {
+ return {
+ on: { type: Boolean }, // Note that re-entrance will happen here!
+ onValue: { type: String, default: '' },
+ offValue: { type: String, default: '' },
+ value: {
+ type: String,
+ input: ['on', 'onValue', 'offValue'],
+ compute: (on, onValue, offValue) => on ? onValue : offValue,
+ },
+ };
+ }
+
+ // Listen for change events and synchronously re-bind values.
+ static get listeners() {
+ return {
+ change: (host, event) => {
+ host.on = event.target.checked;
+ }
+ }
+ }
+
+ // Render out a native checkbox so we can piggy-back off native functionality
+ // like apis, validity, css selectors, etc.
+ static template(html) {
+ return ({ on }) => {
+ return html` `;
+ }
+ }
+}
+```
+
+## References
+
+* [Form-Associated Custom Elements][FACE]
+* [Element Internals][ElementInternals]
+* [More capable form controls (web.dev)][web.dev article]
+
+[web.dev article]: https://web.dev/articles/more-capable-form-controls
+[FACE]: https://html.spec.whatwg.org/dev/custom-elements.html#custom-elements-face-example
+[ElementInternals]: https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals
diff --git a/x-element.js b/x-element.js
index bc5ff8a..91ab5c7 100644
--- a/x-element.js
+++ b/x-element.js
@@ -121,6 +121,11 @@ export default class XElement extends HTMLElement {
return {};
}
+ // TODO: Not sure if we want to expose this sort of thing.
+ static get experimentalSynchronousRender() {
+ return false;
+ }
+
/**
* Customize shadow root initialization and optionally forgo encapsulation.
* E.g., setup focus delegation or return host instead of host.shadowRoot.
@@ -297,7 +302,7 @@ export default class XElement extends HTMLElement {
// Called once per class — kicked off from "static get observedAttributes".
static #analyzeConstructor(constructor) {
- const { styles, properties, listeners } = constructor;
+ const { styles, properties, listeners, experimentalSynchronousRender } = constructor;
const propertiesEntries = Object.entries(properties);
const listenersEntries = Object.entries(listeners);
XElement.#validateProperties(constructor, properties, propertiesEntries);
@@ -323,7 +328,7 @@ export default class XElement extends HTMLElement {
const listenerMap = new Map(listenersEntries);
XElement.#constructors.set(constructor, {
styles, propertyMap, internalPropertyMap, attributeMap, listenerMap,
- propertiesTarget, internalTarget,
+ propertiesTarget, internalTarget, experimentalSynchronousRender,
});
}
@@ -634,7 +639,7 @@ export default class XElement extends HTMLElement {
const computeMap = new Map();
const observeMap = new Map();
const defaultMap = new Map();
- const { styles, propertyMap } = XElement.#constructors.get(host.constructor);
+ const { styles, propertyMap, experimentalSynchronousRender } = XElement.#constructors.get(host.constructor);
if (styles.length > 0) {
if (renderRoot === host.shadowRoot) {
if (renderRoot.adoptedStyleSheets.length === 0) {
@@ -657,7 +662,7 @@ export default class XElement extends HTMLElement {
XElement.#hosts.set(host, {
initialized: false, reflecting: false, invalidProperties, listenerMap,
renderRoot, render, template, properties, internal, computeMap,
- observeMap, defaultMap, valueMap,
+ observeMap, defaultMap, valueMap, experimentalSynchronousRender,
});
}
@@ -898,21 +903,34 @@ export default class XElement extends HTMLElement {
.join(' < ');
}
- static async #invalidateProperty(host, property) {
- const { initialized, invalidProperties, computeMap } = XElement.#hosts.get(host);
+ static async #invalidateProperty(host, property, skipUpdate) {
+ const { initialized, invalidProperties, computeMap, experimentalSynchronousRender } = XElement.#hosts.get(host);
if (initialized) {
- for (const output of property.output) {
- XElement.#invalidateProperty(host, output);
- }
- const queueUpdate = invalidProperties.size === 0;
- invalidProperties.add(property);
- if (property.compute) {
- computeMap.get(property).valid = false;
- }
- if (queueUpdate) {
- // Queue a microtask. Allows multiple, synchronous changes.
- await Promise.resolve();
- XElement.#updateHost(host);
+ if (experimentalSynchronousRender) {
+ for (const output of property.output) {
+ XElement.#invalidateProperty(host, output, true);
+ }
+ invalidProperties.add(property);
+ if (property.compute) {
+ computeMap.get(property).valid = false;
+ }
+ if (!skipUpdate) {
+ XElement.#updateHost(host);
+ }
+ } else {
+ for (const output of property.output) {
+ XElement.#invalidateProperty(host, output);
+ }
+ const queueUpdate = invalidProperties.size === 0;
+ invalidProperties.add(property);
+ if (property.compute) {
+ computeMap.get(property).valid = false;
+ }
+ if (queueUpdate) {
+ // Queue a microtask. Allows multiple, synchronous changes.
+ await Promise.resolve();
+ XElement.#updateHost(host);
+ }
}
}
}